summaryrefslogtreecommitdiff
path: root/boost
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2016-10-06 10:38:45 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2016-10-06 10:39:52 +0900
commit5cde13f21d36c7224b0e13d11c4b49379ae5210d (patch)
treee8269ac85a4b0f7d416e2565fa4f451b5cb41351 /boost
parentd9ec475d945d3035377a0d89ed42e382d8988891 (diff)
downloadboost-5cde13f21d36c7224b0e13d11c4b49379ae5210d.tar.gz
boost-5cde13f21d36c7224b0e13d11c4b49379ae5210d.tar.bz2
boost-5cde13f21d36c7224b0e13d11c4b49379ae5210d.zip
Imported Upstream version 1.61.0
Change-Id: I96a1f878d1e6164f01e9aadd5147f38fca448d90 Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'boost')
-rw-r--r--boost/align.hpp2
-rw-r--r--boost/align/align.hpp2
-rw-r--r--boost/align/align_down.hpp27
-rw-r--r--boost/align/align_down_forward.hpp24
-rw-r--r--boost/align/align_up.hpp27
-rw-r--r--boost/align/align_up_forward.hpp24
-rw-r--r--boost/align/aligned_alloc.hpp6
-rw-r--r--boost/align/aligned_allocator.hpp45
-rw-r--r--boost/align/aligned_allocator_adaptor.hpp57
-rw-r--r--boost/align/aligned_delete.hpp6
-rw-r--r--boost/align/aligned_delete_forward.hpp4
-rw-r--r--boost/align/alignment_of.hpp13
-rw-r--r--boost/align/detail/address.hpp29
-rw-r--r--boost/align/detail/align.hpp24
-rw-r--r--boost/align/detail/align_down.hpp29
-rw-r--r--boost/align/detail/align_up.hpp29
-rw-r--r--boost/align/detail/aligned_alloc.hpp30
-rw-r--r--boost/align/detail/aligned_alloc_android.hpp4
-rw-r--r--boost/align/detail/aligned_alloc_macos.hpp4
-rw-r--r--boost/align/detail/aligned_alloc_msvc.hpp4
-rw-r--r--boost/align/detail/aligned_alloc_posix.hpp4
-rw-r--r--boost/align/detail/aligned_alloc_sunos.hpp4
-rw-r--r--boost/align/detail/assume_aligned.hpp2
-rw-r--r--boost/align/detail/assume_aligned_clang.hpp6
-rw-r--r--boost/align/detail/assume_aligned_gcc.hpp4
-rw-r--r--boost/align/detail/assume_aligned_intel.hpp4
-rw-r--r--boost/align/detail/assume_aligned_msvc.hpp6
-rw-r--r--boost/align/detail/element_type.hpp (renamed from boost/align/detail/remove_traits.hpp)26
-rw-r--r--boost/align/detail/is_aligned.hpp15
-rw-r--r--boost/align/detail/max_align.hpp1
-rw-r--r--boost/align/is_aligned.hpp13
-rw-r--r--boost/align/is_aligned_forward.hpp24
-rw-r--r--boost/archive/add_facet.hpp55
-rw-r--r--boost/archive/basic_binary_iprimitive.hpp20
-rw-r--r--boost/archive/basic_binary_oprimitive.hpp25
-rw-r--r--boost/archive/basic_streambuf_locale_saver.hpp63
-rw-r--r--boost/archive/basic_text_iprimitive.hpp25
-rw-r--r--boost/archive/basic_text_oprimitive.hpp21
-rw-r--r--boost/archive/basic_xml_iarchive.hpp24
-rw-r--r--boost/archive/basic_xml_oarchive.hpp31
-rw-r--r--boost/archive/binary_iarchive_impl.hpp5
-rw-r--r--boost/archive/binary_oarchive_impl.hpp5
-rw-r--r--boost/archive/codecvt_null.hpp4
-rw-r--r--boost/archive/detail/basic_serializer.hpp4
-rw-r--r--boost/archive/detail/common_iarchive.hpp2
-rw-r--r--boost/archive/detail/common_oarchive.hpp3
-rw-r--r--boost/archive/detail/decl.hpp4
-rw-r--r--boost/archive/detail/iserializer.hpp14
-rw-r--r--boost/archive/detail/oserializer.hpp1
-rw-r--r--boost/archive/detail/utf8_codecvt_facet.hpp17
-rw-r--r--boost/archive/impl/basic_binary_iprimitive.ipp53
-rw-r--r--boost/archive/impl/basic_binary_oprimitive.ipp50
-rw-r--r--boost/archive/impl/basic_text_iprimitive.ipp29
-rw-r--r--boost/archive/impl/basic_text_oprimitive.ipp32
-rw-r--r--boost/archive/impl/basic_xml_grammar.hpp2
-rw-r--r--boost/archive/impl/basic_xml_iarchive.ipp3
-rw-r--r--boost/archive/impl/basic_xml_oarchive.ipp18
-rw-r--r--boost/archive/impl/text_oarchive_impl.ipp2
-rw-r--r--boost/archive/impl/xml_iarchive_impl.ipp24
-rw-r--r--boost/archive/impl/xml_oarchive_impl.ipp25
-rw-r--r--boost/archive/impl/xml_wiarchive_impl.ipp28
-rw-r--r--boost/archive/impl/xml_woarchive_impl.ipp44
-rw-r--r--boost/archive/iterators/dataflow.hpp1
-rw-r--r--boost/archive/iterators/istream_iterator.hpp15
-rw-r--r--boost/archive/iterators/mb_from_wchar.hpp32
-rw-r--r--boost/archive/iterators/wchar_from_mb.hpp144
-rw-r--r--boost/archive/text_iarchive.hpp11
-rw-r--r--boost/archive/text_oarchive.hpp14
-rw-r--r--boost/archive/xml_iarchive.hpp14
-rw-r--r--boost/archive/xml_oarchive.hpp52
-rw-r--r--boost/archive/xml_wiarchive.hpp24
-rw-r--r--boost/archive/xml_woarchive.hpp51
-rw-r--r--boost/atomic/detail/ops_emulated.hpp2
-rw-r--r--boost/atomic/detail/ops_gcc_x86_dcas.hpp2
-rw-r--r--boost/bimap/detail/debug/static_error.hpp1
-rw-r--r--boost/compute.hpp44
-rw-r--r--boost/compute/algorithm.hpp94
-rw-r--r--boost/compute/algorithm/accumulate.hpp184
-rw-r--r--boost/compute/algorithm/adjacent_difference.hpp98
-rw-r--r--boost/compute/algorithm/adjacent_find.hpp162
-rw-r--r--boost/compute/algorithm/all_of.hpp36
-rw-r--r--boost/compute/algorithm/any_of.hpp40
-rw-r--r--boost/compute/algorithm/binary_search.hpp37
-rw-r--r--boost/compute/algorithm/copy.hpp362
-rw-r--r--boost/compute/algorithm/copy_if.hpp58
-rw-r--r--boost/compute/algorithm/copy_n.hpp51
-rw-r--r--boost/compute/algorithm/count.hpp55
-rw-r--r--boost/compute/algorithm/count_if.hpp62
-rw-r--r--boost/compute/algorithm/detail/balanced_path.hpp162
-rw-r--r--boost/compute/algorithm/detail/binary_find.hpp133
-rw-r--r--boost/compute/algorithm/detail/compact.hpp77
-rw-r--r--boost/compute/algorithm/detail/copy_on_device.hpp190
-rw-r--r--boost/compute/algorithm/detail/copy_to_device.hpp127
-rw-r--r--boost/compute/algorithm/detail/copy_to_host.hpp137
-rw-r--r--boost/compute/algorithm/detail/count_if_with_ballot.hpp78
-rw-r--r--boost/compute/algorithm/detail/count_if_with_reduce.hpp87
-rw-r--r--boost/compute/algorithm/detail/count_if_with_threads.hpp129
-rw-r--r--boost/compute/algorithm/detail/find_extrema.hpp64
-rw-r--r--boost/compute/algorithm/detail/find_extrema_with_atomics.hpp108
-rw-r--r--boost/compute/algorithm/detail/find_extrema_with_reduce.hpp443
-rw-r--r--boost/compute/algorithm/detail/find_if_with_atomics.hpp212
-rw-r--r--boost/compute/algorithm/detail/inplace_reduce.hpp136
-rw-r--r--boost/compute/algorithm/detail/insertion_sort.hpp165
-rw-r--r--boost/compute/algorithm/detail/merge_path.hpp116
-rw-r--r--boost/compute/algorithm/detail/merge_sort_on_cpu.hpp366
-rw-r--r--boost/compute/algorithm/detail/merge_with_merge_path.hpp203
-rw-r--r--boost/compute/algorithm/detail/radix_sort.hpp415
-rw-r--r--boost/compute/algorithm/detail/random_fill.hpp57
-rw-r--r--boost/compute/algorithm/detail/reduce_by_key.hpp119
-rw-r--r--boost/compute/algorithm/detail/reduce_by_key_with_scan.hpp541
-rw-r--r--boost/compute/algorithm/detail/reduce_on_gpu.hpp286
-rw-r--r--boost/compute/algorithm/detail/scan.hpp45
-rw-r--r--boost/compute/algorithm/detail/scan_on_cpu.hpp103
-rw-r--r--boost/compute/algorithm/detail/scan_on_gpu.hpp331
-rw-r--r--boost/compute/algorithm/detail/search_all.hpp86
-rw-r--r--boost/compute/algorithm/detail/serial_accumulate.hpp56
-rw-r--r--boost/compute/algorithm/detail/serial_count_if.hpp68
-rw-r--r--boost/compute/algorithm/detail/serial_find_extrema.hpp87
-rw-r--r--boost/compute/algorithm/detail/serial_merge.hpp97
-rw-r--r--boost/compute/algorithm/detail/serial_reduce.hpp62
-rw-r--r--boost/compute/algorithm/detail/serial_reduce_by_key.hpp108
-rw-r--r--boost/compute/algorithm/equal.hpp53
-rw-r--r--boost/compute/algorithm/equal_range.hpp42
-rw-r--r--boost/compute/algorithm/exclusive_scan.hpp96
-rw-r--r--boost/compute/algorithm/fill.hpp306
-rw-r--r--boost/compute/algorithm/fill_n.hpp36
-rw-r--r--boost/compute/algorithm/find.hpp57
-rw-r--r--boost/compute/algorithm/find_end.hpp119
-rw-r--r--boost/compute/algorithm/find_if.hpp35
-rw-r--r--boost/compute/algorithm/find_if_not.hpp43
-rw-r--r--boost/compute/algorithm/for_each.hpp65
-rw-r--r--boost/compute/algorithm/for_each_n.hpp35
-rw-r--r--boost/compute/algorithm/gather.hpp84
-rw-r--r--boost/compute/algorithm/generate.hpp49
-rw-r--r--boost/compute/algorithm/generate_n.hpp35
-rw-r--r--boost/compute/algorithm/includes.hpp155
-rw-r--r--boost/compute/algorithm/inclusive_scan.hpp81
-rw-r--r--boost/compute/algorithm/inner_product.hpp93
-rw-r--r--boost/compute/algorithm/inplace_merge.hpp60
-rw-r--r--boost/compute/algorithm/iota.hpp48
-rw-r--r--boost/compute/algorithm/is_partitioned.hpp43
-rw-r--r--boost/compute/algorithm/is_permutation.hpp67
-rw-r--r--boost/compute/algorithm/is_sorted.hpp64
-rw-r--r--boost/compute/algorithm/lexicographical_compare.hpp117
-rw-r--r--boost/compute/algorithm/lower_bound.hpp44
-rw-r--r--boost/compute/algorithm/max_element.hpp74
-rw-r--r--boost/compute/algorithm/merge.hpp105
-rw-r--r--boost/compute/algorithm/min_element.hpp74
-rw-r--r--boost/compute/algorithm/minmax_element.hpp70
-rw-r--r--boost/compute/algorithm/mismatch.hpp89
-rw-r--r--boost/compute/algorithm/next_permutation.hpp170
-rw-r--r--boost/compute/algorithm/none_of.hpp36
-rw-r--r--boost/compute/algorithm/nth_element.hpp87
-rw-r--r--boost/compute/algorithm/partial_sum.hpp37
-rw-r--r--boost/compute/algorithm/partition.hpp39
-rw-r--r--boost/compute/algorithm/partition_copy.hpp63
-rw-r--r--boost/compute/algorithm/partition_point.hpp46
-rw-r--r--boost/compute/algorithm/prev_permutation.hpp170
-rw-r--r--boost/compute/algorithm/random_shuffle.hpp75
-rw-r--r--boost/compute/algorithm/reduce.hpp301
-rw-r--r--boost/compute/algorithm/reduce_by_key.hpp118
-rw-r--r--boost/compute/algorithm/remove.hpp54
-rw-r--r--boost/compute/algorithm/remove_if.hpp47
-rw-r--r--boost/compute/algorithm/replace.hpp90
-rw-r--r--boost/compute/algorithm/replace_copy.hpp62
-rw-r--r--boost/compute/algorithm/reverse.hpp74
-rw-r--r--boost/compute/algorithm/reverse_copy.hpp79
-rw-r--r--boost/compute/algorithm/rotate.hpp54
-rw-r--r--boost/compute/algorithm/rotate_copy.hpp41
-rw-r--r--boost/compute/algorithm/scatter.hpp99
-rw-r--r--boost/compute/algorithm/scatter_if.hpp119
-rw-r--r--boost/compute/algorithm/search.hpp73
-rw-r--r--boost/compute/algorithm/search_n.hpp140
-rw-r--r--boost/compute/algorithm/set_difference.hpp182
-rw-r--r--boost/compute/algorithm/set_intersection.hpp170
-rw-r--r--boost/compute/algorithm/set_symmetric_difference.hpp194
-rw-r--r--boost/compute/algorithm/set_union.hpp195
-rw-r--r--boost/compute/algorithm/sort.hpp194
-rw-r--r--boost/compute/algorithm/sort_by_key.hpp156
-rw-r--r--boost/compute/algorithm/stable_partition.hpp72
-rw-r--r--boost/compute/algorithm/stable_sort.hpp99
-rw-r--r--boost/compute/algorithm/stable_sort_by_key.hpp61
-rw-r--r--boost/compute/algorithm/swap_ranges.hpp44
-rw-r--r--boost/compute/algorithm/transform.hpp76
-rw-r--r--boost/compute/algorithm/transform_if.hpp117
-rw-r--r--boost/compute/algorithm/transform_reduce.hpp89
-rw-r--r--boost/compute/algorithm/unique.hpp66
-rw-r--r--boost/compute/algorithm/unique_copy.hpp164
-rw-r--r--boost/compute/algorithm/upper_bound.hpp43
-rw-r--r--boost/compute/allocator.hpp21
-rw-r--r--boost/compute/allocator/buffer_allocator.hpp118
-rw-r--r--boost/compute/allocator/pinned_allocator.hpp53
-rw-r--r--boost/compute/async.hpp21
-rw-r--r--boost/compute/async/future.hpp166
-rw-r--r--boost/compute/async/wait.hpp56
-rw-r--r--boost/compute/async/wait_guard.hpp63
-rw-r--r--boost/compute/buffer.hpp227
-rw-r--r--boost/compute/cl.hpp20
-rw-r--r--boost/compute/cl_ext.hpp20
-rw-r--r--boost/compute/closure.hpp347
-rw-r--r--boost/compute/command_queue.hpp1881
-rw-r--r--boost/compute/config.hpp70
-rw-r--r--boost/compute/container.hpp27
-rw-r--r--boost/compute/container/array.hpp281
-rw-r--r--boost/compute/container/basic_string.hpp331
-rw-r--r--boost/compute/container/detail/scalar.hpp61
-rw-r--r--boost/compute/container/dynamic_bitset.hpp237
-rw-r--r--boost/compute/container/flat_map.hpp406
-rw-r--r--boost/compute/container/flat_set.hpp339
-rw-r--r--boost/compute/container/mapped_view.hpp250
-rw-r--r--boost/compute/container/stack.hpp81
-rw-r--r--boost/compute/container/string.hpp25
-rw-r--r--boost/compute/container/valarray.hpp499
-rw-r--r--boost/compute/container/vector.hpp761
-rw-r--r--boost/compute/context.hpp245
-rw-r--r--boost/compute/core.hpp32
-rw-r--r--boost/compute/detail/assert_cl_success.hpp24
-rw-r--r--boost/compute/detail/buffer_value.hpp178
-rw-r--r--boost/compute/detail/device_ptr.hpp215
-rw-r--r--boost/compute/detail/diagnostic.hpp112
-rw-r--r--boost/compute/detail/duration.hpp50
-rw-r--r--boost/compute/detail/get_object_info.hpp216
-rw-r--r--boost/compute/detail/getenv.hpp36
-rw-r--r--boost/compute/detail/global_static.hpp37
-rw-r--r--boost/compute/detail/is_buffer_iterator.hpp30
-rw-r--r--boost/compute/detail/is_contiguous_iterator.hpp118
-rw-r--r--boost/compute/detail/iterator_plus_distance.hpp53
-rw-r--r--boost/compute/detail/iterator_range_size.hpp44
-rw-r--r--boost/compute/detail/iterator_traits.hpp35
-rw-r--r--boost/compute/detail/literal.hpp45
-rw-r--r--boost/compute/detail/lru_cache.hpp139
-rw-r--r--boost/compute/detail/meta_kernel.hpp1054
-rw-r--r--boost/compute/detail/mpl_vector_to_tuple.hpp65
-rw-r--r--boost/compute/detail/nvidia_compute_capability.hpp60
-rw-r--r--boost/compute/detail/parameter_cache.hpp215
-rw-r--r--boost/compute/detail/path.hpp73
-rw-r--r--boost/compute/detail/print_range.hpp82
-rw-r--r--boost/compute/detail/read_write_single_value.hpp77
-rw-r--r--boost/compute/detail/sha1.hpp53
-rw-r--r--boost/compute/detail/variadic_macros.hpp35
-rw-r--r--boost/compute/detail/vendor.hpp38
-rw-r--r--boost/compute/detail/work_size.hpp37
-rw-r--r--boost/compute/device.hpp584
-rw-r--r--boost/compute/event.hpp338
-rw-r--r--boost/compute/exception.hpp23
-rw-r--r--boost/compute/exception/context_error.hpp88
-rw-r--r--boost/compute/exception/no_device_found.hpp48
-rw-r--r--boost/compute/exception/opencl_error.hpp158
-rw-r--r--boost/compute/exception/unsupported_extension_error.hpp71
-rw-r--r--boost/compute/experimental/clamp_range.hpp49
-rw-r--r--boost/compute/experimental/malloc.hpp51
-rw-r--r--boost/compute/experimental/sort_by_transform.hpp66
-rw-r--r--boost/compute/experimental/tabulate.hpp44
-rw-r--r--boost/compute/function.hpp454
-rw-r--r--boost/compute/functional.hpp34
-rw-r--r--boost/compute/functional/as.hpp51
-rw-r--r--boost/compute/functional/atomic.hpp141
-rw-r--r--boost/compute/functional/bind.hpp261
-rw-r--r--boost/compute/functional/common.hpp29
-rw-r--r--boost/compute/functional/convert.hpp51
-rw-r--r--boost/compute/functional/detail/macros.hpp35
-rw-r--r--boost/compute/functional/detail/nvidia_ballot.hpp48
-rw-r--r--boost/compute/functional/detail/nvidia_popcount.hpp42
-rw-r--r--boost/compute/functional/detail/unpack.hpp143
-rw-r--r--boost/compute/functional/field.hpp86
-rw-r--r--boost/compute/functional/geometry.hpp32
-rw-r--r--boost/compute/functional/get.hpp76
-rw-r--r--boost/compute/functional/hash.hpp91
-rw-r--r--boost/compute/functional/identity.hpp64
-rw-r--r--boost/compute/functional/integer.hpp30
-rw-r--r--boost/compute/functional/logical.hpp208
-rw-r--r--boost/compute/functional/math.hpp80
-rw-r--r--boost/compute/functional/operator.hpp100
-rw-r--r--boost/compute/functional/popcount.hpp55
-rw-r--r--boost/compute/functional/relational.hpp39
-rw-r--r--boost/compute/image.hpp25
-rw-r--r--boost/compute/image/image1d.hpp204
-rw-r--r--boost/compute/image/image2d.hpp262
-rw-r--r--boost/compute/image/image3d.hpp265
-rw-r--r--boost/compute/image/image_format.hpp135
-rw-r--r--boost/compute/image/image_object.hpp170
-rw-r--r--boost/compute/image/image_sampler.hpp221
-rw-r--r--boost/compute/image2d.hpp12
-rw-r--r--boost/compute/image3d.hpp12
-rw-r--r--boost/compute/image_format.hpp12
-rw-r--r--boost/compute/image_sampler.hpp12
-rw-r--r--boost/compute/interop/eigen.hpp16
-rw-r--r--boost/compute/interop/eigen/core.hpp72
-rw-r--r--boost/compute/interop/opencv.hpp17
-rw-r--r--boost/compute/interop/opencv/core.hpp141
-rw-r--r--boost/compute/interop/opencv/highgui.hpp33
-rw-r--r--boost/compute/interop/opencv/ocl.hpp51
-rw-r--r--boost/compute/interop/opengl.hpp24
-rw-r--r--boost/compute/interop/opengl/acquire.hpp99
-rw-r--r--boost/compute/interop/opengl/cl_gl.hpp20
-rw-r--r--boost/compute/interop/opengl/cl_gl_ext.hpp20
-rw-r--r--boost/compute/interop/opengl/context.hpp135
-rw-r--r--boost/compute/interop/opengl/gl.hpp20
-rw-r--r--boost/compute/interop/opengl/opengl_buffer.hpp106
-rw-r--r--boost/compute/interop/opengl/opengl_renderbuffer.hpp129
-rw-r--r--boost/compute/interop/opengl/opengl_texture.hpp133
-rw-r--r--boost/compute/interop/qt.hpp17
-rw-r--r--boost/compute/interop/qt/qimage.hpp69
-rw-r--r--boost/compute/interop/qt/qpoint.hpp20
-rw-r--r--boost/compute/interop/qt/qpointf.hpp20
-rw-r--r--boost/compute/interop/qt/qtcore.hpp18
-rw-r--r--boost/compute/interop/qt/qtgui.hpp16
-rw-r--r--boost/compute/interop/qt/qvector.hpp48
-rw-r--r--boost/compute/interop/vtk.hpp19
-rw-r--r--boost/compute/interop/vtk/bounds.hpp59
-rw-r--r--boost/compute/interop/vtk/data_array.hpp65
-rw-r--r--boost/compute/interop/vtk/matrix4x4.hpp46
-rw-r--r--boost/compute/interop/vtk/points.hpp55
-rw-r--r--boost/compute/iterator.hpp28
-rw-r--r--boost/compute/iterator/buffer_iterator.hpp280
-rw-r--r--boost/compute/iterator/constant_buffer_iterator.hpp209
-rw-r--r--boost/compute/iterator/constant_iterator.hpp171
-rw-r--r--boost/compute/iterator/counting_iterator.hpp185
-rw-r--r--boost/compute/iterator/detail/get_base_iterator_buffer.hpp52
-rw-r--r--boost/compute/iterator/detail/swizzle_iterator.hpp188
-rw-r--r--boost/compute/iterator/discard_iterator.hpp170
-rw-r--r--boost/compute/iterator/function_input_iterator.hpp186
-rw-r--r--boost/compute/iterator/permutation_iterator.hpp192
-rw-r--r--boost/compute/iterator/strided_iterator.hpp296
-rw-r--r--boost/compute/iterator/transform_iterator.hpp227
-rw-r--r--boost/compute/iterator/zip_iterator.hpp316
-rw-r--r--boost/compute/kernel.hpp394
-rw-r--r--boost/compute/lambda.hpp22
-rw-r--r--boost/compute/lambda/context.hpp329
-rw-r--r--boost/compute/lambda/functional.hpp242
-rw-r--r--boost/compute/lambda/get.hpp148
-rw-r--r--boost/compute/lambda/make_pair.hpp70
-rw-r--r--boost/compute/lambda/make_tuple.hpp127
-rw-r--r--boost/compute/lambda/placeholder.hpp28
-rw-r--r--boost/compute/lambda/placeholders.hpp93
-rw-r--r--boost/compute/lambda/result_of.hpp113
-rw-r--r--boost/compute/memory.hpp21
-rw-r--r--boost/compute/memory/local_buffer.hpp91
-rw-r--r--boost/compute/memory/svm_ptr.hpp81
-rw-r--r--boost/compute/memory_object.hpp264
-rw-r--r--boost/compute/pipe.hpp154
-rw-r--r--boost/compute/platform.hpp235
-rw-r--r--boost/compute/program.hpp650
-rw-r--r--boost/compute/random.hpp28
-rw-r--r--boost/compute/random/bernoulli_distribution.hpp92
-rw-r--r--boost/compute/random/default_random_engine.hpp24
-rw-r--r--boost/compute/random/discrete_distribution.hpp117
-rw-r--r--boost/compute/random/linear_congruential_engine.hpp238
-rw-r--r--boost/compute/random/mersenne_twister_engine.hpp254
-rw-r--r--boost/compute/random/normal_distribution.hpp124
-rw-r--r--boost/compute/random/threefry_engine.hpp311
-rw-r--r--boost/compute/random/uniform_int_distribution.hpp111
-rw-r--r--boost/compute/random/uniform_real_distribution.hpp105
-rw-r--r--boost/compute/source.hpp12
-rw-r--r--boost/compute/svm.hpp62
-rw-r--r--boost/compute/system.hpp278
-rw-r--r--boost/compute/type_traits.hpp25
-rw-r--r--boost/compute/type_traits/common_type.hpp55
-rw-r--r--boost/compute/type_traits/detail/capture_traits.hpp33
-rw-r--r--boost/compute/type_traits/is_device_iterator.hpp39
-rw-r--r--boost/compute/type_traits/is_fundamental.hpp58
-rw-r--r--boost/compute/type_traits/is_vector_type.hpp38
-rw-r--r--boost/compute/type_traits/make_vector_type.hpp71
-rw-r--r--boost/compute/type_traits/result_of.hpp39
-rw-r--r--boost/compute/type_traits/scalar_type.hpp72
-rw-r--r--boost/compute/type_traits/type_definition.hpp39
-rw-r--r--boost/compute/type_traits/type_name.hpp124
-rw-r--r--boost/compute/type_traits/vector_size.hpp65
-rw-r--r--boost/compute/types.hpp24
-rw-r--r--boost/compute/types/builtin.hpp12
-rw-r--r--boost/compute/types/complex.hpp196
-rw-r--r--boost/compute/types/fundamental.hpp172
-rw-r--r--boost/compute/types/pair.hpp117
-rw-r--r--boost/compute/types/struct.hpp173
-rw-r--r--boost/compute/types/tuple.hpp220
-rw-r--r--boost/compute/user_event.hpp88
-rw-r--r--boost/compute/utility.hpp21
-rw-r--r--boost/compute/utility/dim.hpp76
-rw-r--r--boost/compute/utility/extents.hpp164
-rw-r--r--boost/compute/utility/invoke.hpp71
-rw-r--r--boost/compute/utility/program_cache.hpp172
-rw-r--r--boost/compute/utility/source.hpp39
-rw-r--r--boost/compute/utility/wait_list.hpp203
-rw-r--r--boost/compute/version.hpp18
-rw-r--r--boost/compute/wait_list.hpp12
-rw-r--r--boost/config/compiler/clang.hpp15
-rw-r--r--boost/config/compiler/gcc.hpp21
-rw-r--r--boost/config/compiler/intel.hpp10
-rw-r--r--boost/config/compiler/nvcc.hpp8
-rw-r--r--boost/config/stdlib/libcpp.hpp18
-rw-r--r--boost/container/allocator_traits.hpp7
-rw-r--r--boost/container/deque.hpp40
-rw-r--r--boost/container/detail/config_begin.hpp2
-rw-r--r--boost/container/detail/iterators.hpp72
-rw-r--r--boost/container/detail/node_alloc_holder.hpp50
-rw-r--r--boost/container/detail/pair.hpp10
-rw-r--r--boost/container/detail/tree.hpp75
-rw-r--r--boost/container/detail/workaround.hpp13
-rw-r--r--boost/container/map.hpp39
-rw-r--r--boost/container/small_vector.hpp172
-rw-r--r--boost/container/static_vector.hpp53
-rw-r--r--boost/container/throw_exception.hpp1
-rw-r--r--boost/container/vector.hpp216
-rw-r--r--boost/context/all.hpp4
-rw-r--r--boost/context/detail/apply.hpp55
-rw-r--r--boost/context/detail/config.hpp59
-rw-r--r--boost/context/detail/disable_overload.hpp40
-rw-r--r--boost/context/detail/exception.hpp36
-rw-r--r--boost/context/detail/exchange.hpp36
-rw-r--r--boost/context/detail/fcontext.hpp (renamed from boost/context/fcontext.hpp)31
-rw-r--r--boost/context/detail/index_sequence.hpp72
-rw-r--r--boost/context/detail/invoke.hpp58
-rw-r--r--boost/context/detail/tuple.hpp129
-rw-r--r--boost/context/execution_context.hpp12
-rw-r--r--boost/context/execution_context.ipp452
-rw-r--r--boost/context/execution_context_v1.hpp487
-rw-r--r--boost/context/execution_context_v2.hpp395
-rw-r--r--boost/context/execution_context_v2_void.ipp290
-rw-r--r--boost/context/execution_context_winfib.ipp361
-rw-r--r--boost/context/fixedsize_stack.hpp11
-rw-r--r--boost/context/flags.hpp28
-rw-r--r--boost/context/pooled_fixedsize_stack.hpp115
-rw-r--r--boost/context/posix/protected_fixedsize_stack.hpp4
-rw-r--r--boost/context/posix/segmented_stack.hpp4
-rw-r--r--boost/context/preallocated.hpp39
-rw-r--r--boost/context/stack_context.hpp55
-rw-r--r--boost/context/stack_traits.hpp10
-rw-r--r--boost/context/windows/protected_fixedsize_stack.hpp10
-rw-r--r--boost/core/demangle.hpp5
-rw-r--r--boost/core/scoped_enum.hpp56
-rw-r--r--boost/coroutine/attributes.hpp44
-rw-r--r--boost/coroutine/detail/config.hpp8
-rw-r--r--boost/coroutine/detail/coroutine_context.hpp19
-rw-r--r--boost/coroutine/detail/data.hpp34
-rw-r--r--boost/coroutine/detail/flags.hpp3
-rw-r--r--boost/coroutine/detail/pull_coroutine_impl.hpp48
-rw-r--r--boost/coroutine/detail/pull_coroutine_object.hpp33
-rw-r--r--boost/coroutine/detail/pull_coroutine_synthesized.hpp12
-rw-r--r--boost/coroutine/detail/push_coroutine_impl.hpp47
-rw-r--r--boost/coroutine/detail/push_coroutine_object.hpp33
-rw-r--r--boost/coroutine/detail/push_coroutine_synthesized.hpp12
-rw-r--r--boost/coroutine/detail/symmetric_coroutine_impl.hpp66
-rw-r--r--boost/coroutine/detail/symmetric_coroutine_object.hpp27
-rw-r--r--boost/coroutine/detail/trampoline.hpp22
-rw-r--r--boost/coroutine/detail/trampoline_pull.hpp12
-rw-r--r--boost/coroutine/detail/trampoline_push.hpp22
-rw-r--r--boost/coroutine/flags.hpp6
-rw-r--r--boost/coroutine/posix/segmented_stack_allocator.hpp8
-rw-r--r--boost/coroutine/stack_context.hpp2
-rw-r--r--boost/coroutine2/all.hpp1
-rw-r--r--boost/coroutine2/coroutine.hpp4
-rw-r--r--boost/coroutine2/detail/coroutine.hpp29
-rw-r--r--boost/coroutine2/detail/create_control_block.ipp60
-rw-r--r--boost/coroutine2/detail/decay_copy.hpp36
-rw-r--r--boost/coroutine2/detail/disable_overload.hpp34
-rw-r--r--boost/coroutine2/detail/forced_unwind.hpp6
-rw-r--r--boost/coroutine2/detail/pull_control_block.ipp299
-rw-r--r--boost/coroutine2/detail/pull_control_block_ecv1.hpp (renamed from boost/coroutine2/detail/pull_control_block.hpp)54
-rw-r--r--boost/coroutine2/detail/pull_control_block_ecv1.ipp421
-rw-r--r--boost/coroutine2/detail/pull_control_block_ecv2.hpp114
-rw-r--r--boost/coroutine2/detail/pull_control_block_ecv2.ipp411
-rw-r--r--boost/coroutine2/detail/pull_coroutine.hpp131
-rw-r--r--boost/coroutine2/detail/pull_coroutine.ipp158
-rw-r--r--boost/coroutine2/detail/push_control_block.ipp289
-rw-r--r--boost/coroutine2/detail/push_control_block_ecv1.hpp (renamed from boost/coroutine2/detail/push_control_block.hpp)48
-rw-r--r--boost/coroutine2/detail/push_control_block_ecv1.ipp418
-rw-r--r--boost/coroutine2/detail/push_control_block_ecv2.hpp104
-rw-r--r--boost/coroutine2/detail/push_control_block_ecv2.ipp377
-rw-r--r--boost/coroutine2/detail/push_coroutine.hpp115
-rw-r--r--boost/coroutine2/detail/push_coroutine.ipp138
-rw-r--r--boost/coroutine2/detail/state.hpp53
-rw-r--r--boost/coroutine2/fixedsize_stack.hpp4
-rw-r--r--boost/coroutine2/pooled_fixedsize_stack.hpp33
-rw-r--r--boost/coroutine2/protected_fixedsize_stack.hpp2
-rw-r--r--boost/coroutine2/segmented_stack.hpp4
-rw-r--r--boost/detail/utf8_codecvt_facet.hpp18
-rw-r--r--boost/detail/utf8_codecvt_facet.ipp10
-rw-r--r--boost/detail/winapi/GetCurrentProcess.hpp19
-rw-r--r--boost/detail/winapi/GetCurrentThread.hpp19
-rw-r--r--boost/detail/winapi/GetLastError.hpp18
-rw-r--r--boost/detail/winapi/GetProcessTimes.hpp46
-rw-r--r--boost/detail/winapi/GetThreadTimes.hpp40
-rw-r--r--boost/detail/winapi/access_rights.hpp84
-rw-r--r--boost/detail/winapi/basic_types.hpp8
-rw-r--r--boost/detail/winapi/character_code_conversion.hpp108
-rw-r--r--boost/detail/winapi/condition_variable.hpp7
-rw-r--r--boost/detail/winapi/config.hpp13
-rw-r--r--boost/detail/winapi/crypt.hpp4
-rw-r--r--boost/detail/winapi/dbghelp.hpp171
-rw-r--r--boost/detail/winapi/directory_management.hpp1
-rw-r--r--boost/detail/winapi/dll.hpp25
-rw-r--r--boost/detail/winapi/error_handling.hpp19
-rw-r--r--boost/detail/winapi/event.hpp15
-rw-r--r--boost/detail/winapi/file_management.hpp138
-rw-r--r--boost/detail/winapi/file_mapping.hpp72
-rw-r--r--boost/detail/winapi/get_current_process.hpp34
-rw-r--r--boost/detail/winapi/get_current_process_id.hpp33
-rw-r--r--boost/detail/winapi/get_current_thread.hpp34
-rw-r--r--boost/detail/winapi/get_current_thread_id.hpp34
-rw-r--r--boost/detail/winapi/get_last_error.hpp33
-rw-r--r--boost/detail/winapi/get_process_times.hpp60
-rw-r--r--boost/detail/winapi/get_system_directory.hpp63
-rw-r--r--boost/detail/winapi/get_thread_times.hpp55
-rw-r--r--boost/detail/winapi/handle_info.hpp62
-rw-r--r--boost/detail/winapi/limits.hpp51
-rw-r--r--boost/detail/winapi/mutex.hpp5
-rw-r--r--boost/detail/winapi/overlapped.hpp51
-rw-r--r--boost/detail/winapi/page_protection_flags.hpp56
-rw-r--r--boost/detail/winapi/pipes.hpp317
-rw-r--r--boost/detail/winapi/priority_class.hpp78
-rw-r--r--boost/detail/winapi/process.hpp374
-rw-r--r--boost/detail/winapi/semaphore.hpp9
-rw-r--r--boost/detail/winapi/shell.hpp145
-rw-r--r--boost/detail/winapi/show_window.hpp105
-rw-r--r--boost/detail/winapi/srw_lock.hpp11
-rw-r--r--boost/detail/winapi/thread.hpp8
-rw-r--r--boost/detail/winapi/waitable_timer.hpp19
-rw-r--r--boost/dll.hpp27
-rw-r--r--boost/dll/alias.hpp264
-rw-r--r--boost/dll/detail/aggressive_ptr_cast.hpp130
-rw-r--r--boost/dll/detail/ctor_dtor.hpp176
-rw-r--r--boost/dll/detail/demangling/demangle_symbol.hpp83
-rw-r--r--boost/dll/detail/demangling/itanium.hpp285
-rw-r--r--boost/dll/detail/demangling/mangled_storage_base.hpp118
-rw-r--r--boost/dll/detail/demangling/msvc.hpp400
-rw-r--r--boost/dll/detail/elf_info.hpp285
-rw-r--r--boost/dll/detail/get_mem_fn_type.hpp40
-rw-r--r--boost/dll/detail/macho_info.hpp321
-rw-r--r--boost/dll/detail/pe_info.hpp427
-rw-r--r--boost/dll/detail/posix/path_from_handle.hpp169
-rw-r--r--boost/dll/detail/posix/program_location_impl.hpp140
-rw-r--r--boost/dll/detail/posix/shared_library_impl.hpp215
-rw-r--r--boost/dll/detail/system_error.hpp56
-rw-r--r--boost/dll/detail/windows/path_from_handle.hpp62
-rw-r--r--boost/dll/detail/windows/shared_library_impl.hpp177
-rw-r--r--boost/dll/detail/x_info_interface.hpp32
-rw-r--r--boost/dll/import.hpp277
-rw-r--r--boost/dll/library_info.hpp181
-rw-r--r--boost/dll/runtime_symbol_info.hpp194
-rw-r--r--boost/dll/shared_library.hpp550
-rw-r--r--boost/dll/shared_library_load_mode.hpp249
-rw-r--r--boost/dll/smart_library.hpp347
-rw-r--r--boost/endian/conversion.hpp4
-rw-r--r--boost/endian/detail/intrinsic.hpp21
-rw-r--r--boost/fusion/adapted/adt/adapt_adt.hpp9
-rw-r--r--boost/fusion/adapted/adt/adapt_assoc_adt.hpp10
-rw-r--r--boost/fusion/adapted/adt/detail/adapt_base.hpp60
-rw-r--r--boost/fusion/adapted/adt/detail/adapt_base_assoc_attr_filler.hpp13
-rw-r--r--boost/fusion/adapted/adt/detail/adapt_base_attr_filler.hpp32
-rw-r--r--boost/fusion/adapted/struct/adapt_assoc_struct.hpp9
-rw-r--r--boost/fusion/adapted/struct/adapt_assoc_struct_named.hpp11
-rw-r--r--boost/fusion/adapted/struct/adapt_struct.hpp13
-rw-r--r--boost/fusion/adapted/struct/adapt_struct_named.hpp2
-rw-r--r--boost/fusion/adapted/struct/define_assoc_struct.hpp1
-rw-r--r--boost/fusion/adapted/struct/define_struct.hpp1
-rw-r--r--boost/fusion/adapted/struct/detail/adapt_auto.hpp5
-rw-r--r--boost/fusion/adapted/struct/detail/adapt_base.hpp28
-rw-r--r--boost/fusion/adapted/struct/detail/adapt_base_assoc_attr_filler.hpp24
-rw-r--r--boost/fusion/adapted/struct/detail/adapt_base_attr_filler.hpp26
-rw-r--r--boost/fusion/adapted/struct/detail/adapt_is_tpl.hpp2
-rw-r--r--boost/fusion/adapted/struct/detail/define_struct.hpp114
-rw-r--r--boost/fusion/adapted/struct/detail/define_struct_inline.hpp14
-rw-r--r--boost/fusion/adapted/struct/detail/preprocessor/is_seq.hpp2
-rw-r--r--boost/fusion/algorithm/transformation/zip.hpp1
-rw-r--r--boost/fusion/container/deque/deque.hpp8
-rw-r--r--boost/fusion/container/deque/detail/cpp03/deque.hpp12
-rw-r--r--boost/fusion/container/deque/detail/cpp03/preprocessed/deque10.hpp11
-rw-r--r--boost/fusion/container/deque/detail/cpp03/preprocessed/deque20.hpp11
-rw-r--r--boost/fusion/container/deque/detail/cpp03/preprocessed/deque30.hpp11
-rw-r--r--boost/fusion/container/deque/detail/cpp03/preprocessed/deque40.hpp11
-rw-r--r--boost/fusion/container/deque/detail/cpp03/preprocessed/deque50.hpp11
-rw-r--r--boost/fusion/container/generation/make_vector.hpp34
-rw-r--r--boost/fusion/container/list/cons.hpp6
-rw-r--r--boost/fusion/container/list/detail/cpp03/list.hpp4
-rw-r--r--boost/fusion/container/list/detail/cpp03/preprocessed/list10.hpp2
-rw-r--r--boost/fusion/container/list/detail/cpp03/preprocessed/list20.hpp2
-rw-r--r--boost/fusion/container/list/detail/cpp03/preprocessed/list30.hpp2
-rw-r--r--boost/fusion/container/list/detail/cpp03/preprocessed/list40.hpp2
-rw-r--r--boost/fusion/container/list/detail/cpp03/preprocessed/list50.hpp2
-rw-r--r--boost/fusion/container/map/map.hpp8
-rw-r--r--boost/fusion/container/set/detail/cpp03/preprocessed/set10.hpp3
-rw-r--r--boost/fusion/container/set/detail/cpp03/preprocessed/set20.hpp3
-rw-r--r--boost/fusion/container/set/detail/cpp03/preprocessed/set30.hpp3
-rw-r--r--boost/fusion/container/set/detail/cpp03/preprocessed/set40.hpp3
-rw-r--r--boost/fusion/container/set/detail/cpp03/preprocessed/set50.hpp3
-rw-r--r--boost/fusion/container/set/detail/cpp03/set.hpp5
-rw-r--r--boost/fusion/container/set/set.hpp10
-rw-r--r--boost/fusion/container/vector/detail/cpp03/preprocessed/vvector10.hpp2
-rw-r--r--boost/fusion/container/vector/detail/cpp03/preprocessed/vvector20.hpp2
-rw-r--r--boost/fusion/container/vector/detail/cpp03/preprocessed/vvector30.hpp2
-rw-r--r--boost/fusion/container/vector/detail/cpp03/preprocessed/vvector40.hpp2
-rw-r--r--boost/fusion/container/vector/detail/cpp03/preprocessed/vvector50.hpp2
-rw-r--r--boost/fusion/container/vector/detail/cpp03/vector.hpp4
-rw-r--r--boost/fusion/container/vector/vector.hpp38
-rw-r--r--boost/fusion/sequence/convert.hpp11
-rw-r--r--boost/fusion/support/detail/enabler.hpp22
-rw-r--r--boost/fusion/support/detail/index_sequence.hpp20
-rw-r--r--boost/fusion/view/iterator_range/detail/segmented_iterator_range.hpp19
-rw-r--r--boost/fusion/view/single_view/detail/next_impl.hpp5
-rw-r--r--boost/geometry/algorithms/assign.hpp1
-rw-r--r--boost/geometry/algorithms/buffer.hpp2
-rw-r--r--boost/geometry/algorithms/convex_hull.hpp2
-rw-r--r--boost/geometry/algorithms/detail/andoyer_inverse.hpp156
-rw-r--r--boost/geometry/algorithms/detail/as_range.hpp2
-rw-r--r--boost/geometry/algorithms/detail/assign_values.hpp1
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp8
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffer_policies.hpp56
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp37
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffered_ring.hpp23
-rw-r--r--boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp33
-rw-r--r--boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp24
-rw-r--r--boost/geometry/algorithms/detail/direction_code.hpp79
-rw-r--r--boost/geometry/algorithms/detail/disjoint/box_box.hpp70
-rw-r--r--boost/geometry/algorithms/detail/disjoint/point_box.hpp63
-rw-r--r--boost/geometry/algorithms/detail/disjoint/segment_box.hpp9
-rw-r--r--boost/geometry/algorithms/detail/envelope/segment.hpp116
-rw-r--r--boost/geometry/algorithms/detail/intersection/interface.hpp2
-rw-r--r--boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp2
-rw-r--r--boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp44
-rw-r--r--boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp87
-rw-r--r--boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp545
-rw-r--r--boost/geometry/algorithms/detail/overlay/enrichment_info.hpp9
-rw-r--r--boost/geometry/algorithms/detail/overlay/handle_colocations.hpp466
-rw-r--r--boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp786
-rw-r--r--boost/geometry/algorithms/detail/overlay/handle_touch.hpp336
-rw-r--r--boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp203
-rw-r--r--boost/geometry/algorithms/detail/overlay/overlay.hpp139
-rw-r--r--boost/geometry/algorithms/detail/overlay/segment_identifier.hpp5
-rw-r--r--boost/geometry/algorithms/detail/overlay/select_rings.hpp42
-rw-r--r--boost/geometry/algorithms/detail/overlay/sort_by_side.hpp434
-rw-r--r--boost/geometry/algorithms/detail/overlay/traverse.hpp995
-rw-r--r--boost/geometry/algorithms/detail/overlay/turn_info.hpp10
-rw-r--r--boost/geometry/algorithms/detail/overlay/visit_info.hpp13
-rw-r--r--boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp12
-rw-r--r--boost/geometry/algorithms/detail/recalculate.hpp6
-rw-r--r--boost/geometry/algorithms/detail/relate/result.hpp11
-rw-r--r--boost/geometry/algorithms/difference.hpp2
-rw-r--r--boost/geometry/algorithms/length.hpp8
-rw-r--r--boost/geometry/algorithms/remove_spikes.hpp2
-rw-r--r--boost/geometry/algorithms/simplify.hpp4
-rw-r--r--boost/geometry/algorithms/sym_difference.hpp2
-rw-r--r--boost/geometry/algorithms/transform.hpp6
-rw-r--r--boost/geometry/algorithms/union.hpp2
-rw-r--r--boost/geometry/core/access.hpp11
-rw-r--r--boost/geometry/core/closure.hpp2
-rw-r--r--boost/geometry/core/coordinate_dimension.hpp9
-rw-r--r--boost/geometry/core/coordinate_type.hpp2
-rw-r--r--boost/geometry/core/exterior_ring.hpp1
-rw-r--r--boost/geometry/core/interior_type.hpp3
-rw-r--r--boost/geometry/core/mutable_range.hpp2
-rw-r--r--boost/geometry/core/point_order.hpp2
-rw-r--r--boost/geometry/core/radius.hpp1
-rw-r--r--boost/geometry/core/reverse_dispatch.hpp3
-rw-r--r--boost/geometry/core/tag.hpp1
-rw-r--r--boost/geometry/core/tag_cast.hpp2
-rw-r--r--boost/geometry/extensions/algorithms/inverse.hpp59
-rw-r--r--boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp2
-rw-r--r--boost/geometry/index/detail/rtree/pack_create.hpp14
-rw-r--r--boost/geometry/index/rtree.hpp14
-rw-r--r--boost/geometry/io/svg/svg_mapper.hpp50
-rw-r--r--boost/geometry/io/svg/write_svg.hpp30
-rw-r--r--boost/geometry/io/svg/write_svg_multi.hpp31
-rw-r--r--boost/geometry/io/wkt/read.hpp9
-rw-r--r--boost/geometry/policies/robustness/get_rescale_policy.hpp15
-rw-r--r--boost/geometry/policies/robustness/rescale_policy.hpp2
-rw-r--r--boost/geometry/policies/robustness/robust_type.hpp2
-rw-r--r--boost/geometry/strategies/agnostic/point_in_box_by_side.hpp56
-rw-r--r--boost/geometry/strategies/agnostic/point_in_poly_winding.hpp330
-rw-r--r--boost/geometry/strategies/cartesian/area_surveyor.hpp21
-rw-r--r--boost/geometry/strategies/cartesian/box_in_box.hpp123
-rw-r--r--boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp2
-rw-r--r--boost/geometry/strategies/cartesian/distance_projected_point.hpp2
-rw-r--r--boost/geometry/strategies/cartesian/distance_projected_point_ax.hpp2
-rw-r--r--boost/geometry/strategies/cartesian/distance_pythagoras.hpp5
-rw-r--r--boost/geometry/strategies/cartesian/point_in_box.hpp114
-rw-r--r--boost/geometry/strategies/cartesian/side_by_triangle.hpp3
-rw-r--r--boost/geometry/strategies/geographic/distance_andoyer.hpp71
-rw-r--r--boost/geometry/strategies/spherical/ssf.hpp12
-rw-r--r--boost/geometry/util/calculation_type.hpp4
-rw-r--r--boost/geometry/util/combine_if.hpp2
-rw-r--r--boost/geometry/util/math.hpp61
-rw-r--r--boost/geometry/util/normalize_spheroidal_coordinates.hpp106
-rw-r--r--boost/geometry/util/parameter_type_of.hpp2
-rw-r--r--boost/geometry/util/promote_floating_point.hpp2
-rw-r--r--boost/geometry/util/range.hpp55
-rw-r--r--boost/geometry/util/select_calculation_type.hpp2
-rw-r--r--boost/geometry/util/select_most_precise.hpp3
-rw-r--r--boost/graph/adjacency_matrix.hpp2
-rw-r--r--boost/hana.hpp208
-rw-r--r--boost/hana/accessors.hpp56
-rw-r--r--boost/hana/adapt_adt.hpp17
-rw-r--r--boost/hana/adapt_struct.hpp17
-rw-r--r--boost/hana/adjust.hpp55
-rw-r--r--boost/hana/adjust_if.hpp78
-rw-r--r--boost/hana/all.hpp48
-rw-r--r--boost/hana/all_of.hpp51
-rw-r--r--boost/hana/and.hpp58
-rw-r--r--boost/hana/any.hpp48
-rw-r--r--boost/hana/any_of.hpp190
-rw-r--r--boost/hana/ap.hpp78
-rw-r--r--boost/hana/append.hpp74
-rw-r--r--boost/hana/assert.hpp306
-rw-r--r--boost/hana/at.hpp57
-rw-r--r--boost/hana/at_key.hpp121
-rw-r--r--boost/hana/back.hpp53
-rw-r--r--boost/hana/basic_tuple.hpp299
-rw-r--r--boost/hana/bool.hpp264
-rw-r--r--boost/hana/cartesian_product.hpp113
-rw-r--r--boost/hana/chain.hpp50
-rw-r--r--boost/hana/comparing.hpp45
-rw-r--r--boost/hana/concat.hpp80
-rw-r--r--boost/hana/concept.hpp35
-rw-r--r--boost/hana/concept/applicative.hpp31
-rw-r--r--boost/hana/concept/comonad.hpp33
-rw-r--r--boost/hana/concept/comparable.hpp29
-rw-r--r--boost/hana/concept/constant.hpp29
-rw-r--r--boost/hana/concept/euclidean_ring.hpp31
-rw-r--r--boost/hana/concept/foldable.hpp31
-rw-r--r--boost/hana/concept/functor.hpp31
-rw-r--r--boost/hana/concept/group.hpp31
-rw-r--r--boost/hana/concept/hashable.hpp30
-rw-r--r--boost/hana/concept/integral_constant.hpp40
-rw-r--r--boost/hana/concept/iterable.hpp33
-rw-r--r--boost/hana/concept/logical.hpp33
-rw-r--r--boost/hana/concept/metafunction.hpp38
-rw-r--r--boost/hana/concept/monad.hpp31
-rw-r--r--boost/hana/concept/monad_plus.hpp31
-rw-r--r--boost/hana/concept/monoid.hpp31
-rw-r--r--boost/hana/concept/orderable.hpp29
-rw-r--r--boost/hana/concept/product.hpp31
-rw-r--r--boost/hana/concept/ring.hpp31
-rw-r--r--boost/hana/concept/searchable.hpp31
-rw-r--r--boost/hana/concept/sequence.hpp41
-rw-r--r--boost/hana/concept/struct.hpp29
-rw-r--r--boost/hana/config.hpp215
-rw-r--r--boost/hana/contains.hpp51
-rw-r--r--boost/hana/core.hpp22
-rw-r--r--boost/hana/core/common.hpp109
-rw-r--r--boost/hana/core/default.hpp32
-rw-r--r--boost/hana/core/dispatch.hpp18
-rw-r--r--boost/hana/core/is_a.hpp41
-rw-r--r--boost/hana/core/make.hpp45
-rw-r--r--boost/hana/core/tag_of.hpp49
-rw-r--r--boost/hana/core/to.hpp194
-rw-r--r--boost/hana/core/when.hpp15
-rw-r--r--boost/hana/count.hpp50
-rw-r--r--boost/hana/count_if.hpp92
-rw-r--r--boost/hana/cycle.hpp127
-rw-r--r--boost/hana/define_struct.hpp17
-rw-r--r--boost/hana/detail/algorithm.hpp184
-rw-r--r--boost/hana/detail/any_of.hpp46
-rw-r--r--boost/hana/detail/array.hpp105
-rw-r--r--boost/hana/detail/canonical_constant.hpp80
-rw-r--r--boost/hana/detail/concepts.hpp76
-rw-r--r--boost/hana/detail/create.hpp33
-rw-r--r--boost/hana/detail/decay.hpp48
-rw-r--r--boost/hana/detail/dependent_on.hpp24
-rw-r--r--boost/hana/detail/dispatch_if.hpp56
-rw-r--r--boost/hana/detail/fast_and.hpp25
-rw-r--r--boost/hana/detail/first_unsatisfied_index.hpp56
-rw-r--r--boost/hana/detail/has_common_embedding.hpp69
-rw-r--r--boost/hana/detail/has_duplicates.hpp65
-rw-r--r--boost/hana/detail/hash_table.hpp145
-rw-r--r--boost/hana/detail/index_if.hpp69
-rw-r--r--boost/hana/detail/intrinsics.hpp67
-rw-r--r--boost/hana/detail/nested_by.hpp40
-rw-r--r--boost/hana/detail/nested_by_fwd.hpp55
-rw-r--r--boost/hana/detail/nested_than.hpp29
-rw-r--r--boost/hana/detail/nested_than_fwd.hpp47
-rw-r--r--boost/hana/detail/nested_to.hpp28
-rw-r--r--boost/hana/detail/nested_to_fwd.hpp47
-rw-r--r--boost/hana/detail/operators/adl.hpp34
-rw-r--r--boost/hana/detail/operators/arithmetic.hpp78
-rw-r--r--boost/hana/detail/operators/comparable.hpp44
-rw-r--r--boost/hana/detail/operators/iterable.hpp40
-rw-r--r--boost/hana/detail/operators/logical.hpp51
-rw-r--r--boost/hana/detail/operators/monad.hpp35
-rw-r--r--boost/hana/detail/operators/orderable.hpp60
-rw-r--r--boost/hana/detail/operators/searchable.hpp40
-rw-r--r--boost/hana/detail/preprocessor.hpp106
-rw-r--r--boost/hana/detail/std_common_type.hpp36
-rw-r--r--boost/hana/detail/struct_macros.erb.hpp185
-rw-r--r--boost/hana/detail/struct_macros.hpp3469
-rw-r--r--boost/hana/detail/type_foldl1.hpp145
-rw-r--r--boost/hana/detail/type_foldr1.hpp149
-rw-r--r--boost/hana/detail/unpack_flatten.hpp70
-rw-r--r--boost/hana/detail/variadic/at.hpp40
-rw-r--r--boost/hana/detail/variadic/drop_into.hpp47
-rw-r--r--boost/hana/detail/variadic/foldl1.hpp212
-rw-r--r--boost/hana/detail/variadic/foldr1.hpp208
-rw-r--r--boost/hana/detail/variadic/reverse_apply.hpp27
-rw-r--r--boost/hana/detail/variadic/reverse_apply/flat.hpp41
-rw-r--r--boost/hana/detail/variadic/reverse_apply/unrolled.hpp87
-rw-r--r--boost/hana/detail/variadic/split_at.hpp153
-rw-r--r--boost/hana/detail/variadic/take.hpp51
-rw-r--r--boost/hana/detail/void_t.hpp21
-rw-r--r--boost/hana/detail/wrong.hpp33
-rw-r--r--boost/hana/difference.hpp39
-rw-r--r--boost/hana/div.hpp107
-rw-r--r--boost/hana/drop_back.hpp75
-rw-r--r--boost/hana/drop_front.hpp57
-rw-r--r--boost/hana/drop_front_exactly.hpp85
-rw-r--r--boost/hana/drop_while.hpp93
-rw-r--r--boost/hana/duplicate.hpp48
-rw-r--r--boost/hana/empty.hpp53
-rw-r--r--boost/hana/equal.hpp199
-rw-r--r--boost/hana/erase_key.hpp37
-rw-r--r--boost/hana/eval.hpp57
-rw-r--r--boost/hana/eval_if.hpp93
-rw-r--r--boost/hana/experimental/printable.hpp243
-rw-r--r--boost/hana/experimental/types.hpp178
-rw-r--r--boost/hana/experimental/view.hpp512
-rw-r--r--boost/hana/ext/boost.hpp21
-rw-r--r--boost/hana/ext/boost/fusion.hpp22
-rw-r--r--boost/hana/ext/boost/fusion/deque.hpp108
-rw-r--r--boost/hana/ext/boost/fusion/detail/common.hpp79
-rw-r--r--boost/hana/ext/boost/fusion/list.hpp111
-rw-r--r--boost/hana/ext/boost/fusion/tuple.hpp49
-rw-r--r--boost/hana/ext/boost/fusion/vector.hpp110
-rw-r--r--boost/hana/ext/boost/mpl.hpp21
-rw-r--r--boost/hana/ext/boost/mpl/integral_c.hpp81
-rw-r--r--boost/hana/ext/boost/mpl/list.hpp186
-rw-r--r--boost/hana/ext/boost/mpl/vector.hpp185
-rw-r--r--boost/hana/ext/boost/tuple.hpp138
-rw-r--r--boost/hana/ext/std.hpp30
-rw-r--r--boost/hana/ext/std/array.hpp163
-rw-r--r--boost/hana/ext/std/integer_sequence.hpp140
-rw-r--r--boost/hana/ext/std/integral_constant.hpp96
-rw-r--r--boost/hana/ext/std/pair.hpp91
-rw-r--r--boost/hana/ext/std/ratio.hpp164
-rw-r--r--boost/hana/ext/std/tuple.hpp190
-rw-r--r--boost/hana/ext/std/vector.hpp110
-rw-r--r--boost/hana/extend.hpp50
-rw-r--r--boost/hana/extract.hpp45
-rw-r--r--boost/hana/fill.hpp74
-rw-r--r--boost/hana/filter.hpp135
-rw-r--r--boost/hana/find.hpp61
-rw-r--r--boost/hana/find_if.hpp177
-rw-r--r--boost/hana/first.hpp45
-rw-r--r--boost/hana/flatten.hpp62
-rw-r--r--boost/hana/fold.hpp17
-rw-r--r--boost/hana/fold_left.hpp97
-rw-r--r--boost/hana/fold_right.hpp97
-rw-r--r--boost/hana/for_each.hpp62
-rw-r--r--boost/hana/front.hpp47
-rw-r--r--boost/hana/functional.hpp33
-rw-r--r--boost/hana/functional/always.hpp64
-rw-r--r--boost/hana/functional/apply.hpp85
-rw-r--r--boost/hana/functional/arg.hpp141
-rw-r--r--boost/hana/functional/capture.hpp112
-rw-r--r--boost/hana/functional/compose.hpp108
-rw-r--r--boost/hana/functional/curry.hpp169
-rw-r--r--boost/hana/functional/demux.hpp269
-rw-r--r--boost/hana/functional/fix.hpp83
-rw-r--r--boost/hana/functional/flip.hpp73
-rw-r--r--boost/hana/functional/id.hpp38
-rw-r--r--boost/hana/functional/infix.hpp184
-rw-r--r--boost/hana/functional/iterate.hpp201
-rw-r--r--boost/hana/functional/lockstep.hpp114
-rw-r--r--boost/hana/functional/on.hpp83
-rw-r--r--boost/hana/functional/overload.hpp88
-rw-r--r--boost/hana/functional/overload_linearly.hpp105
-rw-r--r--boost/hana/functional/partial.hpp107
-rw-r--r--boost/hana/functional/placeholder.hpp263
-rw-r--r--boost/hana/functional/reverse_partial.hpp101
-rw-r--r--boost/hana/fuse.hpp48
-rw-r--r--boost/hana/fwd/accessors.hpp50
-rw-r--r--boost/hana/fwd/adapt_adt.hpp48
-rw-r--r--boost/hana/fwd/adapt_struct.hpp48
-rw-r--r--boost/hana/fwd/adjust.hpp64
-rw-r--r--boost/hana/fwd/adjust_if.hpp69
-rw-r--r--boost/hana/fwd/all.hpp46
-rw-r--r--boost/hana/fwd/all_of.hpp54
-rw-r--r--boost/hana/fwd/and.hpp53
-rw-r--r--boost/hana/fwd/any.hpp46
-rw-r--r--boost/hana/fwd/any_of.hpp53
-rw-r--r--boost/hana/fwd/ap.hpp82
-rw-r--r--boost/hana/fwd/append.hpp68
-rw-r--r--boost/hana/fwd/at.hpp97
-rw-r--r--boost/hana/fwd/at_key.hpp75
-rw-r--r--boost/hana/fwd/back.hpp48
-rw-r--r--boost/hana/fwd/basic_tuple.hpp65
-rw-r--r--boost/hana/fwd/bool.hpp15
-rw-r--r--boost/hana/fwd/cartesian_product.hpp70
-rw-r--r--boost/hana/fwd/chain.hpp67
-rw-r--r--boost/hana/fwd/comparing.hpp65
-rw-r--r--boost/hana/fwd/concat.hpp63
-rw-r--r--boost/hana/fwd/concept/applicative.hpp117
-rw-r--r--boost/hana/fwd/concept/comonad.hpp111
-rw-r--r--boost/hana/fwd/concept/comparable.hpp161
-rw-r--r--boost/hana/fwd/concept/constant.hpp210
-rw-r--r--boost/hana/fwd/concept/euclidean_ring.hpp117
-rw-r--r--boost/hana/fwd/concept/foldable.hpp141
-rw-r--r--boost/hana/fwd/concept/functor.hpp139
-rw-r--r--boost/hana/fwd/concept/group.hpp111
-rw-r--r--boost/hana/fwd/concept/hashable.hpp68
-rw-r--r--boost/hana/fwd/concept/integral_constant.hpp73
-rw-r--r--boost/hana/fwd/concept/iterable.hpp149
-rw-r--r--boost/hana/fwd/concept/logical.hpp166
-rw-r--r--boost/hana/fwd/concept/metafunction.hpp99
-rw-r--r--boost/hana/fwd/concept/monad.hpp198
-rw-r--r--boost/hana/fwd/concept/monad_plus.hpp89
-rw-r--r--boost/hana/fwd/concept/monoid.hpp101
-rw-r--r--boost/hana/fwd/concept/orderable.hpp187
-rw-r--r--boost/hana/fwd/concept/product.hpp103
-rw-r--r--boost/hana/fwd/concept/ring.hpp106
-rw-r--r--boost/hana/fwd/concept/searchable.hpp143
-rw-r--r--boost/hana/fwd/concept/sequence.hpp165
-rw-r--r--boost/hana/fwd/concept/struct.hpp156
-rw-r--r--boost/hana/fwd/contains.hpp73
-rw-r--r--boost/hana/fwd/core.hpp21
-rw-r--r--boost/hana/fwd/core/common.hpp103
-rw-r--r--boost/hana/fwd/core/default.hpp56
-rw-r--r--boost/hana/fwd/core/is_a.hpp61
-rw-r--r--boost/hana/fwd/core/make.hpp70
-rw-r--r--boost/hana/fwd/core/tag_of.hpp120
-rw-r--r--boost/hana/fwd/core/to.hpp174
-rw-r--r--boost/hana/fwd/core/when.hpp74
-rw-r--r--boost/hana/fwd/count.hpp57
-rw-r--r--boost/hana/fwd/count_if.hpp63
-rw-r--r--boost/hana/fwd/cycle.hpp76
-rw-r--r--boost/hana/fwd/define_struct.hpp48
-rw-r--r--boost/hana/fwd/difference.hpp72
-rw-r--r--boost/hana/fwd/div.hpp59
-rw-r--r--boost/hana/fwd/drop_back.hpp63
-rw-r--r--boost/hana/fwd/drop_front.hpp66
-rw-r--r--boost/hana/fwd/drop_front_exactly.hpp67
-rw-r--r--boost/hana/fwd/drop_while.hpp60
-rw-r--r--boost/hana/fwd/duplicate.hpp57
-rw-r--r--boost/hana/fwd/empty.hpp51
-rw-r--r--boost/hana/fwd/equal.hpp80
-rw-r--r--boost/hana/fwd/erase_key.hpp32
-rw-r--r--boost/hana/fwd/eval.hpp58
-rw-r--r--boost/hana/fwd/eval_if.hpp155
-rw-r--r--boost/hana/fwd/extend.hpp62
-rw-r--r--boost/hana/fwd/extract.hpp58
-rw-r--r--boost/hana/fwd/fill.hpp57
-rw-r--r--boost/hana/fwd/filter.hpp88
-rw-r--r--boost/hana/fwd/find.hpp60
-rw-r--r--boost/hana/fwd/find_if.hpp64
-rw-r--r--boost/hana/fwd/first.hpp49
-rw-r--r--boost/hana/fwd/flatten.hpp63
-rw-r--r--boost/hana/fwd/fold.hpp38
-rw-r--r--boost/hana/fwd/fold_left.hpp96
-rw-r--r--boost/hana/fwd/fold_right.hpp100
-rw-r--r--boost/hana/fwd/for_each.hpp55
-rw-r--r--boost/hana/fwd/front.hpp48
-rw-r--r--boost/hana/fwd/fuse.hpp55
-rw-r--r--boost/hana/fwd/greater.hpp53
-rw-r--r--boost/hana/fwd/greater_equal.hpp54
-rw-r--r--boost/hana/fwd/group.hpp103
-rw-r--r--boost/hana/fwd/hash.hpp68
-rw-r--r--boost/hana/fwd/if.hpp57
-rw-r--r--boost/hana/fwd/insert.hpp60
-rw-r--r--boost/hana/fwd/insert_range.hpp57
-rw-r--r--boost/hana/fwd/integral_constant.hpp399
-rw-r--r--boost/hana/fwd/intersection.hpp61
-rw-r--r--boost/hana/fwd/intersperse.hpp57
-rw-r--r--boost/hana/fwd/is_disjoint.hpp58
-rw-r--r--boost/hana/fwd/is_empty.hpp49
-rw-r--r--boost/hana/fwd/is_subset.hpp87
-rw-r--r--boost/hana/fwd/keys.hpp50
-rw-r--r--boost/hana/fwd/lazy.hpp124
-rw-r--r--boost/hana/fwd/length.hpp50
-rw-r--r--boost/hana/fwd/less.hpp53
-rw-r--r--boost/hana/fwd/less_equal.hpp54
-rw-r--r--boost/hana/fwd/lexicographical_compare.hpp101
-rw-r--r--boost/hana/fwd/lift.hpp59
-rw-r--r--boost/hana/fwd/map.hpp233
-rw-r--r--boost/hana/fwd/max.hpp44
-rw-r--r--boost/hana/fwd/maximum.hpp116
-rw-r--r--boost/hana/fwd/members.hpp46
-rw-r--r--boost/hana/fwd/min.hpp51
-rw-r--r--boost/hana/fwd/minimum.hpp116
-rw-r--r--boost/hana/fwd/minus.hpp67
-rw-r--r--boost/hana/fwd/mod.hpp62
-rw-r--r--boost/hana/fwd/monadic_compose.hpp75
-rw-r--r--boost/hana/fwd/monadic_fold_left.hpp104
-rw-r--r--boost/hana/fwd/monadic_fold_right.hpp106
-rw-r--r--boost/hana/fwd/mult.hpp63
-rw-r--r--boost/hana/fwd/negate.hpp42
-rw-r--r--boost/hana/fwd/none.hpp46
-rw-r--r--boost/hana/fwd/none_of.hpp55
-rw-r--r--boost/hana/fwd/not.hpp47
-rw-r--r--boost/hana/fwd/not_equal.hpp70
-rw-r--r--boost/hana/fwd/one.hpp45
-rw-r--r--boost/hana/fwd/optional.hpp510
-rw-r--r--boost/hana/fwd/or.hpp53
-rw-r--r--boost/hana/fwd/ordering.hpp65
-rw-r--r--boost/hana/fwd/pair.hpp153
-rw-r--r--boost/hana/fwd/partition.hpp89
-rw-r--r--boost/hana/fwd/permutations.hpp50
-rw-r--r--boost/hana/fwd/plus.hpp63
-rw-r--r--boost/hana/fwd/power.hpp56
-rw-r--r--boost/hana/fwd/prefix.hpp72
-rw-r--r--boost/hana/fwd/prepend.hpp73
-rw-r--r--boost/hana/fwd/product.hpp78
-rw-r--r--boost/hana/fwd/range.hpp149
-rw-r--r--boost/hana/fwd/remove.hpp70
-rw-r--r--boost/hana/fwd/remove_at.hpp82
-rw-r--r--boost/hana/fwd/remove_if.hpp69
-rw-r--r--boost/hana/fwd/remove_range.hpp85
-rw-r--r--boost/hana/fwd/repeat.hpp58
-rw-r--r--boost/hana/fwd/replace.hpp64
-rw-r--r--boost/hana/fwd/replace_if.hpp63
-rw-r--r--boost/hana/fwd/replicate.hpp75
-rw-r--r--boost/hana/fwd/reverse.hpp49
-rw-r--r--boost/hana/fwd/reverse_fold.hpp84
-rw-r--r--boost/hana/fwd/scan_left.hpp105
-rw-r--r--boost/hana/fwd/scan_right.hpp105
-rw-r--r--boost/hana/fwd/second.hpp48
-rw-r--r--boost/hana/fwd/set.hpp194
-rw-r--r--boost/hana/fwd/size.hpp33
-rw-r--r--boost/hana/fwd/slice.hpp105
-rw-r--r--boost/hana/fwd/sort.hpp110
-rw-r--r--boost/hana/fwd/span.hpp85
-rw-r--r--boost/hana/fwd/string.hpp240
-rw-r--r--boost/hana/fwd/suffix.hpp72
-rw-r--r--boost/hana/fwd/sum.hpp79
-rw-r--r--boost/hana/fwd/symmetric_difference.hpp62
-rw-r--r--boost/hana/fwd/take_back.hpp58
-rw-r--r--boost/hana/fwd/take_front.hpp78
-rw-r--r--boost/hana/fwd/take_while.hpp56
-rw-r--r--boost/hana/fwd/tap.hpp65
-rw-r--r--boost/hana/fwd/then.hpp52
-rw-r--r--boost/hana/fwd/transform.hpp64
-rw-r--r--boost/hana/fwd/tuple.hpp224
-rw-r--r--boost/hana/fwd/type.hpp478
-rw-r--r--boost/hana/fwd/unfold_left.hpp85
-rw-r--r--boost/hana/fwd/unfold_right.hpp85
-rw-r--r--boost/hana/fwd/union.hpp61
-rw-r--r--boost/hana/fwd/unique.hpp91
-rw-r--r--boost/hana/fwd/unpack.hpp103
-rw-r--r--boost/hana/fwd/value.hpp100
-rw-r--r--boost/hana/fwd/while.hpp71
-rw-r--r--boost/hana/fwd/zero.hpp45
-rw-r--r--boost/hana/fwd/zip.hpp61
-rw-r--r--boost/hana/fwd/zip_shortest.hpp61
-rw-r--r--boost/hana/fwd/zip_shortest_with.hpp62
-rw-r--r--boost/hana/fwd/zip_with.hpp62
-rw-r--r--boost/hana/greater.hpp71
-rw-r--r--boost/hana/greater_equal.hpp74
-rw-r--r--boost/hana/group.hpp157
-rw-r--r--boost/hana/hash.hpp114
-rw-r--r--boost/hana/if.hpp61
-rw-r--r--boost/hana/insert.hpp52
-rw-r--r--boost/hana/insert_range.hpp64
-rw-r--r--boost/hana/integral_constant.hpp15
-rw-r--r--boost/hana/intersection.hpp39
-rw-r--r--boost/hana/intersperse.hpp76
-rw-r--r--boost/hana/is_disjoint.hpp65
-rw-r--r--boost/hana/is_empty.hpp45
-rw-r--r--boost/hana/is_subset.hpp84
-rw-r--r--boost/hana/keys.hpp48
-rw-r--r--boost/hana/lazy.hpp229
-rw-r--r--boost/hana/length.hpp57
-rw-r--r--boost/hana/less.hpp142
-rw-r--r--boost/hana/less_equal.hpp75
-rw-r--r--boost/hana/lexicographical_compare.hpp110
-rw-r--r--boost/hana/lift.hpp54
-rw-r--r--boost/hana/map.hpp389
-rw-r--r--boost/hana/max.hpp58
-rw-r--r--boost/hana/maximum.hpp97
-rw-r--r--boost/hana/members.hpp65
-rw-r--r--boost/hana/min.hpp58
-rw-r--r--boost/hana/minimum.hpp97
-rw-r--r--boost/hana/minus.hpp114
-rw-r--r--boost/hana/mod.hpp107
-rw-r--r--boost/hana/monadic_compose.hpp51
-rw-r--r--boost/hana/monadic_fold_left.hpp131
-rw-r--r--boost/hana/monadic_fold_right.hpp130
-rw-r--r--boost/hana/mult.hpp107
-rw-r--r--boost/hana/negate.hpp61
-rw-r--r--boost/hana/none.hpp48
-rw-r--r--boost/hana/none_of.hpp50
-rw-r--r--boost/hana/not.hpp75
-rw-r--r--boost/hana/not_equal.hpp59
-rw-r--r--boost/hana/one.hpp79
-rw-r--r--boost/hana/optional.hpp416
-rw-r--r--boost/hana/or.hpp61
-rw-r--r--boost/hana/ordering.hpp45
-rw-r--r--boost/hana/pair.hpp147
-rw-r--r--boost/hana/partition.hpp116
-rw-r--r--boost/hana/permutations.hpp78
-rw-r--r--boost/hana/plus.hpp109
-rw-r--r--boost/hana/power.hpp65
-rw-r--r--boost/hana/prefix.hpp52
-rw-r--r--boost/hana/prepend.hpp74
-rw-r--r--boost/hana/product.hpp58
-rw-r--r--boost/hana/range.hpp294
-rw-r--r--boost/hana/remove.hpp54
-rw-r--r--boost/hana/remove_at.hpp86
-rw-r--r--boost/hana/remove_if.hpp52
-rw-r--r--boost/hana/remove_range.hpp100
-rw-r--r--boost/hana/repeat.hpp58
-rw-r--r--boost/hana/replace.hpp56
-rw-r--r--boost/hana/replace_if.hpp54
-rw-r--r--boost/hana/replicate.hpp74
-rw-r--r--boost/hana/reverse.hpp61
-rw-r--r--boost/hana/reverse_fold.hpp37
-rw-r--r--boost/hana/scan_left.hpp133
-rw-r--r--boost/hana/scan_right.hpp130
-rw-r--r--boost/hana/second.hpp45
-rw-r--r--boost/hana/set.hpp322
-rw-r--r--boost/hana/size.hpp17
-rw-r--r--boost/hana/slice.hpp99
-rw-r--r--boost/hana/sort.hpp173
-rw-r--r--boost/hana/span.hpp75
-rw-r--r--boost/hana/string.hpp290
-rw-r--r--boost/hana/suffix.hpp52
-rw-r--r--boost/hana/sum.hpp58
-rw-r--r--boost/hana/symmetric_difference.hpp46
-rw-r--r--boost/hana/take_back.hpp68
-rw-r--r--boost/hana/take_front.hpp75
-rw-r--r--boost/hana/take_while.hpp55
-rw-r--r--boost/hana/tap.hpp59
-rw-r--r--boost/hana/then.hpp55
-rw-r--r--boost/hana/traits.hpp213
-rw-r--r--boost/hana/transform.hpp76
-rw-r--r--boost/hana/tuple.hpp305
-rw-r--r--boost/hana/type.hpp223
-rw-r--r--boost/hana/unfold_left.hpp71
-rw-r--r--boost/hana/unfold_right.hpp71
-rw-r--r--boost/hana/union.hpp39
-rw-r--r--boost/hana/unique.hpp75
-rw-r--r--boost/hana/unpack.hpp141
-rw-r--r--boost/hana/value.hpp56
-rw-r--r--boost/hana/version.hpp53
-rw-r--r--boost/hana/while.hpp117
-rw-r--r--boost/hana/zero.hpp81
-rw-r--r--boost/hana/zip.hpp50
-rw-r--r--boost/hana/zip_shortest.hpp51
-rw-r--r--boost/hana/zip_shortest_with.hpp63
-rw-r--r--boost/hana/zip_with.hpp70
-rw-r--r--boost/heap/binomial_heap.hpp4
-rw-r--r--boost/heap/detail/stable_heap.hpp83
-rw-r--r--boost/heap/detail/tree_iterator.hpp6
-rw-r--r--boost/heap/priority_queue.hpp18
-rw-r--r--boost/interprocess/detail/utilities.hpp18
-rw-r--r--boost/interprocess/detail/win32_api.hpp6
-rw-r--r--boost/interprocess/detail/workaround.hpp17
-rw-r--r--boost/interprocess/offset_ptr.hpp140
-rw-r--r--boost/intrusive/avl_set.hpp49
-rw-r--r--boost/intrusive/avltree.hpp22
-rw-r--r--boost/intrusive/bs_set.hpp41
-rw-r--r--boost/intrusive/bstree.hpp38
-rw-r--r--boost/intrusive/detail/any_node_and_algorithms.hpp89
-rw-r--r--boost/intrusive/detail/avltree_node.hpp53
-rw-r--r--boost/intrusive/detail/bstree_algorithms_base.hpp4
-rw-r--r--boost/intrusive/detail/config_begin.hpp11
-rw-r--r--boost/intrusive/detail/default_header_holder.hpp7
-rw-r--r--boost/intrusive/detail/ebo_functor_holder.hpp51
-rw-r--r--boost/intrusive/detail/equal_to_value.hpp4
-rw-r--r--boost/intrusive/detail/exception_disposer.hpp6
-rw-r--r--boost/intrusive/detail/has_member_function_callable_with.hpp5
-rw-r--r--boost/intrusive/detail/hashtable_node.hpp33
-rw-r--r--boost/intrusive/detail/hook_traits.hpp17
-rw-r--r--boost/intrusive/detail/iiterator.hpp15
-rw-r--r--boost/intrusive/detail/iterator.hpp31
-rw-r--r--boost/intrusive/detail/list_iterator.hpp43
-rw-r--r--boost/intrusive/detail/list_node.hpp13
-rw-r--r--boost/intrusive/detail/parent_from_member.hpp9
-rw-r--r--boost/intrusive/detail/rbtree_node.hpp57
-rw-r--r--boost/intrusive/detail/reverse_iterator.hpp45
-rw-r--r--boost/intrusive/detail/size_holder.hpp26
-rw-r--r--boost/intrusive/detail/slist_iterator.hpp41
-rw-r--r--boost/intrusive/detail/slist_node.hpp7
-rw-r--r--boost/intrusive/detail/to_raw_pointer.hpp5
-rw-r--r--boost/intrusive/detail/transform_iterator.hpp45
-rw-r--r--boost/intrusive/detail/tree_iterator.hpp45
-rw-r--r--boost/intrusive/detail/tree_node.hpp19
-rw-r--r--boost/intrusive/detail/tree_value_compare.hpp11
-rw-r--r--boost/intrusive/detail/workaround.hpp12
-rw-r--r--boost/intrusive/hashtable.hpp34
-rw-r--r--boost/intrusive/list.hpp21
-rw-r--r--boost/intrusive/member_value_traits.hpp8
-rw-r--r--boost/intrusive/parent_from_member.hpp5
-rw-r--r--boost/intrusive/pointer_plus_bits.hpp8
-rw-r--r--boost/intrusive/pointer_traits.hpp8
-rw-r--r--boost/intrusive/priority_compare.hpp7
-rw-r--r--boost/intrusive/rbtree.hpp23
-rw-r--r--boost/intrusive/set.hpp41
-rw-r--r--boost/intrusive/sg_set.hpp49
-rw-r--r--boost/intrusive/sgtree.hpp31
-rw-r--r--boost/intrusive/slist.hpp18
-rw-r--r--boost/intrusive/splay_set.hpp41
-rw-r--r--boost/intrusive/splaytree.hpp23
-rw-r--r--boost/intrusive/treap.hpp128
-rw-r--r--boost/intrusive/treap_set.hpp86
-rw-r--r--boost/intrusive/trivial_value_traits.hpp9
-rw-r--r--boost/intrusive/unordered_set.hpp4
-rw-r--r--boost/lexical_cast.hpp2
-rw-r--r--boost/lexical_cast/lexical_cast_old.hpp1
-rw-r--r--boost/lexical_cast/try_lexical_convert.hpp25
-rw-r--r--boost/lockfree/detail/atomic.hpp6
-rw-r--r--boost/lockfree/detail/freelist.hpp19
-rw-r--r--boost/lockfree/spsc_queue.hpp10
-rw-r--r--boost/log/attributes/attribute_value_impl.hpp2
-rw-r--r--boost/log/detail/config.hpp18
-rw-r--r--boost/log/detail/light_rw_mutex.hpp2
-rw-r--r--boost/log/detail/threadsafe_queue.hpp7
-rw-r--r--boost/log/detail/timestamp.hpp5
-rw-r--r--boost/log/expressions/formatter.hpp14
-rw-r--r--boost/log/keywords/max_files.hpp40
-rw-r--r--boost/log/sinks/text_file_backend.hpp15
-rw-r--r--boost/log/utility/formatting_ostream.hpp35
-rw-r--r--boost/log/utility/once_block.hpp2
-rw-r--r--boost/log/utility/setup/file.hpp1
-rw-r--r--boost/make_unique.hpp14
-rw-r--r--boost/math/bindings/mpfr.hpp2
-rw-r--r--boost/math/cstdfloat/cstdfloat_complex_std.hpp8
-rw-r--r--boost/math/special_functions/detail/polygamma.hpp2
-rw-r--r--boost/math/special_functions/detail/t_distribution_inv.hpp2
-rw-r--r--boost/math/special_functions/ellint_2.hpp2
-rw-r--r--boost/math/special_functions/ellint_3.hpp2
-rw-r--r--boost/math/special_functions/fpclassify.hpp20
-rw-r--r--boost/math/tools/config.hpp12
-rw-r--r--boost/math/tools/polynomial.hpp378
-rw-r--r--boost/metaparse.hpp123
-rw-r--r--boost/metaparse/accept.hpp20
-rw-r--r--boost/metaparse/accept_tag.hpp20
-rw-r--r--boost/metaparse/accept_when.hpp20
-rw-r--r--boost/metaparse/alphanum.hpp20
-rw-r--r--boost/metaparse/always.hpp20
-rw-r--r--boost/metaparse/always_c.hpp20
-rw-r--r--boost/metaparse/build_parser.hpp20
-rw-r--r--boost/metaparse/change_error_message.hpp20
-rw-r--r--boost/metaparse/config.hpp40
-rw-r--r--boost/metaparse/debug_parsing_error.hpp21
-rw-r--r--boost/metaparse/define_error.hpp17
-rw-r--r--boost/metaparse/digit.hpp20
-rw-r--r--boost/metaparse/digit_val.hpp20
-rw-r--r--boost/metaparse/empty.hpp20
-rw-r--r--boost/metaparse/entire_input.hpp20
-rw-r--r--boost/metaparse/error/digit_expected.hpp23
-rw-r--r--boost/metaparse/error/end_of_input_expected.hpp23
-rw-r--r--boost/metaparse/error/index_out_of_range.hpp23
-rw-r--r--boost/metaparse/error/letter_expected.hpp23
-rw-r--r--boost/metaparse/error/literal_expected.hpp24
-rw-r--r--boost/metaparse/error/none_of_the_expected_cases_found.hpp23
-rw-r--r--boost/metaparse/error/unexpected_character.hpp23
-rw-r--r--boost/metaparse/error/unexpected_end_of_input.hpp24
-rw-r--r--boost/metaparse/error/unpaired.hpp23
-rw-r--r--boost/metaparse/error/whitespace_expected.hpp24
-rw-r--r--boost/metaparse/except.hpp20
-rw-r--r--boost/metaparse/fail.hpp20
-rw-r--r--boost/metaparse/fail_at_first_char_expected.hpp20
-rw-r--r--boost/metaparse/fail_tag.hpp21
-rw-r--r--boost/metaparse/first_of.hpp20
-rw-r--r--boost/metaparse/foldl.hpp20
-rw-r--r--boost/metaparse/foldl1.hpp20
-rw-r--r--boost/metaparse/foldl_reject_incomplete.hpp20
-rw-r--r--boost/metaparse/foldl_reject_incomplete1.hpp20
-rw-r--r--boost/metaparse/foldl_reject_incomplete_start_with_parser.hpp20
-rw-r--r--boost/metaparse/foldl_start_with_parser.hpp20
-rw-r--r--boost/metaparse/foldr.hpp20
-rw-r--r--boost/metaparse/foldr1.hpp20
-rw-r--r--boost/metaparse/foldr_reject_incomplete.hpp20
-rw-r--r--boost/metaparse/foldr_reject_incomplete1.hpp20
-rw-r--r--boost/metaparse/foldr_start_with_parser.hpp20
-rw-r--r--boost/metaparse/get_col.hpp20
-rw-r--r--boost/metaparse/get_line.hpp20
-rw-r--r--boost/metaparse/get_message.hpp20
-rw-r--r--boost/metaparse/get_position.hpp20
-rw-r--r--boost/metaparse/get_prev_char.hpp20
-rw-r--r--boost/metaparse/get_remaining.hpp20
-rw-r--r--boost/metaparse/get_result.hpp20
-rw-r--r--boost/metaparse/grammar.hpp19
-rw-r--r--boost/metaparse/if_.hpp20
-rw-r--r--boost/metaparse/int_.hpp20
-rw-r--r--boost/metaparse/is_error.hpp20
-rw-r--r--boost/metaparse/iterate.hpp20
-rw-r--r--boost/metaparse/iterate_c.hpp20
-rw-r--r--boost/metaparse/keyword.hpp20
-rw-r--r--boost/metaparse/last_of.hpp20
-rw-r--r--boost/metaparse/letter.hpp20
-rw-r--r--boost/metaparse/limit_one_char_except_size.hpp15
-rw-r--r--boost/metaparse/limit_one_of_size.hpp14
-rw-r--r--boost/metaparse/limit_sequence_size.hpp14
-rw-r--r--boost/metaparse/limit_string_size.hpp14
-rw-r--r--boost/metaparse/lit.hpp21
-rw-r--r--boost/metaparse/lit_c.hpp21
-rw-r--r--boost/metaparse/look_ahead.hpp20
-rw-r--r--boost/metaparse/middle_of.hpp20
-rw-r--r--boost/metaparse/next_char.hpp20
-rw-r--r--boost/metaparse/next_line.hpp20
-rw-r--r--boost/metaparse/nth_of.hpp20
-rw-r--r--boost/metaparse/nth_of_c.hpp20
-rw-r--r--boost/metaparse/one_char.hpp21
-rw-r--r--boost/metaparse/one_char_except.hpp20
-rw-r--r--boost/metaparse/one_char_except_c.hpp20
-rw-r--r--boost/metaparse/one_of.hpp20
-rw-r--r--boost/metaparse/one_of_c.hpp20
-rw-r--r--boost/metaparse/optional.hpp20
-rw-r--r--boost/metaparse/range.hpp20
-rw-r--r--boost/metaparse/range_c.hpp20
-rw-r--r--boost/metaparse/reject.hpp20
-rw-r--r--boost/metaparse/repeated.hpp20
-rw-r--r--boost/metaparse/repeated1.hpp20
-rw-r--r--boost/metaparse/repeated_one_of.hpp20
-rw-r--r--boost/metaparse/repeated_one_of1.hpp20
-rw-r--r--boost/metaparse/repeated_reject_incomplete.hpp20
-rw-r--r--boost/metaparse/repeated_reject_incomplete1.hpp20
-rw-r--r--boost/metaparse/return_.hpp20
-rw-r--r--boost/metaparse/sequence.hpp20
-rw-r--r--boost/metaparse/sequence_apply.hpp36
-rw-r--r--boost/metaparse/source_position.hpp20
-rw-r--r--boost/metaparse/source_position_tag.hpp20
-rw-r--r--boost/metaparse/space.hpp21
-rw-r--r--boost/metaparse/spaces.hpp20
-rw-r--r--boost/metaparse/start.hpp20
-rw-r--r--boost/metaparse/string.hpp26
-rw-r--r--boost/metaparse/string_tag.hpp20
-rw-r--r--boost/metaparse/token.hpp20
-rw-r--r--boost/metaparse/transform.hpp20
-rw-r--r--boost/metaparse/transform_error.hpp21
-rw-r--r--boost/metaparse/transform_error_message.hpp21
-rw-r--r--boost/metaparse/unless_error.hpp20
-rw-r--r--boost/metaparse/util/digit_to_int.hpp23
-rw-r--r--boost/metaparse/util/digit_to_int_c.hpp23
-rw-r--r--boost/metaparse/util/in_range.hpp23
-rw-r--r--boost/metaparse/util/in_range_c.hpp23
-rw-r--r--boost/metaparse/util/int_to_digit.hpp23
-rw-r--r--boost/metaparse/util/int_to_digit_c.hpp23
-rw-r--r--boost/metaparse/util/is_digit.hpp23
-rw-r--r--boost/metaparse/util/is_lcase_letter.hpp23
-rw-r--r--boost/metaparse/util/is_letter.hpp23
-rw-r--r--boost/metaparse/util/is_ucase_letter.hpp23
-rw-r--r--boost/metaparse/util/is_whitespace.hpp23
-rw-r--r--boost/metaparse/util/is_whitespace_c.hpp23
-rw-r--r--boost/metaparse/v1/accept.hpp36
-rw-r--r--boost/metaparse/v1/accept_tag.hpp47
-rw-r--r--boost/metaparse/v1/accept_when.hpp59
-rw-r--r--boost/metaparse/v1/alphanum.hpp25
-rw-r--r--boost/metaparse/v1/always.hpp51
-rw-r--r--boost/metaparse/v1/always_c.hpp25
-rw-r--r--boost/metaparse/v1/build_parser.hpp66
-rw-r--r--boost/metaparse/v1/change_error_message.hpp39
-rw-r--r--boost/metaparse/v1/debug_parsing_error.hpp105
-rw-r--r--boost/metaparse/v1/define_error.hpp25
-rw-r--r--boost/metaparse/v1/digit.hpp34
-rw-r--r--boost/metaparse/v1/digit_val.hpp26
-rw-r--r--boost/metaparse/v1/empty.hpp42
-rw-r--r--boost/metaparse/v1/entire_input.hpp33
-rw-r--r--boost/metaparse/v1/error/digit_expected.hpp26
-rw-r--r--boost/metaparse/v1/error/end_of_input_expected.hpp29
-rw-r--r--boost/metaparse/v1/error/expected_to_fail.hpp30
-rw-r--r--boost/metaparse/v1/error/index_out_of_range.hpp41
-rw-r--r--boost/metaparse/v1/error/letter_expected.hpp26
-rw-r--r--boost/metaparse/v1/error/literal_expected.hpp36
-rw-r--r--boost/metaparse/v1/error/none_of_the_expected_cases_found.hpp29
-rw-r--r--boost/metaparse/v1/error/unexpected_character.hpp29
-rw-r--r--boost/metaparse/v1/error/unexpected_end_of_input.hpp30
-rw-r--r--boost/metaparse/v1/error/unpaired.hpp50
-rw-r--r--boost/metaparse/v1/error/whitespace_expected.hpp30
-rw-r--r--boost/metaparse/v1/except.hpp40
-rw-r--r--boost/metaparse/v1/fail.hpp30
-rw-r--r--boost/metaparse/v1/fail_at_first_char_expected.hpp58
-rw-r--r--boost/metaparse/v1/fail_tag.hpp42
-rw-r--r--boost/metaparse/v1/first_of.hpp35
-rw-r--r--boost/metaparse/v1/foldl.hpp65
-rw-r--r--boost/metaparse/v1/foldl1.hpp38
-rw-r--r--boost/metaparse/v1/foldl_reject_incomplete.hpp77
-rw-r--r--boost/metaparse/v1/foldl_reject_incomplete1.hpp38
-rw-r--r--boost/metaparse/v1/foldl_reject_incomplete_start_with_parser.hpp55
-rw-r--r--boost/metaparse/v1/foldl_start_with_parser.hpp45
-rw-r--r--boost/metaparse/v1/foldr.hpp25
-rw-r--r--boost/metaparse/v1/foldr1.hpp38
-rw-r--r--boost/metaparse/v1/foldr_reject_incomplete.hpp33
-rw-r--r--boost/metaparse/v1/foldr_reject_incomplete1.hpp38
-rw-r--r--boost/metaparse/v1/foldr_start_with_parser.hpp78
-rw-r--r--boost/metaparse/v1/fwd/accept.hpp22
-rw-r--r--boost/metaparse/v1/fwd/build_parser.hpp22
-rw-r--r--boost/metaparse/v1/fwd/get_col.hpp26
-rw-r--r--boost/metaparse/v1/fwd/get_line.hpp25
-rw-r--r--boost/metaparse/v1/fwd/get_message.hpp25
-rw-r--r--boost/metaparse/v1/fwd/get_position.hpp25
-rw-r--r--boost/metaparse/v1/fwd/get_prev_char.hpp25
-rw-r--r--boost/metaparse/v1/fwd/get_remaining.hpp25
-rw-r--r--boost/metaparse/v1/fwd/get_result.hpp25
-rw-r--r--boost/metaparse/v1/fwd/next_char.hpp25
-rw-r--r--boost/metaparse/v1/fwd/next_line.hpp25
-rw-r--r--boost/metaparse/v1/fwd/reject.hpp22
-rw-r--r--boost/metaparse/v1/fwd/source_position.hpp22
-rw-r--r--boost/metaparse/v1/fwd/string.hpp38
-rw-r--r--boost/metaparse/v1/get_col.hpp29
-rw-r--r--boost/metaparse/v1/get_line.hpp29
-rw-r--r--boost/metaparse/v1/get_message.hpp29
-rw-r--r--boost/metaparse/v1/get_position.hpp29
-rw-r--r--boost/metaparse/v1/get_prev_char.hpp29
-rw-r--r--boost/metaparse/v1/get_remaining.hpp29
-rw-r--r--boost/metaparse/v1/get_result.hpp29
-rw-r--r--boost/metaparse/v1/grammar.hpp386
-rw-r--r--boost/metaparse/v1/if_.hpp43
-rw-r--r--boost/metaparse/v1/impl/apply_parser.hpp63
-rw-r--r--boost/metaparse/v1/impl/assert_string_length.hpp31
-rw-r--r--boost/metaparse/v1/impl/at_c.hpp66
-rw-r--r--boost/metaparse/v1/impl/back_inserter.hpp32
-rw-r--r--boost/metaparse/v1/impl/concat.hpp106
-rw-r--r--boost/metaparse/v1/impl/empty_string.hpp44
-rw-r--r--boost/metaparse/v1/impl/front_inserter.hpp32
-rw-r--r--boost/metaparse/v1/impl/fwd/iterate_impl.hpp34
-rw-r--r--boost/metaparse/v1/impl/has_type.hpp26
-rw-r--r--boost/metaparse/v1/impl/is_any.hpp70
-rw-r--r--boost/metaparse/v1/impl/is_char_c.hpp33
-rw-r--r--boost/metaparse/v1/impl/iterate_impl.hpp46
-rw-r--r--boost/metaparse/v1/impl/iterate_impl_unchecked.hpp44
-rw-r--r--boost/metaparse/v1/impl/later_result.hpp39
-rw-r--r--boost/metaparse/v1/impl/next_digit.hpp36
-rw-r--r--boost/metaparse/v1/impl/no_char.hpp17
-rw-r--r--boost/metaparse/v1/impl/nth_of_c.hpp61
-rw-r--r--boost/metaparse/v1/impl/nth_of_c_impl.hpp77
-rw-r--r--boost/metaparse/v1/impl/one_char_except_not_used.hpp24
-rw-r--r--boost/metaparse/v1/impl/one_of.hpp44
-rw-r--r--boost/metaparse/v1/impl/one_of_fwd_op.hpp46
-rw-r--r--boost/metaparse/v1/impl/pop_back.hpp52
-rw-r--r--boost/metaparse/v1/impl/pop_front.hpp62
-rw-r--r--boost/metaparse/v1/impl/push_back_c.hpp40
-rw-r--r--boost/metaparse/v1/impl/push_front_c.hpp53
-rw-r--r--boost/metaparse/v1/impl/remove_trailing_no_chars.hpp57
-rw-r--r--boost/metaparse/v1/impl/returns.hpp28
-rw-r--r--boost/metaparse/v1/impl/sequence.hpp59
-rw-r--r--boost/metaparse/v1/impl/sequence_impl.hpp37
-rw-r--r--boost/metaparse/v1/impl/size.hpp69
-rw-r--r--boost/metaparse/v1/impl/skip_seq.hpp74
-rw-r--r--boost/metaparse/v1/impl/split_at_c.hpp101
-rw-r--r--boost/metaparse/v1/impl/string_iterator.hpp159
-rw-r--r--boost/metaparse/v1/impl/string_iterator_tag.hpp27
-rw-r--r--boost/metaparse/v1/impl/update_c.hpp93
-rw-r--r--boost/metaparse/v1/impl/void_.hpp25
-rw-r--r--boost/metaparse/v1/int_.hpp25
-rw-r--r--boost/metaparse/v1/is_error.hpp43
-rw-r--r--boost/metaparse/v1/iterate.hpp24
-rw-r--r--boost/metaparse/v1/iterate_c.hpp26
-rw-r--r--boost/metaparse/v1/keyword.hpp82
-rw-r--r--boost/metaparse/v1/last_of.hpp66
-rw-r--r--boost/metaparse/v1/letter.hpp29
-rw-r--r--boost/metaparse/v1/lit.hpp24
-rw-r--r--boost/metaparse/v1/lit_c.hpp34
-rw-r--r--boost/metaparse/v1/look_ahead.hpp50
-rw-r--r--boost/metaparse/v1/middle_of.hpp48
-rw-r--r--boost/metaparse/v1/next_char.hpp30
-rw-r--r--boost/metaparse/v1/next_line.hpp30
-rw-r--r--boost/metaparse/v1/nth_of.hpp39
-rw-r--r--boost/metaparse/v1/nth_of_c.hpp70
-rw-r--r--boost/metaparse/v1/one_char.hpp71
-rw-r--r--boost/metaparse/v1/one_char_except.hpp85
-rw-r--r--boost/metaparse/v1/one_char_except_c.hpp96
-rw-r--r--boost/metaparse/v1/one_of.hpp42
-rw-r--r--boost/metaparse/v1/one_of_c.hpp80
-rw-r--r--boost/metaparse/v1/optional.hpp40
-rw-r--r--boost/metaparse/v1/range.hpp33
-rw-r--r--boost/metaparse/v1/range_c.hpp33
-rw-r--r--boost/metaparse/v1/reject.hpp33
-rw-r--r--boost/metaparse/v1/repeated.hpp27
-rw-r--r--boost/metaparse/v1/repeated1.hpp29
-rw-r--r--boost/metaparse/v1/repeated_one_of.hpp45
-rw-r--r--boost/metaparse/v1/repeated_one_of1.hpp45
-rw-r--r--boost/metaparse/v1/repeated_reject_incomplete.hpp29
-rw-r--r--boost/metaparse/v1/repeated_reject_incomplete1.hpp29
-rw-r--r--boost/metaparse/v1/return_.hpp34
-rw-r--r--boost/metaparse/v1/sequence.hpp64
-rw-r--r--boost/metaparse/v1/sequence_apply.hpp80
-rw-r--r--boost/metaparse/v1/source_position.hpp156
-rw-r--r--boost/metaparse/v1/source_position_tag.hpp80
-rw-r--r--boost/metaparse/v1/space.hpp30
-rw-r--r--boost/metaparse/v1/spaces.hpp24
-rw-r--r--boost/metaparse/v1/start.hpp32
-rw-r--r--boost/metaparse/v1/string.hpp408
-rw-r--r--boost/metaparse/v1/string_tag.hpp24
-rw-r--r--boost/metaparse/v1/swap.hpp29
-rw-r--r--boost/metaparse/v1/token.hpp28
-rw-r--r--boost/metaparse/v1/transform.hpp50
-rw-r--r--boost/metaparse/v1/transform_error.hpp40
-rw-r--r--boost/metaparse/v1/transform_error_message.hpp49
-rw-r--r--boost/metaparse/v1/unless_error.hpp29
-rw-r--r--boost/metaparse/v1/util/digit_to_int.hpp38
-rw-r--r--boost/metaparse/v1/util/digit_to_int_c.hpp40
-rw-r--r--boost/metaparse/v1/util/in_range.hpp75
-rw-r--r--boost/metaparse/v1/util/in_range_c.hpp38
-rw-r--r--boost/metaparse/v1/util/int_to_digit.hpp38
-rw-r--r--boost/metaparse/v1/util/int_to_digit_c.hpp38
-rw-r--r--boost/metaparse/v1/util/is_digit.hpp38
-rw-r--r--boost/metaparse/v1/util/is_lcase_letter.hpp38
-rw-r--r--boost/metaparse/v1/util/is_letter.hpp44
-rw-r--r--boost/metaparse/v1/util/is_ucase_letter.hpp38
-rw-r--r--boost/metaparse/v1/util/is_whitespace.hpp38
-rw-r--r--boost/metaparse/v1/util/is_whitespace_c.hpp32
-rw-r--r--boost/metaparse/version.hpp14
-rw-r--r--boost/move/adl_move_swap.hpp47
-rw-r--r--boost/move/algo/adaptive_merge.hpp67
-rw-r--r--boost/move/algo/adaptive_sort.hpp63
-rw-r--r--boost/move/algo/detail/adaptive_sort_merge.hpp2284
-rw-r--r--boost/move/algo/detail/basic_op.hpp63
-rw-r--r--boost/move/algo/detail/bufferless_merge_sort.hpp120
-rw-r--r--boost/move/algo/detail/insertion_sort.hpp127
-rw-r--r--boost/move/algo/detail/merge.hpp444
-rw-r--r--boost/move/algo/detail/merge_sort.hpp124
-rw-r--r--boost/move/algo/move.hpp155
-rw-r--r--boost/move/algorithm.hpp117
-rw-r--r--boost/move/core.hpp23
-rw-r--r--boost/move/detail/config_begin.hpp2
-rw-r--r--boost/move/detail/destruct_n.hpp67
-rw-r--r--boost/move/detail/iterator_traits.hpp4
-rw-r--r--boost/move/detail/meta_utils.hpp39
-rw-r--r--boost/move/detail/move_helpers.hpp122
-rw-r--r--boost/move/detail/placement_new.hpp30
-rw-r--r--boost/move/detail/workaround.hpp13
-rw-r--r--boost/move/iterator.hpp65
-rw-r--r--boost/move/unique_ptr.hpp98
-rw-r--r--boost/move/utility.hpp15
-rw-r--r--boost/move/utility_core.hpp33
-rw-r--r--boost/mpi/communicator.hpp4
-rw-r--r--boost/mpi/detail/binary_buffer_iprimitive.hpp4
-rw-r--r--boost/mpi/detail/binary_buffer_oprimitive.hpp4
-rw-r--r--boost/mpi/detail/forward_iprimitive.hpp2
-rw-r--r--boost/mpi/detail/forward_oprimitive.hpp2
-rw-r--r--boost/mpi/detail/ignore_iprimitive.hpp2
-rw-r--r--boost/mpi/detail/ignore_oprimitive.hpp2
-rw-r--r--boost/mpi/detail/mpi_datatype_primitive.hpp2
-rw-r--r--boost/mpi/detail/packed_iprimitive.hpp4
-rw-r--r--boost/mpi/detail/packed_oprimitive.hpp2
-rw-r--r--boost/multiprecision/concepts/mp_number_archetypes.hpp4
-rw-r--r--boost/multiprecision/cpp_bin_float.hpp72
-rw-r--r--boost/multiprecision/cpp_dec_float.hpp18
-rw-r--r--boost/multiprecision/cpp_int.hpp6
-rw-r--r--boost/multiprecision/cpp_int/bitwise.hpp426
-rw-r--r--boost/multiprecision/cpp_int/import_export.hpp104
-rw-r--r--boost/multiprecision/debug_adaptor.hpp4
-rw-r--r--boost/multiprecision/detail/bitscan.hpp6
-rw-r--r--boost/multiprecision/detail/default_ops.hpp4
-rw-r--r--boost/multiprecision/detail/functions/pow.hpp9
-rw-r--r--boost/multiprecision/detail/min_max.hpp114
-rw-r--r--boost/multiprecision/detail/number_base.hpp37
-rw-r--r--boost/multiprecision/detail/number_compare.hpp6
-rw-r--r--boost/multiprecision/float128.hpp35
-rw-r--r--boost/multiprecision/mpfi.hpp4
-rw-r--r--boost/multiprecision/mpfr.hpp5
-rw-r--r--boost/multiprecision/number.hpp57
-rw-r--r--boost/multiprecision/tommath.hpp10
-rw-r--r--boost/none.hpp2
-rw-r--r--boost/none_t.hpp5
-rw-r--r--boost/operators.hpp452
-rw-r--r--boost/operators_v1.hpp951
-rw-r--r--boost/optional/detail/old_optional_implementation.hpp1059
-rw-r--r--boost/optional/detail/optional_aligned_storage.hpp75
-rw-r--r--boost/optional/detail/optional_config.hpp99
-rw-r--r--boost/optional/detail/optional_factory_support.hpp36
-rw-r--r--boost/optional/detail/optional_reference_spec.hpp203
-rw-r--r--boost/optional/detail/optional_relops.hpp196
-rw-r--r--boost/optional/detail/optional_swap.hpp117
-rw-r--r--boost/optional/optional.hpp657
-rw-r--r--boost/optional/optional_fwd.hpp13
-rw-r--r--boost/pending/relaxed_heap.hpp5
-rw-r--r--boost/pool/detail/mutex.hpp22
-rw-r--r--boost/predef/hardware/simd.h20
-rw-r--r--boost/predef/hardware/simd/x86.h6
-rw-r--r--boost/predef/hardware/simd/x86_amd.h8
-rw-r--r--boost/predef/hardware/simd/x86_amd/versions.h4
-rw-r--r--boost/predef/os/cygwin.h2
-rw-r--r--boost/predef/version.h4
-rw-r--r--boost/preprocessor/config/config.hpp2
-rw-r--r--boost/property_tree/detail/info_parser_read.hpp2
-rw-r--r--boost/property_tree/detail/json_parser/parser.hpp524
-rw-r--r--boost/property_tree/detail/json_parser/read.hpp55
-rw-r--r--boost/property_tree/detail/ptree_utils.hpp4
-rw-r--r--boost/property_tree/detail/xml_parser_utils.hpp12
-rw-r--r--boost/property_tree/detail/xml_parser_write.hpp18
-rw-r--r--boost/property_tree/detail/xml_parser_writer_settings.hpp6
-rw-r--r--boost/property_tree/json_parser.hpp6
-rw-r--r--boost/property_tree/json_parser/detail/narrow_encoding.hpp (renamed from boost/property_tree/detail/json_parser/narrow_encoding.hpp)13
-rw-r--r--boost/property_tree/json_parser/detail/parser.hpp530
-rw-r--r--boost/property_tree/json_parser/detail/read.hpp90
-rw-r--r--boost/property_tree/json_parser/detail/standard_callbacks.hpp (renamed from boost/property_tree/detail/json_parser/standard_callbacks.hpp)5
-rw-r--r--boost/property_tree/json_parser/detail/wide_encoding.hpp (renamed from boost/property_tree/detail/json_parser/wide_encoding.hpp)17
-rw-r--r--boost/property_tree/json_parser/detail/write.hpp (renamed from boost/property_tree/detail/json_parser_write.hpp)8
-rw-r--r--boost/property_tree/json_parser/error.hpp (renamed from boost/property_tree/detail/json_parser_error.hpp)0
-rw-r--r--boost/python/converter/registered.hpp5
-rw-r--r--boost/python/detail/def_helper.hpp1
-rw-r--r--boost/python/detail/wrap_python.hpp13
-rw-r--r--boost/python/object/class_metadata.hpp12
-rw-r--r--boost/random/uniform_on_sphere.hpp1
-rw-r--r--boost/range/const_iterator.hpp8
-rw-r--r--boost/regex/config.hpp2
-rw-r--r--boost/regex/v4/basic_regex_parser.hpp2
-rw-r--r--boost/regex/v4/fileiter.hpp4
-rw-r--r--boost/regex/v4/match_flags.hpp3
-rw-r--r--boost/regex/v4/mem_block_cache.hpp46
-rw-r--r--boost/serialization/archive_input_unordered_map.hpp16
-rw-r--r--boost/serialization/archive_input_unordered_set.hpp19
-rw-r--r--boost/serialization/array.hpp90
-rw-r--r--boost/serialization/assume_abstract.hpp1
-rw-r--r--boost/serialization/base_object.hpp1
-rw-r--r--boost/serialization/collection_traits.hpp2
-rw-r--r--boost/serialization/detail/stack_constructor.hpp1
-rw-r--r--boost/serialization/export.hpp2
-rw-r--r--boost/serialization/forward_list.hpp13
-rw-r--r--boost/serialization/is_bitwise_serializable.hpp2
-rw-r--r--boost/serialization/map.hpp9
-rw-r--r--boost/serialization/nvp.hpp32
-rw-r--r--boost/serialization/set.hpp7
-rw-r--r--boost/serialization/singleton.hpp26
-rw-r--r--boost/serialization/static_warning.hpp1
-rw-r--r--boost/serialization/traits.hpp2
-rw-r--r--boost/serialization/unique_ptr.hpp4
-rw-r--r--boost/serialization/valarray.hpp18
-rw-r--r--boost/serialization/vector.hpp6
-rw-r--r--boost/serialization/vector_135.hpp2
-rw-r--r--boost/serialization/wrapper.hpp2
-rw-r--r--boost/signals2/detail/variadic_slot_invoker.hpp12
-rw-r--r--boost/smart_ptr/detail/up_if_array.hpp26
-rw-r--r--boost/smart_ptr/detail/up_if_not_array.hpp31
-rw-r--r--boost/smart_ptr/make_unique.hpp108
-rw-r--r--boost/smart_ptr/make_unique_array.hpp31
-rw-r--r--boost/smart_ptr/make_unique_object.hpp45
-rw-r--r--boost/smart_ptr/shared_ptr.hpp2
-rw-r--r--boost/sort/spreadsort/detail/string_sort.hpp2
-rw-r--r--boost/spirit/home/classic/core/non_terminal/impl/grammar.ipp6
-rw-r--r--boost/spirit/home/classic/core/non_terminal/impl/rule.ipp1
-rw-r--r--boost/spirit/home/classic/core/non_terminal/impl/subrule.ipp2
-rw-r--r--boost/spirit/home/classic/core/non_terminal/subrule.hpp3
-rw-r--r--boost/spirit/home/classic/iterator/position_iterator.hpp2
-rw-r--r--boost/spirit/home/classic/tree/parse_tree_utils.hpp2
-rw-r--r--boost/spirit/home/qi/string/tst_map.hpp3
-rw-r--r--boost/spirit/home/support/extended_variant.hpp5
-rw-r--r--boost/spirit/home/support/terminal.hpp11
-rw-r--r--boost/spirit/home/x3/auxiliary/eol.hpp2
-rw-r--r--boost/spirit/home/x3/binary/binary.hpp1
-rw-r--r--boost/spirit/home/x3/char/any_char.hpp2
-rw-r--r--boost/spirit/home/x3/core/parse.hpp3
-rw-r--r--boost/spirit/home/x3/directive/expect.hpp32
-rw-r--r--boost/spirit/home/x3/directive/with.hpp2
-rw-r--r--boost/spirit/home/x3/nonterminal/detail/rule.hpp23
-rw-r--r--boost/spirit/home/x3/nonterminal/detail/transform_attribute.hpp8
-rw-r--r--boost/spirit/home/x3/nonterminal/simple_trace.hpp2
-rw-r--r--boost/spirit/home/x3/operator/detail/sequence.hpp26
-rw-r--r--boost/spirit/home/x3/string/literal_string.hpp16
-rw-r--r--boost/spirit/home/x3/string/symbols.hpp4
-rw-r--r--boost/spirit/home/x3/support/ast/variant.hpp5
-rw-r--r--boost/spirit/home/x3/support/traits/container_traits.hpp87
-rw-r--r--boost/spirit/home/x3/support/traits/move_to.hpp32
-rw-r--r--boost/test/data/for_each_sample.hpp54
-rw-r--r--boost/test/data/index_sequence.hpp62
-rw-r--r--boost/test/data/monomorphic/fwd.hpp3
-rw-r--r--boost/test/data/monomorphic/grid.hpp71
-rw-r--r--boost/test/data/monomorphic/sample_merge.hpp103
-rw-r--r--boost/test/data/monomorphic/zip.hpp64
-rw-r--r--boost/test/data/test_case.hpp114
-rw-r--r--boost/test/data/traits.hpp87
-rw-r--r--boost/test/impl/debug.ipp44
-rw-r--r--boost/test/impl/execution_monitor.ipp12
-rw-r--r--boost/test/impl/framework.ipp20
-rw-r--r--boost/test/impl/xml_report_formatter.ipp2
-rw-r--r--boost/test/tools/collection_comparison_op.hpp10
-rw-r--r--boost/test/tools/detail/print_helper.hpp6
-rw-r--r--boost/test/tools/interface.hpp21
-rw-r--r--boost/test/utils/named_params.hpp2
-rw-r--r--boost/thread/future.hpp147
-rw-r--r--boost/thread/futures/launch.hpp1
-rw-r--r--boost/thread/pthread/condition_variable.hpp7
-rw-r--r--boost/thread/scoped_thread.hpp3
-rw-r--r--boost/thread/win32/thread_primitives.hpp6
-rw-r--r--boost/type_index/stl_type_index.hpp4
-rw-r--r--boost/type_traits.hpp256
-rw-r--r--boost/type_traits/add_reference.hpp6
-rw-r--r--boost/type_traits/aligned_storage.hpp12
-rw-r--r--boost/type_traits/common_type.hpp1
-rw-r--r--boost/type_traits/detail/common_arithmetic_type.hpp6
-rw-r--r--boost/type_traits/detail/mp_defer.hpp6
-rw-r--r--boost/type_traits/has_nothrow_assign.hpp2
-rw-r--r--boost/type_traits/has_nothrow_constructor.hpp2
-rw-r--r--boost/type_traits/has_trivial_assign.hpp2
-rw-r--r--boost/type_traits/has_trivial_destructor.hpp2
-rw-r--r--boost/type_traits/is_default_constructible.hpp21
-rw-r--r--boost/type_traits/is_nothrow_move_assignable.hpp2
-rw-r--r--boost/type_traits/is_nothrow_move_constructible.hpp2
-rw-r--r--boost/units/io.hpp2
-rw-r--r--boost/utility/string_view.hpp670
-rw-r--r--boost/utility/string_view_fwd.hpp39
-rw-r--r--boost/variant/recursive_wrapper_fwd.hpp1
-rw-r--r--boost/version.hpp4
1681 files changed, 120993 insertions, 9513 deletions
diff --git a/boost/align.hpp b/boost/align.hpp
index ce8f78d343..89eebe1a77 100644
--- a/boost/align.hpp
+++ b/boost/align.hpp
@@ -10,6 +10,8 @@ http://boost.org/LICENSE_1_0.txt
#define BOOST_ALIGN_HPP
#include <boost/align/align.hpp>
+#include <boost/align/align_down.hpp>
+#include <boost/align/align_up.hpp>
#include <boost/align/aligned_alloc.hpp>
#include <boost/align/aligned_allocator.hpp>
#include <boost/align/aligned_allocator_adaptor.hpp>
diff --git a/boost/align/align.hpp b/boost/align/align.hpp
index 648a65e295..3582dcc051 100644
--- a/boost/align/align.hpp
+++ b/boost/align/align.hpp
@@ -1,5 +1,5 @@
/*
-(c) 2014 Glen Joseph Fernandes
+(c) 2014-2015 Glen Joseph Fernandes
<glenjofe -at- gmail.com>
Distributed under the Boost Software
diff --git a/boost/align/align_down.hpp b/boost/align/align_down.hpp
new file mode 100644
index 0000000000..f437f8e5b3
--- /dev/null
+++ b/boost/align/align_down.hpp
@@ -0,0 +1,27 @@
+/*
+(c) 2015 Glen Joseph Fernandes
+<glenjofe -at- gmail.com>
+
+Distributed under the Boost Software
+License, Version 1.0.
+http://boost.org/LICENSE_1_0.txt
+*/
+#ifndef BOOST_ALIGN_ALIGN_DOWN_HPP
+#define BOOST_ALIGN_ALIGN_DOWN_HPP
+
+#include <boost/align/detail/align_down.hpp>
+#include <boost/align/align_down_forward.hpp>
+
+namespace boost {
+namespace alignment {
+
+BOOST_CONSTEXPR inline std::size_t align_down(std::size_t value,
+ std::size_t alignment) BOOST_NOEXCEPT
+{
+ return value & ~(alignment - 1);
+}
+
+} /* .alignment */
+} /* .boost */
+
+#endif
diff --git a/boost/align/align_down_forward.hpp b/boost/align/align_down_forward.hpp
new file mode 100644
index 0000000000..6d124e8901
--- /dev/null
+++ b/boost/align/align_down_forward.hpp
@@ -0,0 +1,24 @@
+/*
+(c) 2015 Glen Joseph Fernandes
+<glenjofe -at- gmail.com>
+
+Distributed under the Boost Software
+License, Version 1.0.
+http://boost.org/LICENSE_1_0.txt
+*/
+#ifndef BOOST_ALIGN_ALIGN_DOWN_FORWARD_HPP
+#define BOOST_ALIGN_ALIGN_DOWN_FORWARD_HPP
+
+#include <boost/config.hpp>
+#include <cstddef>
+
+namespace boost {
+namespace alignment {
+
+BOOST_CONSTEXPR std::size_t align_down(std::size_t value,
+ std::size_t alignment) BOOST_NOEXCEPT;
+
+} /* .alignment */
+} /* .boost */
+
+#endif
diff --git a/boost/align/align_up.hpp b/boost/align/align_up.hpp
new file mode 100644
index 0000000000..b1cec1911e
--- /dev/null
+++ b/boost/align/align_up.hpp
@@ -0,0 +1,27 @@
+/*
+(c) 2015 Glen Joseph Fernandes
+<glenjofe -at- gmail.com>
+
+Distributed under the Boost Software
+License, Version 1.0.
+http://boost.org/LICENSE_1_0.txt
+*/
+#ifndef BOOST_ALIGN_ALIGN_UP_HPP
+#define BOOST_ALIGN_ALIGN_UP_HPP
+
+#include <boost/align/detail/align_up.hpp>
+#include <boost/align/align_up_forward.hpp>
+
+namespace boost {
+namespace alignment {
+
+BOOST_CONSTEXPR inline std::size_t align_up(std::size_t value,
+ std::size_t alignment) BOOST_NOEXCEPT
+{
+ return (value + alignment - 1) & ~(alignment - 1);
+}
+
+} /* .alignment */
+} /* .boost */
+
+#endif
diff --git a/boost/align/align_up_forward.hpp b/boost/align/align_up_forward.hpp
new file mode 100644
index 0000000000..47fdfcd0ba
--- /dev/null
+++ b/boost/align/align_up_forward.hpp
@@ -0,0 +1,24 @@
+/*
+(c) 2015 Glen Joseph Fernandes
+<glenjofe -at- gmail.com>
+
+Distributed under the Boost Software
+License, Version 1.0.
+http://boost.org/LICENSE_1_0.txt
+*/
+#ifndef BOOST_ALIGN_ALIGN_UP_FORWARD_HPP
+#define BOOST_ALIGN_ALIGN_UP_FORWARD_HPP
+
+#include <boost/config.hpp>
+#include <cstddef>
+
+namespace boost {
+namespace alignment {
+
+BOOST_CONSTEXPR std::size_t align_up(std::size_t value,
+ std::size_t alignment) BOOST_NOEXCEPT;
+
+} /* .alignment */
+} /* .boost */
+
+#endif
diff --git a/boost/align/aligned_alloc.hpp b/boost/align/aligned_alloc.hpp
index b70f4bc632..7f2c0bb363 100644
--- a/boost/align/aligned_alloc.hpp
+++ b/boost/align/aligned_alloc.hpp
@@ -1,5 +1,5 @@
/*
-(c) 2014 Glen Joseph Fernandes
+(c) 2014-2015 Glen Joseph Fernandes
<glenjofe -at- gmail.com>
Distributed under the Boost Software
@@ -19,7 +19,9 @@ http://boost.org/LICENSE_1_0.txt
#include <AvailabilityMacros.h>
#endif
-#if defined(_MSC_VER)
+#if defined(BOOST_ALIGN_USE_ALLOCATE)
+#include <boost/align/detail/aligned_alloc.hpp>
+#elif defined(_MSC_VER) && !defined(UNDER_CE)
#include <boost/align/detail/aligned_alloc_msvc.hpp>
#elif defined(__MINGW32__) && (__MSVCRT_VERSION__ >= 0x0700)
#include <boost/align/detail/aligned_alloc_msvc.hpp>
diff --git a/boost/align/aligned_allocator.hpp b/boost/align/aligned_allocator.hpp
index 9655e3dfb2..83af070c7a 100644
--- a/boost/align/aligned_allocator.hpp
+++ b/boost/align/aligned_allocator.hpp
@@ -9,16 +9,15 @@ http://boost.org/LICENSE_1_0.txt
#ifndef BOOST_ALIGN_ALIGNED_ALLOCATOR_HPP
#define BOOST_ALIGN_ALIGNED_ALLOCATOR_HPP
-#include <boost/config.hpp>
-#include <boost/static_assert.hpp>
-#include <boost/throw_exception.hpp>
-#include <boost/align/aligned_alloc.hpp>
-#include <boost/align/aligned_allocator_forward.hpp>
-#include <boost/align/alignment_of.hpp>
#include <boost/align/detail/addressof.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/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)
@@ -72,15 +71,17 @@ public:
return detail::addressof(value);
}
- const_pointer address(const_reference value) const
- BOOST_NOEXCEPT {
+ const_pointer address(const_reference value) const BOOST_NOEXCEPT {
return detail::addressof(value);
}
pointer allocate(size_type size, const_void_pointer = 0) {
- void* p = aligned_alloc(min_align, sizeof(T) * size);
- if (size > 0 && !p) {
- ::boost::throw_exception(std::bad_alloc());
+ void* p = 0;
+ if (size > 0) {
+ p = aligned_alloc(min_align, sizeof(T) * size);
+ if (!p) {
+ ::boost::throw_exception(std::bad_alloc());
+ }
}
return static_cast<T*>(p);
}
@@ -97,28 +98,24 @@ public:
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class U, class... Args>
void construct(U* ptr, Args&&... args) {
- void* p = ptr;
- ::new(p) U(std::forward<Args>(args)...);
+ ::new(static_cast<void*>(ptr)) U(std::forward<Args>(args)...);
}
#else
template<class U, class V>
void construct(U* ptr, V&& value) {
- void* p = ptr;
- ::new(p) U(std::forward<V>(value));
+ ::new(static_cast<void*>(ptr)) U(std::forward<V>(value));
}
#endif
#else
template<class U, class V>
void construct(U* ptr, const V& value) {
- void* p = ptr;
- ::new(p) U(value);
+ ::new(static_cast<void*>(ptr)) U(value);
}
#endif
template<class U>
void construct(U* ptr) {
- void* p = ptr;
- ::new(p) U();
+ ::new(static_cast<void*>(ptr)) U();
}
template<class U>
@@ -145,17 +142,15 @@ public:
};
template<class T1, class T2, std::size_t Alignment>
-inline bool operator==(const aligned_allocator<T1,
- Alignment>&, const aligned_allocator<T2,
- Alignment>&) BOOST_NOEXCEPT
+inline bool operator==(const aligned_allocator<T1, Alignment>&,
+ const aligned_allocator<T2, Alignment>&) BOOST_NOEXCEPT
{
return true;
}
template<class T1, class T2, std::size_t Alignment>
-inline bool operator!=(const aligned_allocator<T1,
- Alignment>&, const aligned_allocator<T2,
- Alignment>&) BOOST_NOEXCEPT
+inline bool operator!=(const aligned_allocator<T1, Alignment>&,
+ const aligned_allocator<T2, Alignment>&) BOOST_NOEXCEPT
{
return false;
}
diff --git a/boost/align/aligned_allocator_adaptor.hpp b/boost/align/aligned_allocator_adaptor.hpp
index 19777173f1..29d13874ad 100644
--- a/boost/align/aligned_allocator_adaptor.hpp
+++ b/boost/align/aligned_allocator_adaptor.hpp
@@ -9,15 +9,14 @@ http://boost.org/LICENSE_1_0.txt
#ifndef BOOST_ALIGN_ALIGNED_ALLOCATOR_ADAPTOR_HPP
#define BOOST_ALIGN_ALIGNED_ALLOCATOR_ADAPTOR_HPP
-#include <boost/config.hpp>
-#include <boost/static_assert.hpp>
-#include <boost/align/align.hpp>
-#include <boost/align/aligned_allocator_adaptor_forward.hpp>
-#include <boost/align/alignment_of.hpp>
#include <boost/align/detail/addressof.hpp>
#include <boost/align/detail/is_alignment_constant.hpp>
#include <boost/align/detail/max_align.hpp>
#include <boost/align/detail/max_size.hpp>
+#include <boost/align/align.hpp>
+#include <boost/align/aligned_allocator_adaptor_forward.hpp>
+#include <boost/align/alignment_of.hpp>
+#include <boost/static_assert.hpp>
#include <new>
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
@@ -54,10 +53,6 @@ class aligned_allocator_adaptor
typedef typename char_alloc::pointer char_ptr;
#endif
- enum {
- ptr_align = alignment_of<char_ptr>::value
- };
-
public:
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
typedef typename traits::value_type value_type;
@@ -127,44 +122,44 @@ public:
}
pointer allocate(size_type size) {
- std::size_t n1 = size * sizeof(value_type);
- std::size_t n2 = n1 + min_align - ptr_align;
+ std::size_t s = size * sizeof(value_type);
+ std::size_t n = s + min_align - 1;
char_alloc a(base());
- char_ptr p1 = a.allocate(sizeof p1 + n2);
- void* p2 = detail::addressof(*p1) + sizeof p1;
- (void)align(min_align, n1, p2, n2);
- void* p3 = static_cast<char_ptr*>(p2) - 1;
- ::new(p3) char_ptr(p1);
- return static_cast<pointer>(p2);
+ char_ptr p = a.allocate(sizeof p + n);
+ void* r = detail::addressof(*p) + sizeof p;
+ (void)align(min_align, s, r, n);
+ ::new(static_cast<void*>(static_cast<char_ptr*>(r) -
+ 1)) char_ptr(p);
+ return static_cast<pointer>(r);
}
pointer allocate(size_type size, const_void_pointer hint) {
- std::size_t n1 = size * sizeof(value_type);
- std::size_t n2 = n1 + min_align - ptr_align;
+ std::size_t s = size * sizeof(value_type);
+ std::size_t n = s + min_align - 1;
char_ptr h = char_ptr();
if (hint) {
h = *(static_cast<const char_ptr*>(hint) - 1);
}
char_alloc a(base());
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
- char_ptr p1 = char_traits::allocate(a, sizeof p1 + n2, h);
+ char_ptr p = char_traits::allocate(a, sizeof p + n, h);
#else
- char_ptr p1 = a.allocate(sizeof p1 + n2, h);
+ char_ptr p = a.allocate(sizeof p + n, h);
#endif
- void* p2 = detail::addressof(*p1) + sizeof p1;
- (void)align(min_align, n1, p2, n2);
- void* p3 = static_cast<char_ptr*>(p2) - 1;
- ::new(p3) char_ptr(p1);
- return static_cast<pointer>(p2);
+ void* r = detail::addressof(*p) + sizeof p;
+ (void)align(min_align, s, r, n);
+ ::new(static_cast<void*>(static_cast<char_ptr*>(r) -
+ 1)) char_ptr(p);
+ return static_cast<pointer>(r);
}
void deallocate(pointer ptr, size_type size) {
- char_ptr* p1 = reinterpret_cast<char_ptr*>(ptr) - 1;
- char_ptr p2 = *p1;
- p1->~char_ptr();
+ char_ptr* p = reinterpret_cast<char_ptr*>(ptr) - 1;
+ char_ptr r = *p;
+ p->~char_ptr();
char_alloc a(base());
- a.deallocate(p2, size * sizeof(value_type) +
- min_align - ptr_align + sizeof p2);
+ a.deallocate(r, sizeof r + size * sizeof(value_type) +
+ min_align - 1);
}
};
diff --git a/boost/align/aligned_delete.hpp b/boost/align/aligned_delete.hpp
index c8ad64e4da..6db2bd80d0 100644
--- a/boost/align/aligned_delete.hpp
+++ b/boost/align/aligned_delete.hpp
@@ -1,5 +1,5 @@
/*
-(c) 2014 Glen Joseph Fernandes
+(c) 2014-2015 Glen Joseph Fernandes
<glenjofe -at- gmail.com>
Distributed under the Boost Software
@@ -9,15 +9,13 @@ http://boost.org/LICENSE_1_0.txt
#ifndef BOOST_ALIGN_ALIGNED_DELETE_HPP
#define BOOST_ALIGN_ALIGNED_DELETE_HPP
-#include <boost/config.hpp>
#include <boost/align/aligned_alloc.hpp>
#include <boost/align/aligned_delete_forward.hpp>
namespace boost {
namespace alignment {
-class aligned_delete {
-public:
+struct aligned_delete {
template<class T>
void operator()(T* ptr) const
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(ptr->~T())) {
diff --git a/boost/align/aligned_delete_forward.hpp b/boost/align/aligned_delete_forward.hpp
index 375e576cb5..7334bebdef 100644
--- a/boost/align/aligned_delete_forward.hpp
+++ b/boost/align/aligned_delete_forward.hpp
@@ -1,5 +1,5 @@
/*
-(c) 2014 Glen Joseph Fernandes
+(c) 2014-2015 Glen Joseph Fernandes
<glenjofe -at- gmail.com>
Distributed under the Boost Software
@@ -12,7 +12,7 @@ http://boost.org/LICENSE_1_0.txt
namespace boost {
namespace alignment {
-class aligned_delete;
+struct aligned_delete;
} /* .alignment */
} /* .boost */
diff --git a/boost/align/alignment_of.hpp b/boost/align/alignment_of.hpp
index 2531ced105..fee91838af 100644
--- a/boost/align/alignment_of.hpp
+++ b/boost/align/alignment_of.hpp
@@ -9,9 +9,8 @@ http://boost.org/LICENSE_1_0.txt
#ifndef BOOST_ALIGN_ALIGNMENT_OF_HPP
#define BOOST_ALIGN_ALIGNMENT_OF_HPP
-#include <boost/config.hpp>
+#include <boost/align/detail/element_type.hpp>
#include <boost/align/alignment_of_forward.hpp>
-#include <boost/align/detail/remove_traits.hpp>
#if defined(BOOST_MSVC)
#include <boost/align/detail/alignment_of_msvc.hpp>
@@ -41,12 +40,14 @@ namespace alignment {
template<class T>
struct alignment_of
: detail::alignment_of<typename
- detail::remove_cv<typename
- detail::remove_all_extents<typename
- detail::remove_reference<T>::
- type>::type>::type>::type {
+ detail::element_type<T>::type>::type {
};
+#if !defined(BOOST_NO_CXX14_VARIABLE_TEMPLATES)
+template<class T>
+constexpr std::size_t alignment_of_v = alignment_of<T>::value;
+#endif
+
} /* .alignment */
} /* .boost */
diff --git a/boost/align/detail/address.hpp b/boost/align/detail/address.hpp
deleted file mode 100644
index b38e571534..0000000000
--- a/boost/align/detail/address.hpp
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
-(c) 2014 Glen Joseph Fernandes
-<glenjofe -at- gmail.com>
-
-Distributed under the Boost Software
-License, Version 1.0.
-http://boost.org/LICENSE_1_0.txt
-*/
-#ifndef BOOST_ALIGN_DETAIL_ADDRESS_HPP
-#define BOOST_ALIGN_DETAIL_ADDRESS_HPP
-
-#include <boost/cstdint.hpp>
-#include <cstddef>
-
-namespace boost {
-namespace alignment {
-namespace detail {
-
-#if defined(BOOST_HAS_INTPTR_T)
-typedef boost::uintptr_t address;
-#else
-typedef std::size_t address;
-#endif
-
-} /* .detail */
-} /* .alignment */
-} /* .boost */
-
-#endif
diff --git a/boost/align/detail/align.hpp b/boost/align/detail/align.hpp
index d2404b3e6d..0828c58365 100644
--- a/boost/align/detail/align.hpp
+++ b/boost/align/detail/align.hpp
@@ -9,10 +9,8 @@ http://boost.org/LICENSE_1_0.txt
#ifndef BOOST_ALIGN_DETAIL_ALIGN_HPP
#define BOOST_ALIGN_DETAIL_ALIGN_HPP
-#include <boost/assert.hpp>
-#include <boost/align/detail/address.hpp>
#include <boost/align/detail/is_alignment.hpp>
-#include <cstddef>
+#include <boost/assert.hpp>
namespace boost {
namespace alignment {
@@ -21,17 +19,17 @@ inline void* align(std::size_t alignment, std::size_t size,
void*& ptr, std::size_t& space)
{
BOOST_ASSERT(detail::is_alignment(alignment));
- std::size_t n = detail::address(ptr) & (alignment - 1);
- if (n != 0) {
- n = alignment - n;
- }
- void* p = 0;
- if (n <= space && size <= space - n) {
- p = static_cast<char*>(ptr) + n;
- ptr = p;
- space -= n;
+ if (size <= space) {
+ char* p = reinterpret_cast<char*>((reinterpret_cast<std::
+ size_t>(ptr) + alignment - 1) & ~(alignment - 1));
+ std::ptrdiff_t n = p - static_cast<char*>(ptr);
+ if (size <= space - n) {
+ ptr = p;
+ space -= n;
+ return p;
+ }
}
- return p;
+ return 0;
}
} /* .alignment */
diff --git a/boost/align/detail/align_down.hpp b/boost/align/detail/align_down.hpp
new file mode 100644
index 0000000000..a7a72efaf9
--- /dev/null
+++ b/boost/align/detail/align_down.hpp
@@ -0,0 +1,29 @@
+/*
+(c) 2015 Glen Joseph Fernandes
+<glenjofe -at- gmail.com>
+
+Distributed under the Boost Software
+License, Version 1.0.
+http://boost.org/LICENSE_1_0.txt
+*/
+#ifndef BOOST_ALIGN_DETAIL_ALIGN_DOWN_HPP
+#define BOOST_ALIGN_DETAIL_ALIGN_DOWN_HPP
+
+#include <boost/align/detail/is_alignment.hpp>
+#include <boost/align/align_down_forward.hpp>
+#include <boost/assert.hpp>
+
+namespace boost {
+namespace alignment {
+
+inline void* align_down(void* ptr, std::size_t alignment) BOOST_NOEXCEPT
+{
+ BOOST_ASSERT(detail::is_alignment(alignment));
+ return reinterpret_cast<void*>(align_down(reinterpret_cast<std::
+ size_t>(ptr), alignment));
+}
+
+} /* .alignment */
+} /* .boost */
+
+#endif
diff --git a/boost/align/detail/align_up.hpp b/boost/align/detail/align_up.hpp
new file mode 100644
index 0000000000..d52e0993ce
--- /dev/null
+++ b/boost/align/detail/align_up.hpp
@@ -0,0 +1,29 @@
+/*
+(c) 2015 Glen Joseph Fernandes
+<glenjofe -at- gmail.com>
+
+Distributed under the Boost Software
+License, Version 1.0.
+http://boost.org/LICENSE_1_0.txt
+*/
+#ifndef BOOST_ALIGN_DETAIL_ALIGN_UP_HPP
+#define BOOST_ALIGN_DETAIL_ALIGN_UP_HPP
+
+#include <boost/align/detail/is_alignment.hpp>
+#include <boost/align/align_up_forward.hpp>
+#include <boost/assert.hpp>
+
+namespace boost {
+namespace alignment {
+
+inline void* align_up(void* ptr, std::size_t alignment) BOOST_NOEXCEPT
+{
+ BOOST_ASSERT(detail::is_alignment(alignment));
+ return reinterpret_cast<void*>(align_up(reinterpret_cast<std::
+ size_t>(ptr), alignment));
+}
+
+} /* .alignment */
+} /* .boost */
+
+#endif
diff --git a/boost/align/detail/aligned_alloc.hpp b/boost/align/detail/aligned_alloc.hpp
index 28c0d2938e..0488847bbd 100644
--- a/boost/align/detail/aligned_alloc.hpp
+++ b/boost/align/detail/aligned_alloc.hpp
@@ -9,11 +9,10 @@ http://boost.org/LICENSE_1_0.txt
#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_HPP
#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_HPP
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
+#include <boost/align/detail/is_alignment.hpp>
#include <boost/align/align.hpp>
#include <boost/align/alignment_of.hpp>
-#include <boost/align/detail/is_alignment.hpp>
+#include <boost/assert.hpp>
#include <cstdlib>
namespace boost {
@@ -24,27 +23,26 @@ inline void* aligned_alloc(std::size_t alignment, std::size_t size)
{
BOOST_ASSERT(detail::is_alignment(alignment));
enum {
- N = alignment_of<void*>::value
+ min_align = alignment_of<void*>::value
};
- if (alignment < N) {
- alignment = N;
+ if (alignment < min_align) {
+ alignment = min_align;
}
- std::size_t n = size + alignment - N;
- void* p1 = 0;
- void* p2 = std::malloc(n + sizeof p1);
- if (p2) {
- p1 = static_cast<char*>(p2) + sizeof p1;
- (void)align(alignment, size, p1, n);
- *(static_cast<void**>(p1) - 1) = p2;
+ std::size_t n = size + alignment - min_align;
+ void* r = 0;
+ void* p = std::malloc(sizeof(void*) + n);
+ if (p) {
+ r = static_cast<char*>(p) + sizeof p;
+ (void)align(alignment, size, r, n);
+ *(static_cast<void**>(r) - 1) = p;
}
- return p1;
+ return r;
}
inline void aligned_free(void* ptr) BOOST_NOEXCEPT
{
if (ptr) {
- void* p = *(static_cast<void**>(ptr) - 1);
- std::free(p);
+ std::free(*(static_cast<void**>(ptr) - 1));
}
}
diff --git a/boost/align/detail/aligned_alloc_android.hpp b/boost/align/detail/aligned_alloc_android.hpp
index 2381d8be9c..0ed28a45eb 100644
--- a/boost/align/detail/aligned_alloc_android.hpp
+++ b/boost/align/detail/aligned_alloc_android.hpp
@@ -9,10 +9,8 @@ http://boost.org/LICENSE_1_0.txt
#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_ANDROID_HPP
#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_ANDROID_HPP
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
#include <boost/align/detail/is_alignment.hpp>
-#include <cstddef>
+#include <boost/assert.hpp>
#include <malloc.h>
namespace boost {
diff --git a/boost/align/detail/aligned_alloc_macos.hpp b/boost/align/detail/aligned_alloc_macos.hpp
index da3270b084..0bdb7c2eb1 100644
--- a/boost/align/detail/aligned_alloc_macos.hpp
+++ b/boost/align/detail/aligned_alloc_macos.hpp
@@ -9,10 +9,8 @@ http://boost.org/LICENSE_1_0.txt
#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_MACOS_HPP
#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_MACOS_HPP
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
#include <boost/align/detail/is_alignment.hpp>
-#include <cstddef>
+#include <boost/assert.hpp>
#include <stdlib.h>
namespace boost {
diff --git a/boost/align/detail/aligned_alloc_msvc.hpp b/boost/align/detail/aligned_alloc_msvc.hpp
index 92f4291893..abeccfc4e4 100644
--- a/boost/align/detail/aligned_alloc_msvc.hpp
+++ b/boost/align/detail/aligned_alloc_msvc.hpp
@@ -9,10 +9,8 @@ http://boost.org/LICENSE_1_0.txt
#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_MSVC_HPP
#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_MSVC_HPP
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
#include <boost/align/detail/is_alignment.hpp>
-#include <cstddef>
+#include <boost/assert.hpp>
#include <malloc.h>
namespace boost {
diff --git a/boost/align/detail/aligned_alloc_posix.hpp b/boost/align/detail/aligned_alloc_posix.hpp
index df64d75da3..931b0c4bd6 100644
--- a/boost/align/detail/aligned_alloc_posix.hpp
+++ b/boost/align/detail/aligned_alloc_posix.hpp
@@ -9,10 +9,8 @@ http://boost.org/LICENSE_1_0.txt
#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_POSIX_HPP
#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_POSIX_HPP
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
#include <boost/align/detail/is_alignment.hpp>
-#include <cstddef>
+#include <boost/assert.hpp>
#include <stdlib.h>
namespace boost {
diff --git a/boost/align/detail/aligned_alloc_sunos.hpp b/boost/align/detail/aligned_alloc_sunos.hpp
index 0114597bad..5039c733c6 100644
--- a/boost/align/detail/aligned_alloc_sunos.hpp
+++ b/boost/align/detail/aligned_alloc_sunos.hpp
@@ -9,10 +9,8 @@ http://boost.org/LICENSE_1_0.txt
#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_SUNOS_HPP
#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_SUNOS_HPP
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
#include <boost/align/detail/is_alignment.hpp>
-#include <cstddef>
+#include <boost/assert.hpp>
#include <stdlib.h>
namespace boost {
diff --git a/boost/align/detail/assume_aligned.hpp b/boost/align/detail/assume_aligned.hpp
index cf77086624..a1c632b94d 100644
--- a/boost/align/detail/assume_aligned.hpp
+++ b/boost/align/detail/assume_aligned.hpp
@@ -12,6 +12,6 @@ http://boost.org/LICENSE_1_0.txt
#ifndef BOOST_ALIGN_DETAIL_ASSUME_ALIGNED_HPP
#define BOOST_ALIGN_DETAIL_ASSUME_ALIGNED_HPP
-#define BOOST_ALIGN_ASSUME_ALIGNED(ptr, alignment)
+#define BOOST_ALIGN_ASSUME_ALIGNED(p, n)
#endif
diff --git a/boost/align/detail/assume_aligned_clang.hpp b/boost/align/detail/assume_aligned_clang.hpp
index 2ba41c6970..76046efd6d 100644
--- a/boost/align/detail/assume_aligned_clang.hpp
+++ b/boost/align/detail/assume_aligned_clang.hpp
@@ -10,10 +10,10 @@ http://boost.org/LICENSE_1_0.txt
#define BOOST_ALIGN_DETAIL_ASSUME_ALIGNED_CLANG_HPP
#if __has_builtin(__builtin_assume_aligned)
-#define BOOST_ALIGN_ASSUME_ALIGNED(ptr, alignment) \
-(ptr) = __builtin_assume_aligned((ptr), (alignment))
+#define BOOST_ALIGN_ASSUME_ALIGNED(p, n) \
+(p) = static_cast<__typeof__(p)>(__builtin_assume_aligned((p), (n)))
#else
-#define BOOST_ALIGN_ASSUME_ALIGNED(ptr, alignment)
+#define BOOST_ALIGN_ASSUME_ALIGNED(p, n)
#endif
#endif
diff --git a/boost/align/detail/assume_aligned_gcc.hpp b/boost/align/detail/assume_aligned_gcc.hpp
index f7a545851c..38fab66175 100644
--- a/boost/align/detail/assume_aligned_gcc.hpp
+++ b/boost/align/detail/assume_aligned_gcc.hpp
@@ -12,7 +12,7 @@ http://boost.org/LICENSE_1_0.txt
#ifndef BOOST_ALIGN_DETAIL_ASSUME_ALIGNED_GCC_HPP
#define BOOST_ALIGN_DETAIL_ASSUME_ALIGNED_GCC_HPP
-#define BOOST_ALIGN_ASSUME_ALIGNED(ptr, alignment) \
-(ptr) = __builtin_assume_aligned((ptr), (alignment))
+#define BOOST_ALIGN_ASSUME_ALIGNED(p, n) \
+(p) = static_cast<__typeof__(p)>(__builtin_assume_aligned((p), (n)))
#endif
diff --git a/boost/align/detail/assume_aligned_intel.hpp b/boost/align/detail/assume_aligned_intel.hpp
index e9ec2dbeb4..1944f3de51 100644
--- a/boost/align/detail/assume_aligned_intel.hpp
+++ b/boost/align/detail/assume_aligned_intel.hpp
@@ -12,7 +12,7 @@ http://boost.org/LICENSE_1_0.txt
#ifndef BOOST_ALIGN_DETAIL_ASSUME_ALIGNED_INTEL_HPP
#define BOOST_ALIGN_DETAIL_ASSUME_ALIGNED_INTEL_HPP
-#define BOOST_ALIGN_ASSUME_ALIGNED(ptr, alignment) \
-__assume_aligned((ptr), (alignment))
+#define BOOST_ALIGN_ASSUME_ALIGNED(p, n) \
+__assume_aligned((p), (n))
#endif
diff --git a/boost/align/detail/assume_aligned_msvc.hpp b/boost/align/detail/assume_aligned_msvc.hpp
index 97c1fb1add..84c4d59220 100644
--- a/boost/align/detail/assume_aligned_msvc.hpp
+++ b/boost/align/detail/assume_aligned_msvc.hpp
@@ -12,9 +12,9 @@ http://boost.org/LICENSE_1_0.txt
#ifndef BOOST_ALIGN_DETAIL_ASSUME_ALIGNED_MSVC_HPP
#define BOOST_ALIGN_DETAIL_ASSUME_ALIGNED_MSVC_HPP
-#include <stddef.h>
+#include <cstddef>
-#define BOOST_ALIGN_ASSUME_ALIGNED(ptr, alignment) \
-__assume((uintptr_t(ptr) & ((alignment) - 1)) == 0)
+#define BOOST_ALIGN_ASSUME_ALIGNED(p, n) \
+__assume((reinterpret_cast<std::size_t>(p) & ((n) - 1)) == 0)
#endif
diff --git a/boost/align/detail/remove_traits.hpp b/boost/align/detail/element_type.hpp
index 86a98d459a..793e25ed39 100644
--- a/boost/align/detail/remove_traits.hpp
+++ b/boost/align/detail/element_type.hpp
@@ -1,13 +1,13 @@
/*
-(c) 2014 Glen Joseph Fernandes
+(c) 2015 Glen Joseph Fernandes
<glenjofe -at- gmail.com>
Distributed under the Boost Software
License, Version 1.0.
http://boost.org/LICENSE_1_0.txt
*/
-#ifndef BOOST_ALIGN_DETAIL_REMOVE_TRAITS_HPP
-#define BOOST_ALIGN_DETAIL_REMOVE_TRAITS_HPP
+#ifndef BOOST_ALIGN_DETAIL_ELEMENT_TYPE_HPP
+#define BOOST_ALIGN_DETAIL_ELEMENT_TYPE_HPP
#include <boost/config.hpp>
@@ -22,9 +22,14 @@ namespace alignment {
namespace detail {
#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
-using std::remove_reference;
-using std::remove_all_extents;
-using std::remove_cv;
+template<class T>
+struct element_type {
+ typedef typename
+ std::remove_cv<typename
+ std::remove_all_extents<typename
+ std::remove_reference<T>::
+ type>::type>::type type;
+};
#else
template<class T>
struct remove_reference {
@@ -83,6 +88,15 @@ struct remove_cv {
typedef typename remove_volatile<typename
remove_const<T>::type>::type type;
};
+
+template<class T>
+struct element_type {
+ typedef typename
+ remove_cv<typename
+ remove_all_extents<typename
+ remove_reference<T>::
+ type>::type>::type type;
+};
#endif
} /* .detail */
diff --git a/boost/align/detail/is_aligned.hpp b/boost/align/detail/is_aligned.hpp
index cb45be3433..e9c97ec711 100644
--- a/boost/align/detail/is_aligned.hpp
+++ b/boost/align/detail/is_aligned.hpp
@@ -9,20 +9,25 @@ http://boost.org/LICENSE_1_0.txt
#ifndef BOOST_ALIGN_DETAIL_IS_ALIGNED_HPP
#define BOOST_ALIGN_DETAIL_IS_ALIGNED_HPP
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/align/detail/address.hpp>
#include <boost/align/detail/is_alignment.hpp>
-#include <cstddef>
+#include <boost/align/is_aligned_forward.hpp>
+#include <boost/assert.hpp>
namespace boost {
namespace alignment {
+inline bool is_aligned(const void* ptr, std::size_t alignment)
+ BOOST_NOEXCEPT
+{
+ BOOST_ASSERT(detail::is_alignment(alignment));
+ return is_aligned(reinterpret_cast<std::size_t>(ptr), alignment);
+}
+
inline bool is_aligned(std::size_t alignment, const void* ptr)
BOOST_NOEXCEPT
{
BOOST_ASSERT(detail::is_alignment(alignment));
- return (detail::address(ptr) & (alignment - 1)) == 0;
+ return is_aligned(reinterpret_cast<std::size_t>(ptr), alignment);
}
} /* .alignment */
diff --git a/boost/align/detail/max_align.hpp b/boost/align/detail/max_align.hpp
index daa0413935..8ae6901c19 100644
--- a/boost/align/detail/max_align.hpp
+++ b/boost/align/detail/max_align.hpp
@@ -11,7 +11,6 @@ http://boost.org/LICENSE_1_0.txt
#include <boost/align/detail/max_size.hpp>
#include <boost/align/alignment_of.hpp>
-#include <cstddef>
namespace boost {
namespace alignment {
diff --git a/boost/align/is_aligned.hpp b/boost/align/is_aligned.hpp
index 5d99847e4a..cbace96077 100644
--- a/boost/align/is_aligned.hpp
+++ b/boost/align/is_aligned.hpp
@@ -10,5 +10,18 @@ http://boost.org/LICENSE_1_0.txt
#define BOOST_ALIGN_IS_ALIGNED_HPP
#include <boost/align/detail/is_aligned.hpp>
+#include <boost/align/is_aligned_forward.hpp>
+
+namespace boost {
+namespace alignment {
+
+BOOST_CONSTEXPR inline bool is_aligned(std::size_t value,
+ std::size_t alignment) BOOST_NOEXCEPT
+{
+ return (value & (alignment - 1)) == 0;
+}
+
+} /* .alignment */
+} /* .boost */
#endif
diff --git a/boost/align/is_aligned_forward.hpp b/boost/align/is_aligned_forward.hpp
new file mode 100644
index 0000000000..d1bcbc19dd
--- /dev/null
+++ b/boost/align/is_aligned_forward.hpp
@@ -0,0 +1,24 @@
+/*
+(c) 2015 Glen Joseph Fernandes
+<glenjofe -at- gmail.com>
+
+Distributed under the Boost Software
+License, Version 1.0.
+http://boost.org/LICENSE_1_0.txt
+*/
+#ifndef BOOST_ALIGN_IS_ALIGNED_FORWARD_HPP
+#define BOOST_ALIGN_IS_ALIGNED_FORWARD_HPP
+
+#include <boost/config.hpp>
+#include <cstddef>
+
+namespace boost {
+namespace alignment {
+
+BOOST_CONSTEXPR bool is_aligned(std::size_t value,
+ std::size_t alignment) BOOST_NOEXCEPT;
+
+} /* .alignment */
+} /* .boost */
+
+#endif
diff --git a/boost/archive/add_facet.hpp b/boost/archive/add_facet.hpp
deleted file mode 100644
index 242bdd9001..0000000000
--- a/boost/archive/add_facet.hpp
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef BOOST_ARCHIVE_ADD_FACET_HPP
-#define BOOST_ARCHIVE_ADD_FACET_HPP
-
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER)
-# pragma once
-#endif
-
-/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
-// add_facet.hpp
-
-// (C) Copyright 2003 Robert Ramey - http://www.rrsd.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)
-
-// See http://www.boost.org for updates, documentation, and revision history.
-
-#include <locale>
-#include <boost/config.hpp>
-#include <boost/detail/workaround.hpp>
-
-// does STLport uses native STL for locales?
-#if (defined(__SGI_STL_PORT)&& defined(_STLP_NO_OWN_IOSTREAMS))
-// and this native STL lib is old Dinkumware (has not defined _CPPLIB_VER)
-# if (defined(_YVALS) && !defined(__IBMCPP__)) || !defined(_CPPLIB_VER)
-# define BOOST_ARCHIVE_OLD_DINKUMWARE_BENEATH_STLPORT
-# endif
-#endif
-
-namespace boost {
-namespace archive {
-
-template<class Facet>
-inline std::locale *
-add_facet(const std::locale &l, Facet * f){
- return
- #if defined BOOST_ARCHIVE_OLD_DINKUMWARE_BENEATH_STLPORT
- // std namespace used for native locale
- new std::locale(std::_Addfac(l, f));
- #elif BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) // old Dinkumwar
- // std namespace used for native locale
- new std::locale(std::_Addfac(l, f));
- #else
- // standard compatible
- new std::locale(l, f);
- #endif
-}
-
-} // namespace archive
-} // namespace boost
-
-#undef BOOST_ARCHIVE_OLD_DINKUMWARE_BENEATH_STLPORT
-
-#endif // BOOST_ARCHIVE_ADD_FACET_HPP
diff --git a/boost/archive/basic_binary_iprimitive.hpp b/boost/archive/basic_binary_iprimitive.hpp
index 5e826310d7..40f45d9c2f 100644
--- a/boost/archive/basic_binary_iprimitive.hpp
+++ b/boost/archive/basic_binary_iprimitive.hpp
@@ -44,16 +44,16 @@ namespace std{
#endif
#include <boost/cstdint.hpp>
-#include <boost/scoped_ptr.hpp>
#include <boost/serialization/throw_exception.hpp>
#include <boost/integer.hpp>
#include <boost/integer_traits.hpp>
-#include <boost/mpl/placeholders.hpp>
+//#include <boost/mpl/placeholders.hpp>
#include <boost/serialization/is_bitwise_serializable.hpp>
#include <boost/serialization/array.hpp>
#include <boost/archive/basic_streambuf_locale_saver.hpp>
+#include <boost/archive/codecvt_null.hpp>
#include <boost/archive/archive_exception.hpp>
#include <boost/archive/detail/auto_link_archive.hpp>
#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
@@ -61,9 +61,6 @@ namespace std{
namespace boost {
namespace archive {
-template<class Ch>
-class codecvt_null;
-
/////////////////////////////////////////////////////////////////////////////
// class binary_iarchive - read serialized objects from a input binary stream
template<class Archive, class Elem, class Tr>
@@ -81,9 +78,16 @@ public:
}
#ifndef BOOST_NO_STD_LOCALE
- boost::scoped_ptr<codecvt_null<Elem> > codecvt_facet;
- boost::scoped_ptr<std::locale> archive_locale;
+ // note order! - if you change this, libstd++ will fail!
+ // a) create new locale with new codecvt facet
+ // b) save current locale
+ // c) change locale to new one
+ // d) use stream buffer
+ // e) change locale back to original
+ // f) destroy new codecvt facet
+ boost::archive::codecvt_null<Elem> codecvt_null_facet;
basic_streambuf_locale_saver<Elem, Tr> locale_saver;
+ std::locale archive_locale;
#endif
// main template for serilization of primitive types
@@ -139,7 +143,7 @@ public:
// the optimized load_array dispatches to load_binary
template <class ValueType>
- void load_array(serialization::array<ValueType>& a, unsigned int)
+ void load_array(serialization::array_wrapper<ValueType>& a, unsigned int)
{
load_binary(a.address(),a.count()*sizeof(ValueType));
}
diff --git a/boost/archive/basic_binary_oprimitive.hpp b/boost/archive/basic_binary_oprimitive.hpp
index f2ea6aa3ea..4b7f454b25 100644
--- a/boost/archive/basic_binary_oprimitive.hpp
+++ b/boost/archive/basic_binary_oprimitive.hpp
@@ -43,20 +43,19 @@ namespace std{
#include <boost/scoped_ptr.hpp>
#include <boost/serialization/throw_exception.hpp>
-#include <boost/archive/basic_streambuf_locale_saver.hpp>
-#include <boost/archive/archive_exception.hpp>
+//#include <boost/mpl/placeholders.hpp>
#include <boost/serialization/is_bitwise_serializable.hpp>
-#include <boost/mpl/placeholders.hpp>
#include <boost/serialization/array.hpp>
+
+#include <boost/archive/basic_streambuf_locale_saver.hpp>
+#include <boost/archive/codecvt_null.hpp>
+#include <boost/archive/archive_exception.hpp>
#include <boost/archive/detail/auto_link_archive.hpp>
#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
namespace boost {
namespace archive {
-template<class Ch>
-class codecvt_null;
-
/////////////////////////////////////////////////////////////////////////
// class basic_binary_oprimitive - binary output of prmitives
@@ -74,9 +73,16 @@ public:
return static_cast<Archive *>(this);
}
#ifndef BOOST_NO_STD_LOCALE
- boost::scoped_ptr<codecvt_null<Elem> > codecvt_facet;
- boost::scoped_ptr<std::locale> archive_locale;
+ // note order! - if you change this, libstd++ will fail!
+ // a) create new locale with new codecvt facet
+ // b) save current locale
+ // c) change locale to new one
+ // d) use stream buffer
+ // e) change locale back to original
+ // f) destroy new codecvt facet
+ boost::archive::codecvt_null<Elem> codecvt_null_facet;
basic_streambuf_locale_saver<Elem, Tr> locale_saver;
+ std::locale archive_locale;
#endif
// default saving of primitives.
template<class T>
@@ -131,11 +137,10 @@ public:
struct apply : public boost::serialization::is_bitwise_serializable< T > {};
#endif
};
-
// the optimized save_array dispatches to save_binary
template <class ValueType>
- void save_array(boost::serialization::array<ValueType> const& a, unsigned int)
+ void save_array(boost::serialization::array_wrapper<ValueType> const& a, unsigned int)
{
save_binary(a.address(),a.count()*sizeof(ValueType));
}
diff --git a/boost/archive/basic_streambuf_locale_saver.hpp b/boost/archive/basic_streambuf_locale_saver.hpp
index 64c8e5d314..5cd4b36f08 100644
--- a/boost/archive/basic_streambuf_locale_saver.hpp
+++ b/boost/archive/basic_streambuf_locale_saver.hpp
@@ -27,6 +27,7 @@
#ifndef BOOST_NO_STD_LOCALE
#include <locale> // for std::locale
+#include <ios>
#include <streambuf> // for std::basic_streambuf
#include <boost/config.hpp>
@@ -45,25 +46,57 @@ class basic_streambuf_locale_saver :
private boost::noncopyable
{
public:
- typedef ::std::basic_streambuf<Ch, Tr> state_type;
- typedef ::std::locale aspect_type;
- explicit basic_streambuf_locale_saver( state_type &s )
- : s_save_( s ), a_save_( s.getloc() )
- {}
- explicit basic_streambuf_locale_saver( state_type &s, aspect_type const &a )
- : s_save_( s ), a_save_( s.pubimbue(a) )
- {}
- ~basic_streambuf_locale_saver()
- { this->restore(); }
- void restore(){
- s_save_.pubsync();
- s_save_.pubimbue( a_save_ );
+ explicit basic_streambuf_locale_saver(std::basic_streambuf<Ch, Tr> &s) :
+ m_streambuf(s),
+ m_locale(s.getloc())
+ {}
+ ~basic_streambuf_locale_saver(){
+ m_streambuf.pubsync();
+ m_streambuf.pubimbue(m_locale);
}
private:
- state_type & s_save_;
- aspect_type const a_save_;
+ std::basic_streambuf<Ch, Tr> & m_streambuf;
+ std::locale const m_locale;
};
+template < typename Ch, class Tr >
+class basic_istream_locale_saver :
+ private boost::noncopyable
+{
+public:
+ explicit basic_istream_locale_saver(std::basic_istream<Ch, Tr> &s) :
+ m_istream(s),
+ m_locale(s.getloc())
+ {}
+ ~basic_istream_locale_saver(){
+ // libstdc++ crashes without this
+ m_istream.sync();
+ m_istream.imbue(m_locale);
+ }
+private:
+ std::basic_istream<Ch, Tr> & m_istream;
+ std::locale const m_locale;
+};
+
+template < typename Ch, class Tr >
+class basic_ostream_locale_saver :
+ private boost::noncopyable
+{
+public:
+ explicit basic_ostream_locale_saver(std::basic_ostream<Ch, Tr> &s) :
+ m_ostream(s),
+ m_locale(s.getloc())
+ {}
+ ~basic_ostream_locale_saver(){
+ m_ostream.flush();
+ m_ostream.imbue(m_locale);
+ }
+private:
+ std::basic_ostream<Ch, Tr> & m_ostream;
+ std::locale const m_locale;
+};
+
+
} // archive
} // boost
diff --git a/boost/archive/basic_text_iprimitive.hpp b/boost/archive/basic_text_iprimitive.hpp
index 08da95c36e..bf936b5554 100644
--- a/boost/archive/basic_text_iprimitive.hpp
+++ b/boost/archive/basic_text_iprimitive.hpp
@@ -24,7 +24,6 @@
// in such cases. So we can't use basic_ostream<IStream::char_type> but rather
// use two template parameters
-#include <boost/assert.hpp>
#include <locale>
#include <cstddef> // size_t
@@ -38,17 +37,15 @@ namespace std{
} // namespace std
#endif
+#include <boost/io/ios_state.hpp>
+#include <boost/static_assert.hpp>
+
#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1)
#include <boost/archive/dinkumware.hpp>
#endif
-
-#include <boost/limits.hpp>
-#include <boost/io/ios_state.hpp>
-#include <boost/scoped_ptr.hpp>
-#include <boost/static_assert.hpp>
-
#include <boost/serialization/throw_exception.hpp>
+#include <boost/archive/codecvt_null.hpp>
#include <boost/archive/archive_exception.hpp>
#include <boost/archive/basic_streambuf_locale_saver.hpp>
#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
@@ -71,9 +68,17 @@ protected:
io::ios_precision_saver precision_saver;
#ifndef BOOST_NO_STD_LOCALE
- boost::scoped_ptr<std::locale> archive_locale;
- basic_streambuf_locale_saver<
- typename IStream::char_type,
+ // note order! - if you change this, libstd++ will fail!
+ // a) create new locale with new codecvt facet
+ // b) save current locale
+ // c) change locale to new one
+ // d) use stream buffer
+ // e) change locale back to original
+ // f) destroy new codecvt facet
+ boost::archive::codecvt_null<typename IStream::char_type> codecvt_null_facet;
+ std::locale archive_locale;
+ basic_istream_locale_saver<
+ typename IStream::char_type,
typename IStream::traits_type
> locale_saver;
#endif
diff --git a/boost/archive/basic_text_oprimitive.hpp b/boost/archive/basic_text_oprimitive.hpp
index 86330921d2..c9f8c59160 100644
--- a/boost/archive/basic_text_oprimitive.hpp
+++ b/boost/archive/basic_text_oprimitive.hpp
@@ -26,14 +26,13 @@
#include <iomanip>
#include <locale>
-#include <boost/assert.hpp>
#include <cstddef> // size_t
#include <boost/config.hpp>
#include <boost/static_assert.hpp>
-#include <boost/detail/workaround.hpp>
#include <boost/io/ios_state.hpp>
+#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1)
#include <boost/archive/dinkumware.hpp>
#endif
@@ -52,10 +51,10 @@ namespace std{
#include <boost/limits.hpp>
#include <boost/integer.hpp>
#include <boost/io/ios_state.hpp>
-#include <boost/scoped_ptr.hpp>
#include <boost/serialization/throw_exception.hpp>
-#include <boost/archive/archive_exception.hpp>
#include <boost/archive/basic_streambuf_locale_saver.hpp>
+#include <boost/archive/codecvt_null.hpp>
+#include <boost/archive/archive_exception.hpp>
#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
namespace boost {
@@ -72,9 +71,17 @@ protected:
io::ios_precision_saver precision_saver;
#ifndef BOOST_NO_STD_LOCALE
- boost::scoped_ptr<std::locale> archive_locale;
- basic_streambuf_locale_saver<
- typename OStream::char_type,
+ // note order! - if you change this, libstd++ will fail!
+ // a) create new locale with new codecvt facet
+ // b) save current locale
+ // c) change locale to new one
+ // d) use stream buffer
+ // e) change locale back to original
+ // f) destroy new codecvt facet
+ boost::archive::codecvt_null<typename OStream::char_type> codecvt_null_facet;
+ std::locale archive_locale;
+ basic_ostream_locale_saver<
+ typename OStream::char_type,
typename OStream::traits_type
> locale_saver;
#endif
diff --git a/boost/archive/basic_xml_iarchive.hpp b/boost/archive/basic_xml_iarchive.hpp
index 7834d8a100..a882df5615 100644
--- a/boost/archive/basic_xml_iarchive.hpp
+++ b/boost/archive/basic_xml_iarchive.hpp
@@ -17,15 +17,12 @@
// See http://www.boost.org for updates, documentation, and revision history.
#include <boost/config.hpp>
-#include <boost/detail/workaround.hpp>
+#include <boost/mpl/assert.hpp>
#include <boost/archive/detail/common_iarchive.hpp>
-
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/string.hpp>
-#include <boost/mpl/assert.hpp>
-
#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
#ifdef BOOST_MSVC
@@ -41,24 +38,18 @@ namespace detail {
} // namespace detail
/////////////////////////////////////////////////////////////////////////
-// class xml_iarchive - read serialized objects from a input text stream
+// class basic_xml_iarchive - read serialized objects from a input text stream
template<class Archive>
class BOOST_SYMBOL_VISIBLE basic_xml_iarchive :
public detail::common_iarchive<Archive>
{
+ unsigned int depth;
#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
public:
#else
protected:
- #if BOOST_WORKAROUND(BOOST_MSVC, < 1500)
- // for some inexplicable reason insertion of "class" generates compile erro
- // on msvc 7.1
- friend detail::interface_iarchive<Archive>;
- #else
- friend class detail::interface_iarchive<Archive>;
- #endif
+ friend class detail::interface_iarchive<Archive>;
#endif
- unsigned int depth;
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
load_start(const char *name);
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
@@ -96,14 +87,15 @@ protected:
// an xml archive. So we can skip it here. Note: we MUST override
// it otherwise it will be loaded as a normal primitive w/o tag and
// leaving the archive in an undetermined state
- void load_override(class_id_optional_type & /* t */){}
+ BOOST_ARCHIVE_OR_WARCHIVE_DECL void
+ load_override(class_id_type & t);
+ BOOST_ARCHIVE_OR_WARCHIVE_DECL void
+ load_override(class_id_optional_type & /* t */){}
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
load_override(object_id_type & t);
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
load_override(version_type & t);
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
- load_override(class_id_type & t);
- BOOST_ARCHIVE_OR_WARCHIVE_DECL void
load_override(tracking_type & t);
// class_name_type can't be handled here as it depends upon the
// char type used by the stream. So require the derived implementation
diff --git a/boost/archive/basic_xml_oarchive.hpp b/boost/archive/basic_xml_oarchive.hpp
index 0325eee653..107fca4ec6 100644
--- a/boost/archive/basic_xml_oarchive.hpp
+++ b/boost/archive/basic_xml_oarchive.hpp
@@ -18,15 +18,11 @@
#include <boost/config.hpp>
#include <boost/mpl/assert.hpp>
-#include <boost/detail/workaround.hpp>
#include <boost/archive/detail/common_oarchive.hpp>
-
#include <boost/serialization/nvp.hpp>
-#include <boost/serialization/tracking.hpp>
#include <boost/serialization/string.hpp>
-
#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
#ifdef BOOST_MSVC
@@ -47,28 +43,23 @@ template<class Archive>
class BOOST_SYMBOL_VISIBLE basic_xml_oarchive :
public detail::common_oarchive<Archive>
{
+ // special stuff for xml output
+ unsigned int depth;
+ bool pending_preamble;
#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
public:
#else
protected:
-#endif
-#if BOOST_WORKAROUND(BOOST_MSVC, < 1500)
- // for some inexplicable reason insertion of "class" generates compile erro
- // on msvc 7.1
- friend detail::interface_oarchive<Archive>;
-#else
friend class detail::interface_oarchive<Archive>;
#endif
- friend class save_access;
- // special stuff for xml output
- unsigned int depth;
bool indent_next;
- bool pending_preamble;
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
indent();
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
init();
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
+ windup();
+ BOOST_ARCHIVE_OR_WARCHIVE_DECL void
write_attribute(
const char *attribute_name,
int t,
@@ -113,18 +104,18 @@ protected:
// specific overrides for attributes - not name value pairs so we
// want to trap them before the above "fall through"
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
- save_override(const object_id_type & t);
- BOOST_ARCHIVE_OR_WARCHIVE_DECL void
- save_override(const object_reference_type & t);
- BOOST_ARCHIVE_OR_WARCHIVE_DECL void
- save_override(const version_type & t);
- BOOST_ARCHIVE_OR_WARCHIVE_DECL void
save_override(const class_id_type & t);
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
save_override(const class_id_optional_type & t);
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
save_override(const class_id_reference_type & t);
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
+ save_override(const object_id_type & t);
+ BOOST_ARCHIVE_OR_WARCHIVE_DECL void
+ save_override(const object_reference_type & t);
+ BOOST_ARCHIVE_OR_WARCHIVE_DECL void
+ save_override(const version_type & t);
+ BOOST_ARCHIVE_OR_WARCHIVE_DECL void
save_override(const class_name_type & t);
BOOST_ARCHIVE_OR_WARCHIVE_DECL void
save_override(const tracking_type & t);
diff --git a/boost/archive/binary_iarchive_impl.hpp b/boost/archive/binary_iarchive_impl.hpp
index 3ff994ad83..b4747c98ec 100644
--- a/boost/archive/binary_iarchive_impl.hpp
+++ b/boost/archive/binary_iarchive_impl.hpp
@@ -33,7 +33,7 @@ namespace detail {
} // namespace detail
template<class Archive, class Elem, class Tr>
-class binary_iarchive_impl :
+class BOOST_SYMBOL_VISIBLE binary_iarchive_impl :
public basic_binary_iprimitive<Archive, Elem, Tr>,
public basic_binary_iarchive<Archive>
{
@@ -58,8 +58,9 @@ protected:
this->basic_binary_iarchive<Archive>::load_override(t);
}
void init(unsigned int flags){
- if(0 != (flags & no_header))
+ if(0 != (flags & no_header)){
return;
+ }
#if ! defined(__MWERKS__)
this->basic_binary_iarchive<Archive>::init();
this->basic_binary_iprimitive<Archive, Elem, Tr>::init();
diff --git a/boost/archive/binary_oarchive_impl.hpp b/boost/archive/binary_oarchive_impl.hpp
index 76e3a6565b..6b4d018a56 100644
--- a/boost/archive/binary_oarchive_impl.hpp
+++ b/boost/archive/binary_oarchive_impl.hpp
@@ -34,7 +34,7 @@ namespace detail {
} // namespace detail
template<class Archive, class Elem, class Tr>
-class binary_oarchive_impl :
+class BOOST_SYMBOL_VISIBLE binary_oarchive_impl :
public basic_binary_oprimitive<Archive, Elem, Tr>,
public basic_binary_oarchive<Archive>
{
@@ -59,8 +59,9 @@ protected:
this->basic_binary_oarchive<Archive>::save_override(t);
}
void init(unsigned int flags) {
- if(0 != (flags & no_header))
+ if(0 != (flags & no_header)){
return;
+ }
#if ! defined(__MWERKS__)
this->basic_binary_oarchive<Archive>::init();
this->basic_binary_oprimitive<Archive, Elem, Tr>::init();
diff --git a/boost/archive/codecvt_null.hpp b/boost/archive/codecvt_null.hpp
index 324122b78a..9cc9e5729d 100644
--- a/boost/archive/codecvt_null.hpp
+++ b/boost/archive/codecvt_null.hpp
@@ -56,10 +56,11 @@ public:
explicit codecvt_null(std::size_t no_locale_manage = 0) :
std::codecvt<char, char, std::mbstate_t>(no_locale_manage)
{}
+ virtual ~codecvt_null(){};
};
template<>
-class codecvt_null<wchar_t> : public std::codecvt<wchar_t, char, std::mbstate_t>
+class BOOST_SYMBOL_VISIBLE codecvt_null<wchar_t> : public std::codecvt<wchar_t, char, std::mbstate_t>
{
virtual BOOST_WARCHIVE_DECL std::codecvt_base::result
do_out(
@@ -91,6 +92,7 @@ public:
explicit codecvt_null(std::size_t no_locale_manage = 0) :
std::codecvt<wchar_t, char, std::mbstate_t>(no_locale_manage)
{}
+ virtual ~codecvt_null(){};
};
} // namespace archive
diff --git a/boost/archive/detail/basic_serializer.hpp b/boost/archive/detail/basic_serializer.hpp
index c7d3b4befc..f9c4203f86 100644
--- a/boost/archive/detail/basic_serializer.hpp
+++ b/boost/archive/detail/basic_serializer.hpp
@@ -41,9 +41,7 @@ protected:
const boost::serialization::extended_type_info & eti
) :
m_eti(& eti)
- {
- BOOST_ASSERT(NULL != & eti);
- }
+ {}
public:
inline bool
operator<(const basic_serializer & rhs) const {
diff --git a/boost/archive/detail/common_iarchive.hpp b/boost/archive/detail/common_iarchive.hpp
index b4c44d2767..82304f1e5a 100644
--- a/boost/archive/detail/common_iarchive.hpp
+++ b/boost/archive/detail/common_iarchive.hpp
@@ -35,7 +35,7 @@ class extended_type_info;
// note: referred to as Curiously Recurring Template Patter (CRTP)
template<class Archive>
-class common_iarchive :
+class BOOST_SYMBOL_VISIBLE common_iarchive :
public basic_iarchive,
public interface_iarchive<Archive>
{
diff --git a/boost/archive/detail/common_oarchive.hpp b/boost/archive/detail/common_oarchive.hpp
index 13c71bc5a8..ee42bbe597 100644
--- a/boost/archive/detail/common_oarchive.hpp
+++ b/boost/archive/detail/common_oarchive.hpp
@@ -32,7 +32,8 @@ namespace detail {
// note: referred to as Curiously Recurring Template Patter (CRTP)
template<class Archive>
-class common_oarchive :
+
+class BOOST_SYMBOL_VISIBLE common_oarchive :
public basic_oarchive,
public interface_oarchive<Archive>
{
diff --git a/boost/archive/detail/decl.hpp b/boost/archive/detail/decl.hpp
index bb386d86f8..4f731cded3 100644
--- a/boost/archive/detail/decl.hpp
+++ b/boost/archive/detail/decl.hpp
@@ -29,14 +29,12 @@
#else
#define BOOST_ARCHIVE_DECL BOOST_SYMBOL_IMPORT
#endif
+
#if defined(BOOST_WARCHIVE_SOURCE)
#define BOOST_WARCHIVE_DECL BOOST_SYMBOL_EXPORT
#else
#define BOOST_WARCHIVE_DECL BOOST_SYMBOL_IMPORT
#endif
- #if !defined(BOOST_WARCHIVE_SOURCE) && !defined(BOOST_ARCHIVE_SOURCE)
- #define BOOST_ARCHIVE_OR_WARCHIVE_DECL BOOST_SYMBOL_IMPORT
- #endif
#if defined(BOOST_WARCHIVE_SOURCE) || defined(BOOST_ARCHIVE_SOURCE)
#define BOOST_ARCHIVE_OR_WARCHIVE_DECL BOOST_SYMBOL_EXPORT
diff --git a/boost/archive/detail/iserializer.hpp b/boost/archive/detail/iserializer.hpp
index 6419e623c8..6bec499bd2 100644
--- a/boost/archive/detail/iserializer.hpp
+++ b/boost/archive/detail/iserializer.hpp
@@ -39,7 +39,6 @@ namespace std{
#include <boost/mpl/identity.hpp>
#include <boost/mpl/greater_equal.hpp>
#include <boost/mpl/equal_to.hpp>
-#include <boost/mpl/bool.hpp>
#include <boost/core/no_exceptions_support.hpp>
#ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO
@@ -226,15 +225,6 @@ struct heap_allocation {
static T * invoke_new() {
return static_cast<T *>((T::operator new)(sizeof(T)));
}
- template<void D(void *, std::size_t)>
- static void deleter(void * t, std::size_t s){
- D(t, s);
- }
-
- template<void D(void *)>
- static void deleter(void * t, std::size_t s){
- D(t);
- }
static void invoke_delete(T * t) {
// if compilation fails here, the likely cause that the class
// T has a class specific new operator but no class specific
@@ -244,7 +234,7 @@ struct heap_allocation {
// that the class might have class specific new with NO
// class specific delete at all. Patches (compatible with
// C++03) welcome!
- deleter<T::operator delete>(t, sizeof(T));
+ delete t;
}
};
struct doesnt_have_new_operator {
@@ -253,7 +243,7 @@ struct heap_allocation {
}
static void invoke_delete(T * t) {
// Note: I'm reliance upon automatic conversion from T * to void * here
- (operator delete)(t);
+ delete t;
}
};
static T * invoke_new() {
diff --git a/boost/archive/detail/oserializer.hpp b/boost/archive/detail/oserializer.hpp
index 7a7e239376..0f2e733c58 100644
--- a/boost/archive/detail/oserializer.hpp
+++ b/boost/archive/detail/oserializer.hpp
@@ -33,6 +33,7 @@
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/greater_equal.hpp>
#include <boost/mpl/identity.hpp>
+#include <boost/mpl/bool_fwd.hpp>
#ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO
#include <boost/serialization/extended_type_info_typeid.hpp>
diff --git a/boost/archive/detail/utf8_codecvt_facet.hpp b/boost/archive/detail/utf8_codecvt_facet.hpp
index b2430d5a43..dfbec6bdfd 100644
--- a/boost/archive/detail/utf8_codecvt_facet.hpp
+++ b/boost/archive/detail/utf8_codecvt_facet.hpp
@@ -7,10 +7,17 @@
#ifndef BOOST_ARCHIVE_DETAIL_UTF8_CODECVT_FACET_HPP
#define BOOST_ARCHIVE_DETAIL_UTF8_CODECVT_FACET_HPP
-#ifdef BOOST_NO_CXX11_HDR_CODECVT
+#include <boost/config.hpp>
+
+// std::codecvt_utf8 doesn't seem to work for msvc
+// versions prior to MSVC 14.0
+
+#if defined(_MSC_VER) && _MSC_VER < 1900 \
+|| defined( BOOST_NO_CXX11_HDR_CODECVT )
+ #include <boost/archive/detail/decl.hpp>
#define BOOST_UTF8_BEGIN_NAMESPACE \
namespace boost { namespace archive { namespace detail {
- #define BOOST_UTF8_DECL
+ #define BOOST_UTF8_DECL BOOST_ARCHIVE_DECL
#define BOOST_UTF8_END_NAMESPACE }}}
#include <boost/detail/utf8_codecvt_facet.hpp>
@@ -18,6 +25,10 @@
#undef BOOST_UTF8_END_NAMESPACE
#undef BOOST_UTF8_DECL
#undef BOOST_UTF8_BEGIN_NAMESPACE
+#else
+ #include <codecvt>
+ namespace boost { namespace archive { namespace detail {
+ typedef std::codecvt_utf8<wchar_t> utf8_codecvt_facet;
+ } } }
#endif // BOOST_NO_CXX11_HDR_CODECVT
#endif // BOOST_ARCHIVE_DETAIL_UTF8_CODECVT_FACET_HPP
-
diff --git a/boost/archive/impl/basic_binary_iprimitive.ipp b/boost/archive/impl/basic_binary_iprimitive.ipp
index bee7bafea9..7082b003e7 100644
--- a/boost/archive/impl/basic_binary_iprimitive.ipp
+++ b/boost/archive/impl/basic_binary_iprimitive.ipp
@@ -20,14 +20,9 @@ namespace std{
} // namespace std
#endif
-#include <boost/detail/workaround.hpp> // fixup for RogueWave
-
#include <boost/serialization/throw_exception.hpp>
-
#include <boost/core/no_exceptions_support.hpp>
#include <boost/archive/archive_exception.hpp>
-#include <boost/archive/codecvt_null.hpp>
-#include <boost/archive/add_facet.hpp>
#include <boost/archive/basic_binary_iprimitive.hpp>
namespace boost {
@@ -152,16 +147,13 @@ basic_binary_iprimitive<Archive, Elem, Tr>::basic_binary_iprimitive(
) :
#ifndef BOOST_NO_STD_LOCALE
m_sb(sb),
- locale_saver(m_sb)
+ codecvt_null_facet(1),
+ locale_saver(m_sb),
+ archive_locale(sb.getloc(), & codecvt_null_facet)
{
if(! no_codecvt){
- archive_locale.reset(
- add_facet(
- std::locale::classic(),
- new codecvt_null<Elem>
- )
- );
- //m_sb.pubimbue(* archive_locale);
+ m_sb.pubsync();
+ m_sb.pubimbue(archive_locale);
}
}
#else
@@ -169,42 +161,11 @@ basic_binary_iprimitive<Archive, Elem, Tr>::basic_binary_iprimitive(
{}
#endif
-// some libraries including stl and libcomo fail if the
-// buffer isn't flushed before the code_cvt facet is changed.
-// I think this is a bug. We explicity invoke sync to when
-// we're done with the streambuf to work around this problem.
-// Note that sync is a protected member of stream buff so we
-// have to invoke it through a contrived derived class.
-namespace detail {
-// note: use "using" to get past msvc bug
-using namespace std;
-template<class Elem, class Tr>
-class input_streambuf_access : public std::basic_streambuf<Elem, Tr> {
- public:
- virtual int sync(){
-#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
- return this->basic_streambuf::sync();
-#else
- return this->basic_streambuf<Elem, Tr>::sync();
-#endif
- }
-};
-} // detail
-
-// scoped_ptr requires that archive_locale be a complete type at time of
+// scoped_ptr requires that g be a complete type at time of
// destruction so define destructor here rather than in the header
template<class Archive, class Elem, class Tr>
BOOST_ARCHIVE_OR_WARCHIVE_DECL
-basic_binary_iprimitive<Archive, Elem, Tr>::~basic_binary_iprimitive(){
- // push back unread characters
- //destructor can't throw !
- BOOST_TRY{
- static_cast<detail::input_streambuf_access<Elem, Tr> &>(m_sb).sync();
- }
- BOOST_CATCH(...){
- }
- BOOST_CATCH_END
-}
+basic_binary_iprimitive<Archive, Elem, Tr>::~basic_binary_iprimitive(){}
} // namespace archive
} // namespace boost
diff --git a/boost/archive/impl/basic_binary_oprimitive.ipp b/boost/archive/impl/basic_binary_oprimitive.ipp
index 88cc12433c..130831e4fb 100644
--- a/boost/archive/impl/basic_binary_oprimitive.ipp
+++ b/boost/archive/impl/basic_binary_oprimitive.ipp
@@ -27,10 +27,6 @@ namespace std{ using ::wcslen; }
#endif
#endif
-#include <boost/detail/workaround.hpp>
-
-#include <boost/archive/add_facet.hpp>
-#include <boost/archive/codecvt_null.hpp>
#include <boost/archive/basic_binary_oprimitive.hpp>
#include <boost/core/no_exceptions_support.hpp>
@@ -104,16 +100,13 @@ basic_binary_oprimitive<Archive, Elem, Tr>::basic_binary_oprimitive(
) :
#ifndef BOOST_NO_STD_LOCALE
m_sb(sb),
- locale_saver(m_sb)
+ codecvt_null_facet(1),
+ locale_saver(m_sb),
+ archive_locale(sb.getloc(), & codecvt_null_facet)
{
if(! no_codecvt){
- archive_locale.reset(
- add_facet(
- std::locale::classic(),
- new codecvt_null<Elem>
- )
- );
- //m_sb.pubimbue(* archive_locale);
+ m_sb.pubsync();
+ m_sb.pubimbue(archive_locale);
}
}
#else
@@ -121,42 +114,11 @@ basic_binary_oprimitive<Archive, Elem, Tr>::basic_binary_oprimitive(
{}
#endif
-// some libraries including stl and libcomo fail if the
-// buffer isn't flushed before the code_cvt facet is changed.
-// I think this is a bug. We explicity invoke sync to when
-// we're done with the streambuf to work around this problem.
-// Note that sync is a protected member of stream buff so we
-// have to invoke it through a contrived derived class.
-namespace detail {
-// note: use "using" to get past msvc bug
-using namespace std;
-template<class Elem, class Tr>
-class output_streambuf_access : public std::basic_streambuf<Elem, Tr> {
- public:
- virtual int sync(){
-#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
- return this->basic_streambuf::sync();
-#else
- return this->basic_streambuf<Elem, Tr>::sync();
-#endif
- }
-};
-} // detail
-
// scoped_ptr requires that g be a complete type at time of
// destruction so define destructor here rather than in the header
template<class Archive, class Elem, class Tr>
BOOST_ARCHIVE_OR_WARCHIVE_DECL
-basic_binary_oprimitive<Archive, Elem, Tr>::~basic_binary_oprimitive(){
- // flush buffer
- //destructor can't throw
- BOOST_TRY{
- static_cast<detail::output_streambuf_access<Elem, Tr> &>(m_sb).sync();
- }
- BOOST_CATCH(...){
- }
- BOOST_CATCH_END
-}
+basic_binary_oprimitive<Archive, Elem, Tr>::~basic_binary_oprimitive(){}
} // namespace archive
} // namespace boost
diff --git a/boost/archive/impl/basic_text_iprimitive.ipp b/boost/archive/impl/basic_text_iprimitive.ipp
index e245dc540f..4e44728068 100644
--- a/boost/archive/impl/basic_text_iprimitive.ipp
+++ b/boost/archive/impl/basic_text_iprimitive.ipp
@@ -8,8 +8,8 @@
// See http://www.boost.org for updates, documentation, and revision history.
-#include <cstddef> // size_t
-#include <cstddef> // NULL
+#include <cstddef> // size_t, NULL
+#include <limits> // NULL
#include <boost/config.hpp>
#if defined(BOOST_NO_STDC_NAMESPACE)
@@ -21,8 +21,6 @@ namespace std{
#include <boost/serialization/throw_exception.hpp>
#include <boost/archive/basic_text_iprimitive.hpp>
-#include <boost/archive/codecvt_null.hpp>
-#include <boost/archive/add_facet.hpp>
#include <boost/archive/iterators/remove_whitespace.hpp>
#include <boost/archive/iterators/istream_iterator.hpp>
@@ -78,7 +76,7 @@ basic_text_iprimitive<IStream>::load_binary(
iterators::remove_whitespace<
iterators::istream_iterator<CharType>
>
- ,CharType
+ ,typename IStream::int_type
>
,8
,6
@@ -112,34 +110,27 @@ basic_text_iprimitive<IStream>::basic_text_iprimitive(
IStream &is_,
bool no_codecvt
) :
-#ifndef BOOST_NO_STD_LOCALE
is(is_),
flags_saver(is_),
precision_saver(is_),
- locale_saver(* is_.rdbuf())
+#ifndef BOOST_NO_STD_LOCALE
+ codecvt_null_facet(1),
+ archive_locale(is.getloc(), & codecvt_null_facet),
+ locale_saver(is)
{
if(! no_codecvt){
- archive_locale.reset(
- add_facet(
- std::locale::classic(),
- new boost::archive::codecvt_null<typename IStream::char_type>
- )
- );
- //is.imbue(* archive_locale);
+ is_.sync();
+ is_.imbue(archive_locale);
}
- is >> std::noboolalpha;
+ is_ >> std::noboolalpha;
}
#else
- is(is_),
- flags_saver(is_),
- precision_saver(is_)
{}
#endif
template<class IStream>
BOOST_ARCHIVE_OR_WARCHIVE_DECL
basic_text_iprimitive<IStream>::~basic_text_iprimitive(){
- is.sync();
}
} // namespace archive
diff --git a/boost/archive/impl/basic_text_oprimitive.ipp b/boost/archive/impl/basic_text_oprimitive.ipp
index f2b0a10a60..6030fd44c5 100644
--- a/boost/archive/impl/basic_text_oprimitive.ipp
+++ b/boost/archive/impl/basic_text_oprimitive.ipp
@@ -10,10 +10,15 @@
#include <cstddef> // NULL
#include <algorithm> // std::copy
+#include <exception> // std::uncaught_exception
+#include <boost/config.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{
+ using ::size_t;
+} // namespace std
+#endif
#include <boost/archive/basic_text_oprimitive.hpp>
-#include <boost/archive/codecvt_null.hpp>
-#include <boost/archive/add_facet.hpp>
#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/insert_linebreaks.hpp>
@@ -79,33 +84,30 @@ basic_text_oprimitive<OStream>::basic_text_oprimitive(
OStream & os_,
bool no_codecvt
) :
-#ifndef BOOST_NO_STD_LOCALE
os(os_),
flags_saver(os_),
precision_saver(os_),
- locale_saver(* os_.rdbuf())
+#ifndef BOOST_NO_STD_LOCALE
+ codecvt_null_facet(1),
+ archive_locale(os.getloc(), & codecvt_null_facet),
+ locale_saver(os)
{
if(! no_codecvt){
- archive_locale.reset(
- add_facet(
- std::locale::classic(),
- new boost::archive::codecvt_null<typename OStream::char_type>
- )
- );
- //os.imbue(* archive_locale);
+ os_.flush();
+ os_.imbue(archive_locale);
}
- os << std::noboolalpha;
+ os_ << std::noboolalpha;
}
#else
- os(os_),
- flags_saver(os_),
- precision_saver(os_)
{}
#endif
+
template<class OStream>
BOOST_ARCHIVE_OR_WARCHIVE_DECL
basic_text_oprimitive<OStream>::~basic_text_oprimitive(){
+ if(std::uncaught_exception())
+ return;
os << std::endl;
}
diff --git a/boost/archive/impl/basic_xml_grammar.hpp b/boost/archive/impl/basic_xml_grammar.hpp
index 70a6013abc..6d4e4683f6 100644
--- a/boost/archive/impl/basic_xml_grammar.hpp
+++ b/boost/archive/impl/basic_xml_grammar.hpp
@@ -163,7 +163,7 @@ public:
bool parse_end_tag(IStream & is) const;
bool parse_string(IStream & is, StringType & s) /*const*/;
void init(IStream & is);
- void windup(IStream & is);
+ bool windup(IStream & is);
basic_xml_grammar();
};
diff --git a/boost/archive/impl/basic_xml_iarchive.ipp b/boost/archive/impl/basic_xml_iarchive.ipp
index 9e670120f0..625458b9eb 100644
--- a/boost/archive/impl/basic_xml_iarchive.ipp
+++ b/boost/archive/impl/basic_xml_iarchive.ipp
@@ -108,7 +108,8 @@ basic_xml_iarchive<Archive>::basic_xml_iarchive(unsigned int flags) :
{}
template<class Archive>
BOOST_ARCHIVE_OR_WARCHIVE_DECL
-basic_xml_iarchive<Archive>::~basic_xml_iarchive(){}
+basic_xml_iarchive<Archive>::~basic_xml_iarchive(){
+}
} // namespace archive
} // namespace boost
diff --git a/boost/archive/impl/basic_xml_oarchive.ipp b/boost/archive/impl/basic_xml_oarchive.ipp
index 5db1e13096..3184413f38 100644
--- a/boost/archive/impl/basic_xml_oarchive.ipp
+++ b/boost/archive/impl/basic_xml_oarchive.ipp
@@ -247,25 +247,25 @@ basic_xml_oarchive<Archive>::init(){
}
template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL void
+basic_xml_oarchive<Archive>::windup(){
+ // xml_trailer
+ this->This()->put("</boost_serialization>\n");
+}
+
+template<class Archive>
BOOST_ARCHIVE_OR_WARCHIVE_DECL
basic_xml_oarchive<Archive>::basic_xml_oarchive(unsigned int flags) :
detail::common_oarchive<Archive>(flags),
depth(0),
- indent_next(false),
- pending_preamble(false)
+ pending_preamble(false),
+ indent_next(false)
{
}
template<class Archive>
BOOST_ARCHIVE_OR_WARCHIVE_DECL
basic_xml_oarchive<Archive>::~basic_xml_oarchive(){
- if(0 == (this->get_flags() & no_header)){
- BOOST_TRY{
- this->This()->put("</boost_serialization>\n");
- }
- BOOST_CATCH(...){}
- BOOST_CATCH_END
- }
}
} // namespace archive
diff --git a/boost/archive/impl/text_oarchive_impl.ipp b/boost/archive/impl/text_oarchive_impl.ipp
index 4ff488f4cb..37d8664a98 100644
--- a/boost/archive/impl/text_oarchive_impl.ipp
+++ b/boost/archive/impl/text_oarchive_impl.ipp
@@ -10,7 +10,6 @@
#include <string>
#include <boost/config.hpp>
-#include <locale>
#include <cstddef> // size_t
#include <boost/config.hpp>
@@ -27,7 +26,6 @@ namespace std{ using ::wcslen; }
#endif
#endif
-#include <boost/archive/add_facet.hpp>
#include <boost/archive/text_oarchive.hpp>
namespace boost {
diff --git a/boost/archive/impl/xml_iarchive_impl.ipp b/boost/archive/impl/xml_iarchive_impl.ipp
index bf94774987..efc32e0163 100644
--- a/boost/archive/impl/xml_iarchive_impl.ipp
+++ b/boost/archive/impl/xml_iarchive_impl.ipp
@@ -11,6 +11,8 @@
#include <boost/config.hpp>
#include <cstring> // memcpy
#include <cstddef> // NULL
+#include <exception>
+
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std{
using ::memcpy;
@@ -64,22 +66,22 @@ xml_iarchive_impl<Archive>::load(std::wstring &ws){
#if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101))
if(NULL != ws.data())
#endif
- ws.resize(0);
- std::mbstate_t mbs;
+ ws.resize(0);
+ std::mbstate_t mbs = std::mbstate_t();
const char * start = s.data();
const char * end = start + s.size();
while(start < end){
wchar_t wc;
- std::size_t result = std::mbrtowc(&wc, start, end - start, &mbs);
- if(result == static_cast<std::size_t>(-1))
+ std::size_t count = std::mbrtowc(&wc, start, end - start, &mbs);
+ if(count == static_cast<std::size_t>(-1))
boost::serialization::throw_exception(
iterators::dataflow_exception(
iterators::dataflow_exception::invalid_conversion
)
);
- if(result == static_cast<std::size_t>(-2))
+ if(count == static_cast<std::size_t>(-2))
continue;
- start += result;
+ start += count;
ws += wc;
}
}
@@ -98,7 +100,7 @@ xml_iarchive_impl<Archive>::load(wchar_t * ws){
)
);
- std::mbstate_t mbs;
+ std::mbstate_t mbs = std::mbstate_t();
const char * start = s.data();
const char * end = start + s.size();
while(start < end){
@@ -187,12 +189,10 @@ xml_iarchive_impl<Archive>::xml_iarchive_impl(
template<class Archive>
BOOST_ARCHIVE_DECL
xml_iarchive_impl<Archive>::~xml_iarchive_impl(){
+ if(std::uncaught_exception())
+ return;
if(0 == (this->get_flags() & no_header)){
- BOOST_TRY{
- gimpl->windup(is);
- }
- BOOST_CATCH(...){}
- BOOST_CATCH_END
+ gimpl->windup(is);
}
}
} // namespace archive
diff --git a/boost/archive/impl/xml_oarchive_impl.ipp b/boost/archive/impl/xml_oarchive_impl.ipp
index 9e714f3ca6..5ebd454e72 100644
--- a/boost/archive/impl/xml_oarchive_impl.ipp
+++ b/boost/archive/impl/xml_oarchive_impl.ipp
@@ -10,6 +10,7 @@
#include <iomanip>
#include <algorithm> // std::copy
#include <string>
+#include <exception>
#include <cstring> // strlen
#include <boost/config.hpp> // msvc 6.0 needs this to suppress warnings
@@ -113,5 +114,29 @@ xml_oarchive_impl<Archive>::xml_oarchive_impl(
this->init();
}
+template<class Archive>
+BOOST_ARCHIVE_DECL void
+xml_oarchive_impl<Archive>::save_binary(const void *address, std::size_t count){
+ this->end_preamble();
+ #if ! defined(__MWERKS__)
+ this->basic_text_oprimitive<std::ostream>::save_binary(
+ #else
+ this->basic_text_oprimitive::save_binary(
+ #endif
+ address,
+ count
+ );
+ this->indent_next = true;
+}
+
+template<class Archive>
+BOOST_ARCHIVE_DECL
+xml_oarchive_impl<Archive>::~xml_oarchive_impl(){
+ if(std::uncaught_exception())
+ return;
+ if(0 == (this->get_flags() & no_header))
+ this->windup();
+}
+
} // namespace archive
} // namespace boost
diff --git a/boost/archive/impl/xml_wiarchive_impl.ipp b/boost/archive/impl/xml_wiarchive_impl.ipp
index a837347edb..ee66c1263e 100644
--- a/boost/archive/impl/xml_wiarchive_impl.ipp
+++ b/boost/archive/impl/xml_wiarchive_impl.ipp
@@ -20,7 +20,7 @@ namespace std{
#include <boost/assert.hpp>
#include <algorithm> // std::copy
-
+#include <exception> // uncaught exception
#include <boost/detail/workaround.hpp> // Dinkumware and RogueWave
#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1)
#include <boost/archive/dinkumware.hpp>
@@ -33,11 +33,11 @@ namespace std{
#include <boost/archive/basic_xml_archive.hpp>
#include <boost/archive/xml_wiarchive.hpp>
-#include <boost/archive/add_facet.hpp>
-
#include <boost/archive/xml_archive_exception.hpp>
#include <boost/archive/iterators/mb_from_wchar.hpp>
+#include <boost/archive/detail/utf8_codecvt_facet.hpp>
+
#include "basic_xml_grammar.hpp"
namespace boost {
@@ -161,15 +161,13 @@ xml_wiarchive_impl<Archive>::xml_wiarchive_impl(
gimpl(new xml_wgrammar())
{
if(0 == (flags & no_codecvt)){
- // note usage of argument "1" so that the locale isn't
- // automatically delete the facet
- archive_locale.reset(
- add_facet(
- is_.getloc(),
- new boost::archive::detail::utf8_codecvt_facet
- )
+ std::locale l = std::locale(
+ is_.getloc(),
+ new boost::archive::detail::utf8_codecvt_facet
);
- //is.imbue(* archive_locale);
+ // libstdc++ crashes without this
+ is_.sync();
+ is_.imbue(l);
}
if(0 == (flags & no_header))
init();
@@ -178,12 +176,10 @@ xml_wiarchive_impl<Archive>::xml_wiarchive_impl(
template<class Archive>
BOOST_WARCHIVE_DECL
xml_wiarchive_impl<Archive>::~xml_wiarchive_impl(){
+ if(std::uncaught_exception())
+ return;
if(0 == (this->get_flags() & no_header)){
- BOOST_TRY{
- gimpl->windup(is);
- }
- BOOST_CATCH(...){}
- BOOST_CATCH_END
+ gimpl->windup(is);
}
}
diff --git a/boost/archive/impl/xml_woarchive_impl.ipp b/boost/archive/impl/xml_woarchive_impl.ipp
index d5586d51ae..58f92c9d92 100644
--- a/boost/archive/impl/xml_woarchive_impl.ipp
+++ b/boost/archive/impl/xml_woarchive_impl.ipp
@@ -13,6 +13,7 @@
#include <string>
#include <algorithm> // std::copy
#include <locale>
+#include <exception>
#include <cstring> // strlen
#include <cstdlib> // mbtowc
@@ -30,6 +31,8 @@ namespace std{
#endif
#include <boost/archive/xml_woarchive.hpp>
+#include <boost/archive/detail/utf8_codecvt_facet.hpp>
+
#include <boost/serialization/throw_exception.hpp>
#include <boost/archive/iterators/xml_escape.hpp>
@@ -37,8 +40,6 @@ namespace std{
#include <boost/archive/iterators/ostream_iterator.hpp>
#include <boost/archive/iterators/dataflow_exception.hpp>
-#include <boost/archive/add_facet.hpp>
-
namespace boost {
namespace archive {
@@ -122,19 +123,13 @@ xml_woarchive_impl<Archive>::xml_woarchive_impl(
),
basic_xml_oarchive<Archive>(flags)
{
- // Standard behavior is that imbue can be called
- // a) before output is invoked or
- // b) after flush has been called. This prevents one-to-many
- // transforms (such as one to many transforms from getting
- // mixed up.
if(0 == (flags & no_codecvt)){
- archive_locale.reset(
- add_facet(
- os_.getloc(),
- new boost::archive::detail::utf8_codecvt_facet
- )
+ std::locale l = std::locale(
+ os_.getloc(),
+ new boost::archive::detail::utf8_codecvt_facet
);
- //os.imbue(* archive_locale);
+ os_.flush();
+ os_.imbue(l);
}
if(0 == (flags & no_header))
this->init();
@@ -143,6 +138,29 @@ xml_woarchive_impl<Archive>::xml_woarchive_impl(
template<class Archive>
BOOST_WARCHIVE_DECL
xml_woarchive_impl<Archive>::~xml_woarchive_impl(){
+ if(std::uncaught_exception())
+ return;
+ if(0 == (this->get_flags() & no_header)){
+ save(L"</boost_serialization>\n");
+ }
+}
+
+template<class Archive>
+BOOST_WARCHIVE_DECL void
+xml_woarchive_impl<Archive>::save_binary(
+ const void *address,
+ std::size_t count
+){
+ this->end_preamble();
+ #if ! defined(__MWERKS__)
+ this->basic_text_oprimitive<std::wostream>::save_binary(
+ #else
+ this->basic_text_oprimitive::save_binary(
+ #endif
+ address,
+ count
+ );
+ this->indent_next = true;
}
} // namespace archive
diff --git a/boost/archive/iterators/dataflow.hpp b/boost/archive/iterators/dataflow.hpp
index 6f8001d3ce..07733d5fd6 100644
--- a/boost/archive/iterators/dataflow.hpp
+++ b/boost/archive/iterators/dataflow.hpp
@@ -20,7 +20,6 @@
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/if.hpp>
-#include <boost/mpl/bool.hpp>
#include <boost/mpl/apply.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/int.hpp>
diff --git a/boost/archive/iterators/istream_iterator.hpp b/boost/archive/iterators/istream_iterator.hpp
index 41aa0be37b..9a1d555c10 100644
--- a/boost/archive/iterators/istream_iterator.hpp
+++ b/boost/archive/iterators/istream_iterator.hpp
@@ -54,21 +54,6 @@ class istream_iterator :
return m_istream == rhs.m_istream;
}
-/*
- //Access the value referred to
- Elem dereference() const {
- return m_current_value;
- }
-
- void increment(){
- if(NULL != m_istream){
- m_current_value = static_cast<Elem>(m_istream->get());
- if(! m_istream->good()){
- const_cast<this_t *>(this)->m_istream = NULL;
- }
- }
- }
-*/
//Access the value referred to
Elem dereference() const {
return m_istream->peek();
diff --git a/boost/archive/iterators/mb_from_wchar.hpp b/boost/archive/iterators/mb_from_wchar.hpp
index d76eb3e2d2..d5110de28a 100644
--- a/boost/archive/iterators/mb_from_wchar.hpp
+++ b/boost/archive/iterators/mb_from_wchar.hpp
@@ -18,17 +18,15 @@
#include <boost/assert.hpp>
#include <cstddef> // size_t
-#include <cwchar> // for mbstate_t and wcrtomb()
+#include <cwchar> // mbstate_t
#include <boost/config.hpp>
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std{
- using ::size_t;
using ::mbstate_t;
- using ::wcrtomb;
} // namespace std
#endif
-
+#include <boost/archive/detail/utf8_codecvt_facet.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
namespace boost {
@@ -67,10 +65,10 @@ class mb_from_wchar
}
return m_buffer[m_bnext];
}
+
char dereference() const {
return (const_cast<this_t *>(this))->dereference_impl();
}
-
// test for iterator equality
bool equal(const mb_from_wchar<Base> & rhs) const {
// once the value is filled, the base_reference has been incremented
@@ -83,14 +81,17 @@ class mb_from_wchar
}
void fill(){
- std::mbstate_t mbs;
- std::wcrtomb(0, 0, &mbs);
wchar_t value = * this->base_reference();
- m_bend = std::wcrtomb(m_buffer, value, &mbs);
- BOOST_ASSERT(-1 != m_bend);
- BOOST_ASSERT((std::size_t)m_bend <= sizeof(m_buffer));
- BOOST_ASSERT(m_bend > 0);
+ const wchar_t *wend;
+ char *bend;
+ std::codecvt_base::result r = m_codecvt_facet.out(
+ m_mbs,
+ & value, & value + 1, wend,
+ m_buffer, m_buffer + sizeof(m_buffer), bend
+ );
+ BOOST_ASSERT(std::codecvt_base::ok == r);
m_bnext = 0;
+ m_bend = bend - m_buffer;
}
void increment(){
@@ -102,10 +103,12 @@ class mb_from_wchar
m_full = false;
}
+ boost::archive::detail::utf8_codecvt_facet m_codecvt_facet;
+ std::mbstate_t m_mbs;
// buffer to handle pending characters
- int m_bend;
- int m_bnext;
- char m_buffer[9];
+ char m_buffer[9 /* MB_CUR_MAX */];
+ std::size_t m_bend;
+ std::size_t m_bnext;
bool m_full;
public:
@@ -113,6 +116,7 @@ public:
template<class T>
mb_from_wchar(T start) :
super_t(Base(static_cast< T >(start))),
+ m_mbs(std::mbstate_t()),
m_bend(0),
m_bnext(0),
m_full(false)
diff --git a/boost/archive/iterators/wchar_from_mb.hpp b/boost/archive/iterators/wchar_from_mb.hpp
index 998a4686b2..52a44bdc79 100644
--- a/boost/archive/iterators/wchar_from_mb.hpp
+++ b/boost/archive/iterators/wchar_from_mb.hpp
@@ -19,20 +19,22 @@
#include <boost/assert.hpp>
#include <cctype>
#include <cstddef> // size_t
-#include <cwchar> // mbstate_t and mbrtowc
+#include <cwchar> // mbstate_t
+#include <algorithm> // copy
#include <boost/config.hpp>
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std{
using ::mbstate_t;
- using ::mbrtowc;
} // namespace std
#endif
-
-#include <boost/serialization/throw_exception.hpp>
-
+#include <boost/array.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/archive/detail/utf8_codecvt_facet.hpp>
#include <boost/archive/iterators/dataflow_exception.hpp>
+#include <boost/serialization/throw_exception.hpp>
+
+#include <iostream>
namespace boost {
namespace archive {
@@ -62,57 +64,125 @@ class wchar_from_mb
typedef wchar_from_mb<Base> this_t;
- wchar_t drain();
+ void drain();
- wchar_t dereference_impl() {
- if(! m_full){
- m_current_value = drain();
- m_full = true;
+ wchar_t dereference() const {
+ if(m_output.m_next == m_output.m_next_available)
+ return static_cast<wchar_t>(0);
+ return * m_output.m_next;
+ }
+
+ void increment(){
+ if(m_output.m_next == m_output.m_next_available)
+ return;
+ if(++m_output.m_next == m_output.m_next_available){
+ if(m_input.m_done)
+ return;
+ drain();
}
- return m_current_value;
}
- wchar_t dereference() const {
- return const_cast<this_t *>(this)->dereference_impl();
+ bool equal(this_t const & rhs) const {
+ return dereference() == rhs.dereference();
}
- void increment(){
- dereference_impl();
- m_full = false;
- ++(this->base_reference());
+ boost::archive::detail::utf8_codecvt_facet m_codecvt_facet;
+ std::mbstate_t m_mbs;
+
+ template<typename T>
+ struct sliding_buffer {
+ boost::array<T, 32> m_buffer;
+ typename boost::array<T, 32>::const_iterator m_next_available;
+ typename boost::array<T, 32>::iterator m_next;
+ bool m_done;
+ // default ctor
+ sliding_buffer() :
+ m_next_available(m_buffer.begin()),
+ m_next(m_buffer.begin()),
+ m_done(false)
+ {}
+ // copy ctor
+ sliding_buffer(const sliding_buffer & rhs) :
+ m_next_available(
+ std::copy(
+ rhs.m_buffer.begin(),
+ rhs.m_next_available,
+ m_buffer.begin()
+ )
+ ),
+ m_next(
+ m_buffer.begin() + (rhs.m_next - rhs.m_buffer.begin())
+ ),
+ m_done(rhs.m_done)
+ {}
};
- wchar_t m_current_value;
- bool m_full;
+ sliding_buffer<typename iterator_value<Base>::type> m_input;
+ sliding_buffer<typename iterator_value<this_t>::type> m_output;
public:
// make composible buy using templated constructor
template<class T>
wchar_from_mb(T start) :
super_t(Base(static_cast< T >(start))),
- m_full(false)
- {}
- // intel 7.1 doesn't like default copy constructor
- wchar_from_mb(const wchar_from_mb & rhs) :
+ m_mbs(std::mbstate_t())
+ {
+ BOOST_ASSERT(std::mbsinit(&m_mbs));
+ drain();
+ }
+ // default constructor used as an end iterator
+ wchar_from_mb(){}
+
+ // copy ctor
+ wchar_from_mb(const wchar_from_mb & rhs) :
super_t(rhs.base_reference()),
- m_full(rhs.m_full)
+ m_mbs(rhs.m_mbs),
+ m_input(rhs.m_input),
+ m_output(rhs.m_output)
{}
};
template<class Base>
-wchar_t wchar_from_mb<Base>::drain(){
- std::mbstate_t mbs;
- wchar_t retval;
- std::size_t result;
- do {
- char val = *this->base_reference();
- result = std::mbrtowc(&retval, &val, 1, &mbs);
- if(result == static_cast<std::size_t>(-1))
- boost::serialization::throw_exception(iterators::dataflow_exception(
- iterators::dataflow_exception::invalid_conversion
- ));
- } while (result == static_cast<std::size_t>(-2));
- return retval;
+void wchar_from_mb<Base>::drain(){
+ BOOST_ASSERT(! m_input.m_done);
+ for(;;){
+ typename boost::iterators::iterator_reference<Base>::type c = *(this->base_reference());
+ // a null character in a multibyte stream is takes as end of string
+ if(0 == c){
+ m_input.m_done = true;
+ break;
+ }
+ ++(this->base_reference());
+ * const_cast<typename iterator_value<Base>::type *>(
+ (m_input.m_next_available++)
+ ) = c;
+ // if input buffer is full - we're done for now
+ if(m_input.m_buffer.end() == m_input.m_next_available)
+ break;
+ }
+ const typename boost::iterators::iterator_value<Base>::type * input_new_start;
+ typename iterator_value<this_t>::type * next_available;
+
+ std::codecvt_base::result r = m_codecvt_facet.in(
+ m_mbs,
+ m_input.m_buffer.begin(),
+ m_input.m_next_available,
+ input_new_start,
+ m_output.m_buffer.begin(),
+ m_output.m_buffer.end(),
+ next_available
+ );
+ BOOST_ASSERT(std::codecvt_base::ok == r);
+ m_output.m_next_available = next_available;
+ m_output.m_next = m_output.m_buffer.begin();
+
+ // we're done with some of the input so shift left.
+ m_input.m_next_available = std::copy(
+ input_new_start,
+ m_input.m_next_available,
+ m_input.m_buffer.begin()
+ );
+ m_input.m_next = m_input.m_buffer.begin();
}
} // namespace iterators
diff --git a/boost/archive/text_iarchive.hpp b/boost/archive/text_iarchive.hpp
index e40db8371d..d9d60adf0b 100644
--- a/boost/archive/text_iarchive.hpp
+++ b/boost/archive/text_iarchive.hpp
@@ -48,15 +48,8 @@ class BOOST_SYMBOL_VISIBLE text_iarchive_impl :
public:
#else
protected:
- #if BOOST_WORKAROUND(BOOST_MSVC, < 1500)
- // for some inexplicable reason insertion of "class" generates compile erro
- // on msvc 7.1
- friend detail::interface_iarchive<Archive>;
- friend load_access;
- #else
- friend class detail::interface_iarchive<Archive>;
- friend class load_access;
- #endif
+ friend class detail::interface_iarchive<Archive>;
+ friend class load_access;
#endif
template<class T>
void load(T & t){
diff --git a/boost/archive/text_oarchive.hpp b/boost/archive/text_oarchive.hpp
index 7eaea17232..9ba0dafffb 100644
--- a/boost/archive/text_oarchive.hpp
+++ b/boost/archive/text_oarchive.hpp
@@ -55,17 +55,9 @@ class BOOST_SYMBOL_VISIBLE text_oarchive_impl :
public:
#else
protected:
- #if BOOST_WORKAROUND(BOOST_MSVC, < 1500)
- // for some inexplicable reason insertion of "class" generates compile erro
- // on msvc 7.1
- friend detail::interface_oarchive<Archive>;
- friend basic_text_oarchive<Archive>;
- friend save_access;
- #else
- friend class detail::interface_oarchive<Archive>;
- friend class basic_text_oarchive<Archive>;
- friend class save_access;
- #endif
+ friend class detail::interface_oarchive<Archive>;
+ friend class basic_text_oarchive<Archive>;
+ friend class save_access;
#endif
template<class T>
void save(const T & t){
diff --git a/boost/archive/xml_iarchive.hpp b/boost/archive/xml_iarchive.hpp
index 055ba0f426..abd2f9fc4e 100644
--- a/boost/archive/xml_iarchive.hpp
+++ b/boost/archive/xml_iarchive.hpp
@@ -52,17 +52,9 @@ class BOOST_SYMBOL_VISIBLE xml_iarchive_impl :
public:
#else
protected:
- #if BOOST_WORKAROUND(BOOST_MSVC, < 1500)
- // for some inexplicable reason insertion of "class" generates compile erro
- // on msvc 7.1
- friend detail::interface_iarchive<Archive>;
- friend basic_xml_iarchive<Archive>;
- friend load_access;
- #else
- friend class detail::interface_iarchive<Archive>;
- friend class basic_xml_iarchive<Archive>;
- friend class load_access;
- #endif
+ friend class detail::interface_iarchive<Archive>;
+ friend class basic_xml_iarchive<Archive>;
+ friend class load_access;
#endif
// use boost:scoped_ptr to implement automatic deletion;
boost::scoped_ptr<xml_grammar> gimpl;
diff --git a/boost/archive/xml_oarchive.hpp b/boost/archive/xml_oarchive.hpp
index c5e6da9271..eea1268037 100644
--- a/boost/archive/xml_oarchive.hpp
+++ b/boost/archive/xml_oarchive.hpp
@@ -55,21 +55,10 @@ class BOOST_SYMBOL_VISIBLE xml_oarchive_impl :
public:
#else
protected:
- #if BOOST_WORKAROUND(BOOST_MSVC, < 1500)
- // for some inexplicable reason insertion of "class" generates compile erro
- // on msvc 7.1
- friend detail::interface_oarchive<Archive>;
- friend basic_xml_oarchive<Archive>;
- friend save_access;
- #else
- friend class detail::interface_oarchive<Archive>;
- friend class basic_xml_oarchive<Archive>;
- friend class save_access;
- #endif
+ friend class detail::interface_oarchive<Archive>;
+ friend class basic_xml_oarchive<Archive>;
+ friend class save_access;
#endif
- //void end_preamble(){
- // basic_xml_oarchive<Archive>::end_preamble();
- //}
template<class T>
void save(const T & t){
basic_text_oprimitive<std::ostream>::save(t);
@@ -96,22 +85,29 @@ protected:
#endif
BOOST_ARCHIVE_DECL
xml_oarchive_impl(std::ostream & os, unsigned int flags);
- ~xml_oarchive_impl(){}
+ BOOST_ARCHIVE_DECL
+ ~xml_oarchive_impl();
public:
- void save_binary(const void *address, std::size_t count){
- this->end_preamble();
- #if ! defined(__MWERKS__)
- this->basic_text_oprimitive<std::ostream>::save_binary(
- #else
- this->basic_text_oprimitive::save_binary(
- #endif
- address,
- count
- );
- this->indent_next = true;
- }
+ BOOST_ARCHIVE_DECL
+ void save_binary(const void *address, std::size_t count);
};
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost {
+namespace archive {
+
// we use the following because we can't use
// typedef xml_oarchive_impl<xml_oarchive_impl<...> > xml_oarchive;
@@ -138,6 +134,4 @@ BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::xml_oarchive)
#pragma warning(pop)
#endif
-#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
-
#endif // BOOST_ARCHIVE_XML_OARCHIVE_HPP
diff --git a/boost/archive/xml_wiarchive.hpp b/boost/archive/xml_wiarchive.hpp
index dbc2d721a4..ac24289ac1 100644
--- a/boost/archive/xml_wiarchive.hpp
+++ b/boost/archive/xml_wiarchive.hpp
@@ -29,15 +29,7 @@
#include <boost/archive/basic_xml_iarchive.hpp>
#include <boost/archive/detail/register_archive.hpp>
#include <boost/serialization/item_version_type.hpp>
-
-#ifdef BOOST_NO_CXX11_HDR_CODECVT
- #include <boost/archive/detail/utf8_codecvt_facet.hpp>
-#else
- #include <codecvt>
- namespace boost { namespace archive { namespace detail {
- typedef std::codecvt_utf8<wchar_t> utf8_codecvt_facet;
- } } }
-#endif
+// #include <boost/archive/detail/utf8_codecvt_facet.hpp>
#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
@@ -66,17 +58,9 @@ class BOOST_SYMBOL_VISIBLE xml_wiarchive_impl :
public:
#else
protected:
- #if BOOST_WORKAROUND(BOOST_MSVC, < 1500)
- // for some inexplicable reason insertion of "class" generates compile erro
- // on msvc 7.1
- friend detail::interface_iarchive<Archive>;
- friend basic_xml_iarchive<Archive>;
- friend load_access;
- #else
- friend class detail::interface_iarchive<Archive>;
- friend class basic_xml_iarchive<Archive>;
- friend class load_access;
- #endif
+ friend class detail::interface_iarchive<Archive>;
+ friend class basic_xml_iarchive<Archive>;
+ friend class load_access;
#endif
boost::scoped_ptr<xml_wgrammar> gimpl;
std::wistream & get_is(){
diff --git a/boost/archive/xml_woarchive.hpp b/boost/archive/xml_woarchive.hpp
index 62700162d7..cb7ce68cb6 100644
--- a/boost/archive/xml_woarchive.hpp
+++ b/boost/archive/xml_woarchive.hpp
@@ -20,7 +20,6 @@
#ifdef BOOST_NO_STD_WSTREAMBUF
#error "wide char i/o not supported on this platform"
#else
-
#include <cstddef> // size_t
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std{
@@ -30,21 +29,13 @@ namespace std{
#include <ostream>
-#include <boost/smart_ptr/scoped_ptr.hpp>
+//#include <boost/smart_ptr/scoped_ptr.hpp>
#include <boost/archive/detail/auto_link_warchive.hpp>
#include <boost/archive/basic_text_oprimitive.hpp>
#include <boost/archive/basic_xml_oarchive.hpp>
#include <boost/archive/detail/register_archive.hpp>
#include <boost/serialization/item_version_type.hpp>
-
-#ifdef BOOST_NO_CXX11_HDR_CODECVT
- #include <boost/archive/detail/utf8_codecvt_facet.hpp>
-#else
- #include <codecvt>
- namespace boost { namespace archive { namespace detail {
- typedef std::codecvt_utf8<wchar_t> utf8_codecvt_facet;
- } } }
-#endif
+//#include <boost/archive/detail/utf8_codecvt_facet.hpp>
#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
@@ -69,27 +60,19 @@ class BOOST_SYMBOL_VISIBLE xml_woarchive_impl :
public:
#else
protected:
- #if BOOST_WORKAROUND(BOOST_MSVC, < 1500)
- // for some inexplicable reason insertion of "class" generates compile erro
- // on msvc 7.1
- friend detail::interface_oarchive<Archive>;
- friend basic_xml_oarchive<Archive>;
- friend save_access;
- #else
- friend class detail::interface_oarchive<Archive>;
- friend class basic_xml_oarchive<Archive>;
- friend class save_access;
- #endif
+ friend class detail::interface_oarchive<Archive>;
+ friend class basic_xml_oarchive<Archive>;
+ friend class save_access;
#endif
//void end_preamble(){
// basic_xml_oarchive<Archive>::end_preamble();
//}
template<class T>
- void
+ void
save(const T & t){
basic_text_oprimitive<std::wostream>::save(t);
}
- void
+ void
save(const version_type & t){
save(static_cast<const unsigned int>(t));
}
@@ -111,22 +94,12 @@ protected:
#endif
BOOST_WARCHIVE_DECL
xml_woarchive_impl(std::wostream & os, unsigned int flags);
- BOOST_WARCHIVE_DECL
+ BOOST_WARCHIVE_DECL
~xml_woarchive_impl();
public:
- void
- save_binary(const void *address, std::size_t count){
- this->end_preamble();
- #if ! defined(__MWERKS__)
- this->basic_text_oprimitive<std::wostream>::save_binary(
- #else
- this->basic_text_oprimitive::save_binary(
- #endif
- address,
- count
- );
- this->indent_next = true;
- }
+ BOOST_WARCHIVE_DECL void
+ save_binary(const void *address, std::size_t count);
+
};
// we use the following because we can't use
@@ -135,7 +108,7 @@ public:
// do not derive from this class. If you want to extend this functionality
// via inhertance, derived from xml_woarchive_impl instead. This will
// preserve correct static polymorphism.
-class BOOST_SYMBOL_VISIBLE xml_woarchive :
+class BOOST_SYMBOL_VISIBLE xml_woarchive :
public xml_woarchive_impl<xml_woarchive>
{
public:
diff --git a/boost/atomic/detail/ops_emulated.hpp b/boost/atomic/detail/ops_emulated.hpp
index 0dc4e6828a..17032917fe 100644
--- a/boost/atomic/detail/ops_emulated.hpp
+++ b/boost/atomic/detail/ops_emulated.hpp
@@ -89,7 +89,7 @@ struct emulated_operations
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
- storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
+ storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
// Note: This function is the exact copy of compare_exchange_strong. The reason we're not just forwarding the call
// is that MSVC-12 ICEs in this case.
diff --git a/boost/atomic/detail/ops_gcc_x86_dcas.hpp b/boost/atomic/detail/ops_gcc_x86_dcas.hpp
index f7a84f79ce..47cc36d8e7 100644
--- a/boost/atomic/detail/ops_gcc_x86_dcas.hpp
+++ b/boost/atomic/detail/ops_gcc_x86_dcas.hpp
@@ -522,7 +522,7 @@ struct gcc_dcas_x86_64
return compare_exchange_strong(storage, expected, desired, success_order, failure_order);
}
- static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
+ static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
#if defined(__clang__)
// Clang cannot allocate eax:edx register pairs but it has sync intrinsics
diff --git a/boost/bimap/detail/debug/static_error.hpp b/boost/bimap/detail/debug/static_error.hpp
index cbb1cadb8d..4e5cb26371 100644
--- a/boost/bimap/detail/debug/static_error.hpp
+++ b/boost/bimap/detail/debug/static_error.hpp
@@ -25,7 +25,6 @@
// a static error.
/*===========================================================================*/
#define BOOST_BIMAP_STATIC_ERROR(MESSAGE,VARIABLES) \
- struct BOOST_PP_CAT(BIMAP_STATIC_ERROR__,MESSAGE) {}; \
BOOST_MPL_ASSERT_MSG(false, \
BOOST_PP_CAT(BIMAP_STATIC_ERROR__,MESSAGE), \
VARIABLES)
diff --git a/boost/compute.hpp b/boost/compute.hpp
new file mode 100644
index 0000000000..83e17acc1f
--- /dev/null
+++ b/boost/compute.hpp
@@ -0,0 +1,44 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_HPP
+#define BOOST_COMPUTE_HPP
+
+#include <boost/compute/algorithm.hpp>
+#include <boost/compute/allocator.hpp>
+#include <boost/compute/async.hpp>
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/cl.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/config.hpp>
+#include <boost/compute/container.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/device.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/image.hpp>
+#include <boost/compute/iterator.hpp>
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/pipe.hpp>
+#include <boost/compute/platform.hpp>
+#include <boost/compute/program.hpp>
+#include <boost/compute/random.hpp>
+#include <boost/compute/svm.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/types.hpp>
+#include <boost/compute/user_event.hpp>
+#include <boost/compute/utility.hpp>
+#include <boost/compute/version.hpp>
+
+#ifdef BOOST_COMPUTE_HAVE_HDR_CL_EXT
+#include <boost/compute/cl_ext.hpp>
+#endif
+
+#endif // BOOST_COMPUTE_HPP
diff --git a/boost/compute/algorithm.hpp b/boost/compute/algorithm.hpp
new file mode 100644
index 0000000000..686640e9e9
--- /dev/null
+++ b/boost/compute/algorithm.hpp
@@ -0,0 +1,94 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_HPP
+#define BOOST_COMPUTE_ALGORITHM_HPP
+
+/// \file
+///
+/// Meta-header to include all Boost.Compute algorithm headers.
+
+#include <boost/compute/algorithm/accumulate.hpp>
+#include <boost/compute/algorithm/adjacent_difference.hpp>
+#include <boost/compute/algorithm/adjacent_find.hpp>
+#include <boost/compute/algorithm/all_of.hpp>
+#include <boost/compute/algorithm/any_of.hpp>
+#include <boost/compute/algorithm/binary_search.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/copy_if.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/algorithm/count.hpp>
+#include <boost/compute/algorithm/count_if.hpp>
+#include <boost/compute/algorithm/equal.hpp>
+#include <boost/compute/algorithm/equal_range.hpp>
+#include <boost/compute/algorithm/exclusive_scan.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/algorithm/fill_n.hpp>
+#include <boost/compute/algorithm/find.hpp>
+#include <boost/compute/algorithm/find_end.hpp>
+#include <boost/compute/algorithm/find_if.hpp>
+#include <boost/compute/algorithm/find_if_not.hpp>
+#include <boost/compute/algorithm/for_each.hpp>
+#include <boost/compute/algorithm/for_each_n.hpp>
+#include <boost/compute/algorithm/gather.hpp>
+#include <boost/compute/algorithm/generate.hpp>
+#include <boost/compute/algorithm/generate_n.hpp>
+#include <boost/compute/algorithm/inclusive_scan.hpp>
+#include <boost/compute/algorithm/includes.hpp>
+#include <boost/compute/algorithm/inner_product.hpp>
+#include <boost/compute/algorithm/iota.hpp>
+#include <boost/compute/algorithm/is_partitioned.hpp>
+#include <boost/compute/algorithm/is_permutation.hpp>
+#include <boost/compute/algorithm/is_sorted.hpp>
+#include <boost/compute/algorithm/lower_bound.hpp>
+#include <boost/compute/algorithm/lexicographical_compare.hpp>
+#include <boost/compute/algorithm/max_element.hpp>
+#include <boost/compute/algorithm/merge.hpp>
+#include <boost/compute/algorithm/min_element.hpp>
+#include <boost/compute/algorithm/minmax_element.hpp>
+#include <boost/compute/algorithm/mismatch.hpp>
+#include <boost/compute/algorithm/next_permutation.hpp>
+#include <boost/compute/algorithm/none_of.hpp>
+#include <boost/compute/algorithm/partial_sum.hpp>
+#include <boost/compute/algorithm/partition.hpp>
+#include <boost/compute/algorithm/partition_copy.hpp>
+#include <boost/compute/algorithm/partition_point.hpp>
+#include <boost/compute/algorithm/prev_permutation.hpp>
+#include <boost/compute/algorithm/random_shuffle.hpp>
+#include <boost/compute/algorithm/reduce.hpp>
+#include <boost/compute/algorithm/reduce_by_key.hpp>
+#include <boost/compute/algorithm/remove.hpp>
+#include <boost/compute/algorithm/remove_if.hpp>
+#include <boost/compute/algorithm/replace.hpp>
+#include <boost/compute/algorithm/replace_copy.hpp>
+#include <boost/compute/algorithm/reverse.hpp>
+#include <boost/compute/algorithm/reverse_copy.hpp>
+#include <boost/compute/algorithm/rotate.hpp>
+#include <boost/compute/algorithm/rotate_copy.hpp>
+#include <boost/compute/algorithm/scatter.hpp>
+#include <boost/compute/algorithm/search.hpp>
+#include <boost/compute/algorithm/search_n.hpp>
+#include <boost/compute/algorithm/set_difference.hpp>
+#include <boost/compute/algorithm/set_intersection.hpp>
+#include <boost/compute/algorithm/set_symmetric_difference.hpp>
+#include <boost/compute/algorithm/set_union.hpp>
+#include <boost/compute/algorithm/sort.hpp>
+#include <boost/compute/algorithm/sort_by_key.hpp>
+#include <boost/compute/algorithm/stable_partition.hpp>
+#include <boost/compute/algorithm/stable_sort.hpp>
+#include <boost/compute/algorithm/stable_sort_by_key.hpp>
+#include <boost/compute/algorithm/swap_ranges.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/algorithm/transform_reduce.hpp>
+#include <boost/compute/algorithm/unique.hpp>
+#include <boost/compute/algorithm/unique_copy.hpp>
+#include <boost/compute/algorithm/upper_bound.hpp>
+
+#endif // BOOST_COMPUTE_ALGORITHM_HPP
diff --git a/boost/compute/algorithm/accumulate.hpp b/boost/compute/algorithm/accumulate.hpp
new file mode 100644
index 0000000000..328420a07c
--- /dev/null
+++ b/boost/compute/algorithm/accumulate.hpp
@@ -0,0 +1,184 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_ACCUMULATE_HPP
+#define BOOST_COMPUTE_ALGORITHM_ACCUMULATE_HPP
+
+#include <boost/preprocessor/seq/for_each.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/reduce.hpp>
+#include <boost/compute/algorithm/detail/serial_accumulate.hpp>
+#include <boost/compute/container/array.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator, class T, class BinaryFunction>
+inline T generic_accumulate(InputIterator first,
+ InputIterator last,
+ T init,
+ BinaryFunction function,
+ command_queue &queue)
+{
+ const context &context = queue.get_context();
+
+ size_t size = iterator_range_size(first, last);
+ if(size == 0){
+ return init;
+ }
+
+ // accumulate on device
+ array<T, 1> device_result(context);
+ detail::serial_accumulate(
+ first, last, device_result.begin(), init, function, queue
+ );
+
+ // copy result to host
+ T result;
+ ::boost::compute::copy_n(device_result.begin(), 1, &result, queue);
+ return result;
+}
+
+// returns true if we can use reduce() instead of accumulate() when
+// accumulate() this is true when the function is commutative (such as
+// addition of integers) and the initial value is the identity value
+// for the operation (zero for addition, one for multiplication).
+template<class T, class F>
+inline bool can_accumulate_with_reduce(T init, F function)
+{
+ (void) init;
+ (void) function;
+
+ return false;
+}
+
+/// \internal_
+#define BOOST_COMPUTE_DETAIL_DECLARE_CAN_ACCUMULATE_WITH_REDUCE(r, data, type) \
+ inline bool can_accumulate_with_reduce(type init, plus<type>) \
+ { \
+ return init == type(0); \
+ } \
+ inline bool can_accumulate_with_reduce(type init, multiplies<type>) \
+ { \
+ return init == type(1); \
+ }
+
+BOOST_PP_SEQ_FOR_EACH(
+ BOOST_COMPUTE_DETAIL_DECLARE_CAN_ACCUMULATE_WITH_REDUCE,
+ _,
+ (char_)(uchar_)(short_)(ushort_)(int_)(uint_)(long_)(ulong_)
+)
+
+template<class T>
+inline bool can_accumulate_with_reduce(T init, min<T>)
+{
+ return init == (std::numeric_limits<T>::max)();
+}
+
+template<class T>
+inline bool can_accumulate_with_reduce(T init, max<T>)
+{
+ return init == (std::numeric_limits<T>::min)();
+}
+
+#undef BOOST_COMPUTE_DETAIL_DECLARE_CAN_ACCUMULATE_WITH_REDUCE
+
+template<class InputIterator, class T, class BinaryFunction>
+inline T dispatch_accumulate(InputIterator first,
+ InputIterator last,
+ T init,
+ BinaryFunction function,
+ command_queue &queue)
+{
+ size_t size = iterator_range_size(first, last);
+ if(size == 0){
+ return init;
+ }
+
+ if(can_accumulate_with_reduce(init, function)){
+ T result;
+ reduce(first, last, &result, function, queue);
+ return result;
+ }
+ else {
+ return generic_accumulate(first, last, init, function, queue);
+ }
+}
+
+} // end detail namespace
+
+/// Returns the result of applying \p function to the elements in the
+/// range [\p first, \p last) and \p init.
+///
+/// If no function is specified, \c plus will be used.
+///
+/// \param first first element in the input range
+/// \param last last element in the input range
+/// \param init initial value
+/// \param function binary reduction function
+/// \param queue command queue to perform the operation
+///
+/// \return the accumulated result value
+///
+/// In specific situations the call to \c accumulate() can be automatically
+/// optimized to a call to the more efficient \c reduce() algorithm. This
+/// occurs when the binary reduction function is recognized as associative
+/// (such as the \c plus<int> function).
+///
+/// Note that because floating-point addition is not associative, calling
+/// \c accumulate() with \c plus<float> results in a less efficient serial
+/// reduction algorithm being executed. If a slight loss in precision is
+/// acceptable, the more efficient parallel \c reduce() algorithm should be
+/// used instead.
+///
+/// For example:
+/// \code
+/// // with vec = boost::compute::vector<int>
+/// accumulate(vec.begin(), vec.end(), 0, plus<int>()); // fast
+/// reduce(vec.begin(), vec.end(), &result, plus<int>()); // fast
+///
+/// // with vec = boost::compute::vector<float>
+/// accumulate(vec.begin(), vec.end(), 0, plus<float>()); // slow
+/// reduce(vec.begin(), vec.end(), &result, plus<float>()); // fast
+/// \endcode
+///
+/// \see reduce()
+template<class InputIterator, class T, class BinaryFunction>
+inline T accumulate(InputIterator first,
+ InputIterator last,
+ T init,
+ BinaryFunction function,
+ command_queue &queue = system::default_queue())
+{
+ return detail::dispatch_accumulate(first, last, init, function, queue);
+}
+
+/// \overload
+template<class InputIterator, class T>
+inline T accumulate(InputIterator first,
+ InputIterator last,
+ T init,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type IT;
+
+ return detail::dispatch_accumulate(first, last, init, plus<IT>(), queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_ACCUMULATE_HPP
diff --git a/boost/compute/algorithm/adjacent_difference.hpp b/boost/compute/algorithm/adjacent_difference.hpp
new file mode 100644
index 0000000000..a8f84e020e
--- /dev/null
+++ b/boost/compute/algorithm/adjacent_difference.hpp
@@ -0,0 +1,98 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_ADJACENT_DIFFERENCE_HPP
+#define BOOST_COMPUTE_ALGORITHM_ADJACENT_DIFFERENCE_HPP
+
+#include <iterator>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/functional/operator.hpp>
+#include <boost/compute/container/vector.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Stores the difference of each pair of consecutive values in the range
+/// [\p first, \p last) to the range beginning at \p result. If \p op is not
+/// provided, \c minus<T> is used.
+///
+/// \param first first element in the input range
+/// \param last last element in the input range
+/// \param result first element in the output range
+/// \param op binary difference function
+/// \param queue command queue to perform the operation
+///
+/// \return \c OutputIterator to the end of the result range
+///
+/// \see adjacent_find()
+template<class InputIterator, class OutputIterator, class BinaryFunction>
+inline OutputIterator
+adjacent_difference(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ BinaryFunction op,
+ command_queue &queue = system::default_queue())
+{
+ if(first == last){
+ return result;
+ }
+
+ size_t count = detail::iterator_range_size(first, last);
+
+ detail::meta_kernel k("adjacent_difference");
+
+ k << "const uint i = get_global_id(0);\n"
+ << "if(i == 0){\n"
+ << " " << result[k.var<uint_>("0")] << " = " << first[k.var<uint_>("0")] << ";\n"
+ << "}\n"
+ << "else {\n"
+ << " " << result[k.var<uint_>("i")] << " = "
+ << op(first[k.var<uint_>("i")], first[k.var<uint_>("i-1")]) << ";\n"
+ << "}\n";
+
+ k.exec_1d(queue, 0, count, 1);
+
+ return result + count;
+}
+
+/// \overload
+template<class InputIterator, class OutputIterator>
+inline OutputIterator
+adjacent_difference(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ if (first == result) {
+ vector<value_type> temp(detail::iterator_range_size(first, last),
+ queue.get_context());
+ copy(first, last, temp.begin(), queue);
+
+ return ::boost::compute::adjacent_difference(
+ temp.begin(), temp.end(), result, ::boost::compute::minus<value_type>(), queue
+ );
+ }
+ else {
+ return ::boost::compute::adjacent_difference(
+ first, last, result, ::boost::compute::minus<value_type>(), queue
+ );
+ }
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_ADJACENT_DIFFERENCE_HPP
diff --git a/boost/compute/algorithm/adjacent_find.hpp b/boost/compute/algorithm/adjacent_find.hpp
new file mode 100644
index 0000000000..992a01eddc
--- /dev/null
+++ b/boost/compute/algorithm/adjacent_find.hpp
@@ -0,0 +1,162 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_ADJACENT_FIND_HPP
+#define BOOST_COMPUTE_ALGORITHM_ADJACENT_FIND_HPP
+
+#include <iterator>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/container/detail/scalar.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/functional/operator.hpp>
+#include <boost/compute/type_traits/vector_size.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator, class Compare>
+inline InputIterator
+serial_adjacent_find(InputIterator first,
+ InputIterator last,
+ Compare compare,
+ command_queue &queue)
+{
+ if(first == last){
+ return last;
+ }
+
+ const context &context = queue.get_context();
+
+ detail::scalar<uint_> output(context);
+
+ detail::meta_kernel k("serial_adjacent_find");
+
+ size_t size_arg = k.add_arg<const uint_>("size");
+ size_t output_arg = k.add_arg<uint_ *>(memory_object::global_memory, "output");
+
+ k << k.decl<uint_>("result") << " = size;\n"
+ << "for(uint i = 0; i < size - 1; i++){\n"
+ << " if(" << compare(first[k.expr<uint_>("i")],
+ first[k.expr<uint_>("i+1")]) << "){\n"
+ << " result = i;\n"
+ << " break;\n"
+ << " }\n"
+ << "}\n"
+ << "*output = result;\n";
+
+ k.set_arg<const uint_>(
+ size_arg, static_cast<uint_>(detail::iterator_range_size(first, last))
+ );
+ k.set_arg(output_arg, output.get_buffer());
+
+ k.exec_1d(queue, 0, 1, 1);
+
+ return first + output.read(queue);
+}
+
+template<class InputIterator, class Compare>
+inline InputIterator
+adjacent_find_with_atomics(InputIterator first,
+ InputIterator last,
+ Compare compare,
+ command_queue &queue)
+{
+ if(first == last){
+ return last;
+ }
+
+ const context &context = queue.get_context();
+ size_t count = detail::iterator_range_size(first, last);
+
+ // initialize output to the last index
+ detail::scalar<uint_> output(context);
+ output.write(static_cast<uint_>(count), queue);
+
+ detail::meta_kernel k("adjacent_find_with_atomics");
+
+ size_t output_arg = k.add_arg<uint_ *>(memory_object::global_memory, "output");
+
+ k << "const uint i = get_global_id(0);\n"
+ << "if(" << compare(first[k.expr<uint_>("i")],
+ first[k.expr<uint_>("i+1")]) << "){\n"
+ << " atomic_min(output, i);\n"
+ << "}\n";
+
+ k.set_arg(output_arg, output.get_buffer());
+
+ k.exec_1d(queue, 0, count - 1, 1);
+
+ return first + output.read(queue);
+}
+
+} // end detail namespace
+
+/// Searches the range [\p first, \p last) for two identical adjacent
+/// elements and returns an iterator pointing to the first.
+///
+/// \param first first element in the range to search
+/// \param last last element in the range to search
+/// \param compare binary comparison function
+/// \param queue command queue to perform the operation
+///
+/// \return \c InputIteratorm to the first element which compares equal
+/// to the following element. If none are equal, returns \c last.
+///
+/// \see find(), adjacent_difference()
+template<class InputIterator, class Compare>
+inline InputIterator
+adjacent_find(InputIterator first,
+ InputIterator last,
+ Compare compare,
+ command_queue &queue = system::default_queue())
+{
+ size_t count = detail::iterator_range_size(first, last);
+ if(count < 32){
+ return detail::serial_adjacent_find(first, last, compare, queue);
+ }
+ else {
+ return detail::adjacent_find_with_atomics(first, last, compare, queue);
+ }
+}
+
+/// \overload
+template<class InputIterator>
+inline InputIterator
+adjacent_find(InputIterator first,
+ InputIterator last,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ using ::boost::compute::lambda::_1;
+ using ::boost::compute::lambda::_2;
+ using ::boost::compute::lambda::all;
+
+ if(vector_size<value_type>::value == 1){
+ return ::boost::compute::adjacent_find(
+ first, last, _1 == _2, queue
+ );
+ }
+ else {
+ return ::boost::compute::adjacent_find(
+ first, last, all(_1 == _2), queue
+ );
+ }
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_ADJACENT_FIND_HPP
diff --git a/boost/compute/algorithm/all_of.hpp b/boost/compute/algorithm/all_of.hpp
new file mode 100644
index 0000000000..34d7518f32
--- /dev/null
+++ b/boost/compute/algorithm/all_of.hpp
@@ -0,0 +1,36 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_ALL_OF_HPP
+#define BOOST_COMPUTE_ALGORITHM_ALL_OF_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/find_if_not.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns \c true if \p predicate returns \c true for all of the elements in
+/// the range [\p first, \p last).
+///
+/// \see any_of(), none_of()
+template<class InputIterator, class UnaryPredicate>
+inline bool all_of(InputIterator first,
+ InputIterator last,
+ UnaryPredicate predicate,
+ command_queue &queue = system::default_queue())
+{
+ return ::boost::compute::find_if_not(first, last, predicate, queue) == last;
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_ALL_OF_HPP
diff --git a/boost/compute/algorithm/any_of.hpp b/boost/compute/algorithm/any_of.hpp
new file mode 100644
index 0000000000..b07779597c
--- /dev/null
+++ b/boost/compute/algorithm/any_of.hpp
@@ -0,0 +1,40 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_ANY_OF_HPP
+#define BOOST_COMPUTE_ALGORITHM_ANY_OF_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/find_if.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns \c true if \p predicate returns \c true for any of the elements in
+/// the range [\p first, \p last).
+///
+/// For example, to test if a vector contains any negative values:
+///
+/// \snippet test/test_any_all_none_of.cpp any_of
+///
+/// \see all_of(), none_of()
+template<class InputIterator, class UnaryPredicate>
+inline bool any_of(InputIterator first,
+ InputIterator last,
+ UnaryPredicate predicate,
+ command_queue &queue = system::default_queue())
+{
+ return ::boost::compute::find_if(first, last, predicate, queue) != last;
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_ANY_OF_HPP
diff --git a/boost/compute/algorithm/binary_search.hpp b/boost/compute/algorithm/binary_search.hpp
new file mode 100644
index 0000000000..6e19498790
--- /dev/null
+++ b/boost/compute/algorithm/binary_search.hpp
@@ -0,0 +1,37 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_BINARY_SEARCH_HPP
+#define BOOST_COMPUTE_ALGORITHM_BINARY_SEARCH_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/lower_bound.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns \c true if \p value is in the sorted range [\p first,
+/// \p last).
+template<class InputIterator, class T>
+inline bool binary_search(InputIterator first,
+ InputIterator last,
+ const T &value,
+ command_queue &queue = system::default_queue())
+{
+ InputIterator position = lower_bound(first, last, value, queue);
+
+ return position != last && position.read(queue) == value;
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_BINARY_SEARCH_HPP
diff --git a/boost/compute/algorithm/copy.hpp b/boost/compute/algorithm/copy.hpp
new file mode 100644
index 0000000000..2a25059bba
--- /dev/null
+++ b/boost/compute/algorithm/copy.hpp
@@ -0,0 +1,362 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_COPY_HPP
+#define BOOST_COMPUTE_ALGORITHM_COPY_HPP
+
+#include <algorithm>
+#include <iterator>
+
+#include <boost/utility/enable_if.hpp>
+
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/not.hpp>
+
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/detail/copy_on_device.hpp>
+#include <boost/compute/algorithm/detail/copy_to_device.hpp>
+#include <boost/compute/algorithm/detail/copy_to_host.hpp>
+#include <boost/compute/async/future.hpp>
+#include <boost/compute/detail/is_contiguous_iterator.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+#include <boost/compute/type_traits/is_device_iterator.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+namespace mpl = boost::mpl;
+
+// meta-function returning true if copy() between InputIterator and
+// OutputIterator can be implemented with clEnqueueCopyBuffer().
+template<class InputIterator, class OutputIterator>
+struct can_copy_with_copy_buffer :
+ mpl::and_<
+ boost::is_same<
+ InputIterator,
+ buffer_iterator<typename InputIterator::value_type>
+ >,
+ boost::is_same<
+ OutputIterator,
+ buffer_iterator<typename OutputIterator::value_type>
+ >,
+ boost::is_same<
+ typename InputIterator::value_type,
+ typename OutputIterator::value_type
+ >
+ >::type {};
+
+// host -> device
+template<class InputIterator, class OutputIterator>
+inline OutputIterator
+dispatch_copy(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue,
+ typename boost::enable_if_c<
+ !is_device_iterator<InputIterator>::value &&
+ is_device_iterator<OutputIterator>::value
+ >::type* = 0)
+{
+ if(is_contiguous_iterator<InputIterator>::value){
+ return copy_to_device(first, last, result, queue);
+ }
+ else {
+ // for non-contiguous input we first copy the values to
+ // a temporary std::vector and then copy from there
+ typedef typename std::iterator_traits<InputIterator>::value_type T;
+ std::vector<T> vector(first, last);
+ return copy_to_device(vector.begin(), vector.end(), result, queue);
+ }
+}
+
+// host -> device (async)
+template<class InputIterator, class OutputIterator>
+inline future<OutputIterator>
+dispatch_copy_async(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue,
+ typename boost::enable_if_c<
+ !is_device_iterator<InputIterator>::value &&
+ is_device_iterator<OutputIterator>::value
+ >::type* = 0)
+{
+ BOOST_STATIC_ASSERT_MSG(
+ is_contiguous_iterator<InputIterator>::value,
+ "copy_async() is only supported for contiguous host iterators"
+ );
+
+ return copy_to_device_async(first, last, result, queue);
+}
+
+// device -> host
+template<class InputIterator, class OutputIterator>
+inline OutputIterator
+dispatch_copy(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue,
+ typename boost::enable_if_c<
+ is_device_iterator<InputIterator>::value &&
+ !is_device_iterator<OutputIterator>::value
+ >::type* = 0)
+{
+ if(is_contiguous_iterator<OutputIterator>::value){
+ return copy_to_host(first, last, result, queue);
+ }
+ else {
+ // for non-contiguous input we first copy the values to
+ // a temporary std::vector and then copy from there
+ typedef typename std::iterator_traits<InputIterator>::value_type T;
+ std::vector<T> vector(iterator_range_size(first, last));
+ copy_to_host(first, last, vector.begin(), queue);
+ return std::copy(vector.begin(), vector.end(), result);
+ }
+}
+
+// device -> host (async)
+template<class InputIterator, class OutputIterator>
+inline future<OutputIterator>
+dispatch_copy_async(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue,
+ typename boost::enable_if_c<
+ is_device_iterator<InputIterator>::value &&
+ !is_device_iterator<OutputIterator>::value
+ >::type* = 0)
+{
+ BOOST_STATIC_ASSERT_MSG(
+ is_contiguous_iterator<OutputIterator>::value,
+ "copy_async() is only supported for contiguous host iterators"
+ );
+
+ return copy_to_host_async(first, last, result, queue);
+}
+
+// device -> device
+template<class InputIterator, class OutputIterator>
+inline OutputIterator
+dispatch_copy(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue,
+ typename boost::enable_if<
+ mpl::and_<
+ is_device_iterator<InputIterator>,
+ is_device_iterator<OutputIterator>,
+ mpl::not_<
+ can_copy_with_copy_buffer<
+ InputIterator, OutputIterator
+ >
+ >
+ >
+ >::type* = 0)
+{
+ return copy_on_device(first, last, result, queue);
+}
+
+// device -> device (specialization for buffer iterators)
+template<class InputIterator, class OutputIterator>
+inline OutputIterator
+dispatch_copy(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue,
+ typename boost::enable_if<
+ mpl::and_<
+ is_device_iterator<InputIterator>,
+ is_device_iterator<OutputIterator>,
+ can_copy_with_copy_buffer<
+ InputIterator, OutputIterator
+ >
+ >
+ >::type* = 0)
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+ typedef typename std::iterator_traits<InputIterator>::difference_type difference_type;
+
+ difference_type n = std::distance(first, last);
+ if(n < 1){
+ // nothing to copy
+ return result;
+ }
+
+ queue.enqueue_copy_buffer(first.get_buffer(),
+ result.get_buffer(),
+ first.get_index() * sizeof(value_type),
+ result.get_index() * sizeof(value_type),
+ static_cast<size_t>(n) * sizeof(value_type));
+ return result + n;
+}
+
+// device -> device (async)
+template<class InputIterator, class OutputIterator>
+inline future<OutputIterator>
+dispatch_copy_async(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue,
+ typename boost::enable_if<
+ mpl::and_<
+ is_device_iterator<InputIterator>,
+ is_device_iterator<OutputIterator>,
+ mpl::not_<
+ can_copy_with_copy_buffer<
+ InputIterator, OutputIterator
+ >
+ >
+ >
+ >::type* = 0)
+{
+ return copy_on_device_async(first, last, result, queue);
+}
+
+// device -> device (async, specialization for buffer iterators)
+template<class InputIterator, class OutputIterator>
+inline future<OutputIterator>
+dispatch_copy_async(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue,
+ typename boost::enable_if<
+ mpl::and_<
+ is_device_iterator<InputIterator>,
+ is_device_iterator<OutputIterator>,
+ can_copy_with_copy_buffer<
+ InputIterator, OutputIterator
+ >
+ >
+ >::type* = 0)
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+ typedef typename std::iterator_traits<InputIterator>::difference_type difference_type;
+
+ difference_type n = std::distance(first, last);
+ if(n < 1){
+ // nothing to copy
+ return make_future(result, event());
+ }
+
+ event event_ =
+ queue.enqueue_copy_buffer(
+ first.get_buffer(),
+ result.get_buffer(),
+ first.get_index() * sizeof(value_type),
+ result.get_index() * sizeof(value_type),
+ static_cast<size_t>(n) * sizeof(value_type)
+ );
+
+ return make_future(result + n, event_);
+}
+
+// host -> host
+template<class InputIterator, class OutputIterator>
+inline OutputIterator
+dispatch_copy(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue,
+ typename boost::enable_if_c<
+ !is_device_iterator<InputIterator>::value &&
+ !is_device_iterator<OutputIterator>::value
+ >::type* = 0)
+{
+ (void) queue;
+
+ return std::copy(first, last, result);
+}
+
+} // end detail namespace
+
+/// Copies the values in the range [\p first, \p last) to the range
+/// beginning at \p result.
+///
+/// The generic copy() function can be used for a variety of data
+/// transfer tasks and provides a standard interface to the following
+/// OpenCL functions:
+///
+/// \li \c clEnqueueReadBuffer()
+/// \li \c clEnqueueWriteBuffer()
+/// \li \c clEnqueueCopyBuffer()
+///
+/// Unlike the aforementioned OpenCL functions, copy() will also work
+/// with non-contiguous data-structures (e.g. \c std::list<T>) as
+/// well as with "fancy" iterators (e.g. transform_iterator).
+///
+/// \param first first element in the range to copy
+/// \param last last element in the range to copy
+/// \param result first element in the result range
+/// \param queue command queue to perform the operation
+///
+/// \return \c OutputIterator to the end of the result range
+///
+/// For example, to copy an array of \c int values on the host to a vector on
+/// the device:
+/// \code
+/// // array on the host
+/// int data[] = { 1, 2, 3, 4 };
+///
+/// // vector on the device
+/// boost::compute::vector<int> vec(4, context);
+///
+/// // copy values to the device vector
+/// boost::compute::copy(data, data + 4, vec.begin(), queue);
+/// \endcode
+///
+/// The copy algorithm can also be used with standard containers such as
+/// \c std::vector<T>:
+/// \code
+/// std::vector<int> host_vector = ...
+/// boost::compute::vector<int> device_vector = ...
+///
+/// // copy from the host to the device
+/// boost::compute::copy(
+/// host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+/// );
+///
+/// // copy from the device to the host
+/// boost::compute::copy(
+/// device_vector.begin(), device_vector.end(), host_vector.begin(), queue
+/// );
+/// \endcode
+///
+/// \see copy_n(), copy_if(), copy_async()
+template<class InputIterator, class OutputIterator>
+inline OutputIterator copy(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
+{
+ return detail::dispatch_copy(first, last, result, queue);
+}
+
+/// Copies the values in the range [\p first, \p last) to the range
+/// beginning at \p result. The copy is performed asynchronously.
+///
+/// \see copy()
+template<class InputIterator, class OutputIterator>
+inline future<OutputIterator>
+copy_async(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
+{
+ return detail::dispatch_copy_async(first, last, result, queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_COPY_HPP
diff --git a/boost/compute/algorithm/copy_if.hpp b/boost/compute/algorithm/copy_if.hpp
new file mode 100644
index 0000000000..3cd08ef293
--- /dev/null
+++ b/boost/compute/algorithm/copy_if.hpp
@@ -0,0 +1,58 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_COPY_IF_HPP
+#define BOOST_COMPUTE_ALGORITHM_COPY_IF_HPP
+
+#include <boost/compute/algorithm/transform_if.hpp>
+#include <boost/compute/functional/identity.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+// like the copy_if() algorithm but writes the indices of the values for which
+// predicate returns true.
+template<class InputIterator, class OutputIterator, class Predicate>
+inline OutputIterator copy_index_if(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ Predicate predicate,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type T;
+
+ return detail::transform_if_impl(
+ first, last, result, identity<T>(), predicate, true, queue
+ );
+}
+
+} // end detail namespace
+
+/// Copies each element in the range [\p first, \p last) for which
+/// \p predicate returns \c true to the range beginning at \p result.
+template<class InputIterator, class OutputIterator, class Predicate>
+inline OutputIterator copy_if(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ Predicate predicate,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type T;
+
+ return ::boost::compute::transform_if(
+ first, last, result, identity<T>(), predicate, queue
+ );
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_COPY_IF_HPP
diff --git a/boost/compute/algorithm/copy_n.hpp b/boost/compute/algorithm/copy_n.hpp
new file mode 100644
index 0000000000..f0989edc67
--- /dev/null
+++ b/boost/compute/algorithm/copy_n.hpp
@@ -0,0 +1,51 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_COPY_N_HPP
+#define BOOST_COMPUTE_ALGORITHM_COPY_N_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Copies \p count elements from \p first to \p result.
+///
+/// For example, to copy four values from the host to the device:
+/// \code
+/// // values on the host and vector on the device
+/// float values[4] = { 1.f, 2.f, 3.f, 4.f };
+/// boost::compute::vector<float> vec(4, context);
+///
+/// // copy from the host to the device
+/// boost::compute::copy_n(values, 4, vec.begin(), queue);
+/// \endcode
+///
+/// \see copy()
+template<class InputIterator, class Size, class OutputIterator>
+inline OutputIterator copy_n(InputIterator first,
+ Size count,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator>::difference_type difference_type;
+
+ return ::boost::compute::copy(first,
+ first + static_cast<difference_type>(count),
+ result,
+ queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_COPY_N_HPP
diff --git a/boost/compute/algorithm/count.hpp b/boost/compute/algorithm/count.hpp
new file mode 100644
index 0000000000..140d67379f
--- /dev/null
+++ b/boost/compute/algorithm/count.hpp
@@ -0,0 +1,55 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_COUNT_HPP
+#define BOOST_COMPUTE_ALGORITHM_COUNT_HPP
+
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/count_if.hpp>
+#include <boost/compute/type_traits/vector_size.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns the number of occurrences of \p value in the range
+/// [\p first, \p last).
+///
+/// \see count_if()
+template<class InputIterator, class T>
+inline size_t count(InputIterator first,
+ InputIterator last,
+ const T &value,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ using ::boost::compute::_1;
+ using ::boost::compute::lambda::all;
+
+ if(vector_size<value_type>::value == 1){
+ return ::boost::compute::count_if(first,
+ last,
+ _1 == value,
+ queue);
+ }
+ else {
+ return ::boost::compute::count_if(first,
+ last,
+ all(_1 == value),
+ queue);
+ }
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_COUNT_HPP
diff --git a/boost/compute/algorithm/count_if.hpp b/boost/compute/algorithm/count_if.hpp
new file mode 100644
index 0000000000..c9381ce5d4
--- /dev/null
+++ b/boost/compute/algorithm/count_if.hpp
@@ -0,0 +1,62 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_COUNT_IF_HPP
+#define BOOST_COMPUTE_ALGORITHM_COUNT_IF_HPP
+
+#include <boost/compute/device.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/detail/count_if_with_ballot.hpp>
+#include <boost/compute/algorithm/detail/count_if_with_reduce.hpp>
+#include <boost/compute/algorithm/detail/count_if_with_threads.hpp>
+#include <boost/compute/algorithm/detail/serial_count_if.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns the number of elements in the range [\p first, \p last)
+/// for which \p predicate returns \c true.
+template<class InputIterator, class Predicate>
+inline size_t count_if(InputIterator first,
+ InputIterator last,
+ Predicate predicate,
+ command_queue &queue = system::default_queue())
+{
+ const device &device = queue.get_device();
+
+ size_t input_size = detail::iterator_range_size(first, last);
+ if(input_size == 0){
+ return 0;
+ }
+
+ if(device.type() & device::cpu){
+ if(input_size < 1024){
+ return detail::serial_count_if(first, last, predicate, queue);
+ }
+ else {
+ return detail::count_if_with_threads(first, last, predicate, queue);
+ }
+ }
+ else {
+ if(input_size < 32){
+ return detail::serial_count_if(first, last, predicate, queue);
+ }
+ else {
+ return detail::count_if_with_reduce(first, last, predicate, queue);
+ }
+ }
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_COUNT_IF_HPP
diff --git a/boost/compute/algorithm/detail/balanced_path.hpp b/boost/compute/algorithm/detail/balanced_path.hpp
new file mode 100644
index 0000000000..e5025532d3
--- /dev/null
+++ b/boost/compute/algorithm/detail/balanced_path.hpp
@@ -0,0 +1,162 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_BALANCED_PATH_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_BALANCED_PATH_HPP
+
+#include <iterator>
+
+#include <boost/compute/algorithm/find_if.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/system.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+///
+/// \brief Balanced Path kernel class
+///
+/// Subclass of meta_kernel to break two sets into tiles according
+/// to their balanced path.
+///
+class balanced_path_kernel : public meta_kernel
+{
+public:
+ unsigned int tile_size;
+
+ balanced_path_kernel() : meta_kernel("balanced_path")
+ {
+ tile_size = 4;
+ }
+
+ template<class InputIterator1, class InputIterator2,
+ class OutputIterator1, class OutputIterator2,
+ class Compare>
+ void set_range(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator1 result_a,
+ OutputIterator2 result_b,
+ Compare comp)
+ {
+ typedef typename std::iterator_traits<InputIterator1>::value_type value_type;
+
+ m_a_count = iterator_range_size(first1, last1);
+ m_a_count_arg = add_arg<uint_>("a_count");
+
+ m_b_count = iterator_range_size(first2, last2);
+ m_b_count_arg = add_arg<uint_>("b_count");
+
+ *this <<
+ "uint i = get_global_id(0);\n" <<
+ "uint target = (i+1)*" << tile_size << ";\n" <<
+ "uint start = max(convert_int(0),convert_int(target)-convert_int(b_count));\n" <<
+ "uint end = min(target,a_count);\n" <<
+ "uint a_index, b_index;\n" <<
+ "while(start<end)\n" <<
+ "{\n" <<
+ " a_index = (start + end)/2;\n" <<
+ " b_index = target - a_index - 1;\n" <<
+ " if(!(" << comp(first2[expr<uint_>("b_index")],
+ first1[expr<uint_>("a_index")]) << "))\n" <<
+ " start = a_index + 1;\n" <<
+ " else end = a_index;\n" <<
+ "}\n" <<
+ "a_index = start;\n" <<
+ "b_index = target - start;\n" <<
+ "if(b_index < b_count)\n" <<
+ "{\n" <<
+ " " << decl<const value_type>("x") << " = " <<
+ first2[expr<uint_>("b_index")] << ";\n" <<
+ " uint a_start = 0, a_end = a_index, a_mid;\n" <<
+ " uint b_start = 0, b_end = b_index, b_mid;\n" <<
+ " while(a_start<a_end)\n" <<
+ " {\n" <<
+ " a_mid = (a_start + a_end)/2;\n" <<
+ " if(" << comp(first1[expr<uint_>("a_mid")], expr<value_type>("x")) << ")\n" <<
+ " a_start = a_mid+1;\n" <<
+ " else a_end = a_mid;\n" <<
+ " }\n" <<
+ " while(b_start<b_end)\n" <<
+ " {\n" <<
+ " b_mid = (b_start + b_end)/2;\n" <<
+ " if(" << comp(first2[expr<uint_>("b_mid")], expr<value_type>("x")) << ")\n" <<
+ " b_start = b_mid+1;\n" <<
+ " else b_end = b_mid;\n" <<
+ " }\n" <<
+ " uint a_run = a_index - a_start;\n" <<
+ " uint b_run = b_index - b_start;\n" <<
+ " uint x_count = a_run + b_run;\n" <<
+ " uint b_advance = max(x_count / 2, x_count - a_run);\n" <<
+ " b_end = min(b_count, b_start + b_advance + 1);\n" <<
+ " uint temp_start = b_index, temp_end = b_end, temp_mid;" <<
+ " while(temp_start < temp_end)\n" <<
+ " {\n" <<
+ " temp_mid = (temp_start + temp_end + 1)/2;\n" <<
+ " if(" << comp(expr<value_type>("x"), first2[expr<uint_>("temp_mid")]) << ")\n" <<
+ " temp_end = temp_mid-1;\n" <<
+ " else temp_start = temp_mid;\n" <<
+ " }\n" <<
+ " b_run = temp_start - b_start + 1;\n" <<
+ " b_advance = min(b_advance, b_run);\n" <<
+ " uint a_advance = x_count - b_advance;\n" <<
+ " uint star = convert_uint((a_advance == b_advance + 1) " <<
+ "&& (b_advance < b_run));\n" <<
+ " a_index = a_start + a_advance;\n" <<
+ " b_index = target - a_index + star;\n" <<
+ "}\n" <<
+ result_a[expr<uint_>("i")] << " = a_index;\n" <<
+ result_b[expr<uint_>("i")] << " = b_index;\n";
+
+ }
+
+ template<class InputIterator1, class InputIterator2,
+ class OutputIterator1, class OutputIterator2>
+ void set_range(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator1 result_a,
+ OutputIterator2 result_b)
+ {
+ typedef typename std::iterator_traits<InputIterator1>::value_type value_type;
+ ::boost::compute::less<value_type> less_than;
+ set_range(first1, last1, first2, last2, result_a, result_b, less_than);
+ }
+
+ event exec(command_queue &queue)
+ {
+ if((m_a_count + m_b_count)/tile_size == 0) {
+ return event();
+ }
+
+ set_arg(m_a_count_arg, uint_(m_a_count));
+ set_arg(m_b_count_arg, uint_(m_b_count));
+
+ return exec_1d(queue, 0, (m_a_count + m_b_count)/tile_size);
+ }
+
+private:
+ size_t m_a_count;
+ size_t m_a_count_arg;
+ size_t m_b_count;
+ size_t m_b_count_arg;
+};
+
+} //end detail namespace
+} //end compute namespace
+} //end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_BALANCED_PATH_HPP
diff --git a/boost/compute/algorithm/detail/binary_find.hpp b/boost/compute/algorithm/detail/binary_find.hpp
new file mode 100644
index 0000000000..27fa11fbaf
--- /dev/null
+++ b/boost/compute/algorithm/detail/binary_find.hpp
@@ -0,0 +1,133 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_BINARY_FIND_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_BINARY_FIND_HPP
+
+#include <boost/compute/functional.hpp>
+#include <boost/compute/algorithm/find_if.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/detail/parameter_cache.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail{
+
+///
+/// \brief Binary find kernel class
+///
+/// Subclass of meta_kernel to perform single step in binary find.
+///
+template<class InputIterator, class UnaryPredicate>
+class binary_find_kernel : public meta_kernel
+{
+public:
+ binary_find_kernel(InputIterator first,
+ InputIterator last,
+ UnaryPredicate predicate)
+ : meta_kernel("binary_find")
+ {
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ m_index_arg = add_arg<uint_ *>(memory_object::global_memory, "index");
+ m_block_arg = add_arg<uint_>("block");
+
+ atomic_min<uint_> atomic_min_uint;
+
+ *this <<
+ "uint i = get_global_id(0) * block;\n" <<
+ decl<value_type>("value") << "=" << first[var<uint_>("i")] << ";\n" <<
+ "if(" << predicate(var<value_type>("value")) << ") {\n" <<
+ atomic_min_uint(var<uint_ *>("index"), var<uint_>("i")) << ";\n" <<
+ "}\n";
+ }
+
+ size_t m_index_arg;
+ size_t m_block_arg;
+};
+
+///
+/// \brief Binary find algorithm
+///
+/// Finds the end of true values in the partitioned range [first, last).
+/// \return Iterator pointing to end of true values
+///
+/// \param first Iterator pointing to start of range
+/// \param last Iterator pointing to end of range
+/// \param predicate Predicate according to which the range is partitioned
+/// \param queue Queue on which to execute
+///
+template<class InputIterator, class UnaryPredicate>
+inline InputIterator binary_find(InputIterator first,
+ InputIterator last,
+ UnaryPredicate predicate,
+ command_queue &queue = system::default_queue())
+{
+ const device &device = queue.get_device();
+
+ boost::shared_ptr<parameter_cache> parameters =
+ detail::parameter_cache::get_global_cache(device);
+
+ const std::string cache_key = "__boost_binary_find";
+
+ size_t find_if_limit = 128;
+ size_t threads = parameters->get(cache_key, "tpb", 128);
+ size_t count = iterator_range_size(first, last);
+
+ InputIterator search_first = first;
+ InputIterator search_last = last;
+
+ scalar<uint_> index(queue.get_context());
+
+ // construct and compile binary_find kernel
+ binary_find_kernel<InputIterator, UnaryPredicate>
+ binary_find_kernel(search_first, search_last, predicate);
+ ::boost::compute::kernel kernel = binary_find_kernel.compile(queue.get_context());
+
+ // set buffer for index
+ kernel.set_arg(binary_find_kernel.m_index_arg, index.get_buffer());
+
+ while(count > find_if_limit) {
+ index.write(static_cast<uint_>(count), queue);
+
+ // set block and run binary_find kernel
+ uint_ block = static_cast<uint_>((count - 1)/(threads - 1));
+ kernel.set_arg(binary_find_kernel.m_block_arg, block);
+ queue.enqueue_1d_range_kernel(kernel, 0, threads, 0);
+
+ size_t i = index.read(queue);
+
+ if(i == count) {
+ search_first = search_last - ((count - 1)%(threads - 1));
+ break;
+ } else {
+ search_last = search_first + i;
+ search_first = search_last - ((count - 1)/(threads - 1));
+ }
+
+ // Make sure that first and last stay within the input range
+ search_last = (std::min)(search_last, last);
+ search_last = (std::max)(search_last, first);
+
+ search_first = (std::max)(search_first, first);
+ search_first = (std::min)(search_first, last);
+
+ count = iterator_range_size(search_first, search_last);
+ }
+
+ return find_if(search_first, search_last, predicate, queue);
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_BINARY_FIND_HPP
diff --git a/boost/compute/algorithm/detail/compact.hpp b/boost/compute/algorithm/detail/compact.hpp
new file mode 100644
index 0000000000..983352d543
--- /dev/null
+++ b/boost/compute/algorithm/detail/compact.hpp
@@ -0,0 +1,77 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_COMPACT_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_COMPACT_HPP
+
+#include <iterator>
+
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/system.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+///
+/// \brief Compact kernel class
+///
+/// Subclass of meta_kernel to compact the result of set kernels to
+/// get actual sets
+///
+class compact_kernel : public meta_kernel
+{
+public:
+ unsigned int tile_size;
+
+ compact_kernel() : meta_kernel("compact")
+ {
+ tile_size = 4;
+ }
+
+ template<class InputIterator1, class InputIterator2, class OutputIterator>
+ void set_range(InputIterator1 start,
+ InputIterator2 counts_begin,
+ InputIterator2 counts_end,
+ OutputIterator result)
+ {
+ m_count = iterator_range_size(counts_begin, counts_end) - 1;
+
+ *this <<
+ "uint i = get_global_id(0);\n" <<
+ "uint count = i*" << tile_size << ";\n" <<
+ "for(uint j = " << counts_begin[expr<uint_>("i")] << "; j<" <<
+ counts_begin[expr<uint_>("i+1")] << "; j++, count++)\n" <<
+ "{\n" <<
+ result[expr<uint_>("j")] << " = " << start[expr<uint_>("count")]
+ << ";\n" <<
+ "}\n";
+ }
+
+ event exec(command_queue &queue)
+ {
+ if(m_count == 0) {
+ return event();
+ }
+
+ return exec_1d(queue, 0, m_count);
+ }
+
+private:
+ size_t m_count;
+};
+
+} //end detail namespace
+} //end compute namespace
+} //end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_COMPACT_HPP
diff --git a/boost/compute/algorithm/detail/copy_on_device.hpp b/boost/compute/algorithm/detail/copy_on_device.hpp
new file mode 100644
index 0000000000..0bcee27ed5
--- /dev/null
+++ b/boost/compute/algorithm/detail/copy_on_device.hpp
@@ -0,0 +1,190 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_ON_DEVICE_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_ON_DEVICE_HPP
+
+#include <iterator>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/async/future.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+#include <boost/compute/iterator/discard_iterator.hpp>
+#include <boost/compute/memory/svm_ptr.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/parameter_cache.hpp>
+#include <boost/compute/detail/work_size.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+inline size_t pick_copy_work_group_size(size_t n, const device &device)
+{
+ (void) device;
+
+ if(n % 32 == 0) return 32;
+ else if(n % 16 == 0) return 16;
+ else if(n % 8 == 0) return 8;
+ else if(n % 4 == 0) return 4;
+ else if(n % 2 == 0) return 2;
+ else return 1;
+}
+
+template<class InputIterator, class OutputIterator>
+class copy_kernel : public meta_kernel
+{
+public:
+ copy_kernel(const device &device)
+ : meta_kernel("copy")
+ {
+ m_count = 0;
+
+ typedef typename std::iterator_traits<InputIterator>::value_type input_type;
+
+ boost::shared_ptr<parameter_cache> parameters =
+ detail::parameter_cache::get_global_cache(device);
+
+ std::string cache_key =
+ "__boost_copy_kernel_" + boost::lexical_cast<std::string>(sizeof(input_type));
+
+ m_vpt = parameters->get(cache_key, "vpt", 4);
+ m_tpb = parameters->get(cache_key, "tpb", 128);
+ }
+
+ void set_range(InputIterator first,
+ InputIterator last,
+ OutputIterator result)
+ {
+ m_count_arg = add_arg<uint_>("count");
+
+ *this <<
+ "uint index = get_local_id(0) + " <<
+ "(" << m_vpt * m_tpb << " * get_group_id(0));\n" <<
+ "for(uint i = 0; i < " << m_vpt << "; i++){\n" <<
+ " if(index < count){\n" <<
+ result[expr<uint_>("index")] << '=' <<
+ first[expr<uint_>("index")] << ";\n" <<
+ " index += " << m_tpb << ";\n"
+ " }\n"
+ "}\n";
+
+ m_count = detail::iterator_range_size(first, last);
+ }
+
+ event exec(command_queue &queue)
+ {
+ if(m_count == 0){
+ // nothing to do
+ return event();
+ }
+
+ size_t global_work_size = calculate_work_size(m_count, m_vpt, m_tpb);
+
+ set_arg(m_count_arg, uint_(m_count));
+
+ return exec_1d(queue, 0, global_work_size, m_tpb);
+ }
+
+private:
+ size_t m_count;
+ size_t m_count_arg;
+ uint_ m_vpt;
+ uint_ m_tpb;
+};
+
+template<class InputIterator, class OutputIterator>
+inline OutputIterator copy_on_device(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue)
+{
+ const device &device = queue.get_device();
+
+ copy_kernel<InputIterator, OutputIterator> kernel(device);
+
+ kernel.set_range(first, last, result);
+ kernel.exec(queue);
+
+ return result + std::distance(first, last);
+}
+
+template<class InputIterator>
+inline discard_iterator copy_on_device(InputIterator first,
+ InputIterator last,
+ discard_iterator result,
+ command_queue &queue)
+{
+ (void) queue;
+
+ return result + std::distance(first, last);
+}
+
+template<class InputIterator, class OutputIterator>
+inline future<OutputIterator> copy_on_device_async(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue)
+{
+ const device &device = queue.get_device();
+
+ copy_kernel<InputIterator, OutputIterator> kernel(device);
+
+ kernel.set_range(first, last, result);
+ event event_ = kernel.exec(queue);
+
+ return make_future(result + std::distance(first, last), event_);
+}
+
+#ifdef CL_VERSION_2_0
+// copy_on_device() specialization for svm_ptr
+template<class T>
+inline svm_ptr<T> copy_on_device(svm_ptr<T> first,
+ svm_ptr<T> last,
+ svm_ptr<T> result,
+ command_queue &queue)
+{
+ size_t count = iterator_range_size(first, last);
+ if(count == 0){
+ return result;
+ }
+
+ queue.enqueue_svm_memcpy(
+ result.get(), first.get(), count * sizeof(T)
+ );
+
+ return result + count;
+}
+
+template<class T>
+inline future<svm_ptr<T> > copy_on_device_async(svm_ptr<T> first,
+ svm_ptr<T> last,
+ svm_ptr<T> result,
+ command_queue &queue)
+{
+ size_t count = iterator_range_size(first, last);
+ if(count == 0){
+ return result;
+ }
+
+ event event_ = queue.enqueue_svm_memcpy_async(
+ result.get(), first.get(), count * sizeof(T)
+ );
+
+ return make_future(result + count, event_);
+}
+#endif // CL_VERSION_2_0
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_ON_DEVICE_HPP
diff --git a/boost/compute/algorithm/detail/copy_to_device.hpp b/boost/compute/algorithm/detail/copy_to_device.hpp
new file mode 100644
index 0000000000..90545fb4ed
--- /dev/null
+++ b/boost/compute/algorithm/detail/copy_to_device.hpp
@@ -0,0 +1,127 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_TO_DEVICE_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_TO_DEVICE_HPP
+
+#include <iterator>
+
+#include <boost/utility/addressof.hpp>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/async/future.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+#include <boost/compute/memory/svm_ptr.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class HostIterator, class DeviceIterator>
+inline DeviceIterator copy_to_device(HostIterator first,
+ HostIterator last,
+ DeviceIterator result,
+ command_queue &queue)
+{
+ typedef typename
+ std::iterator_traits<DeviceIterator>::value_type
+ value_type;
+ typedef typename
+ std::iterator_traits<DeviceIterator>::difference_type
+ difference_type;
+
+ size_t count = iterator_range_size(first, last);
+ if(count == 0){
+ return result;
+ }
+
+ size_t offset = result.get_index();
+
+ queue.enqueue_write_buffer(result.get_buffer(),
+ offset * sizeof(value_type),
+ count * sizeof(value_type),
+ ::boost::addressof(*first));
+
+ return result + static_cast<difference_type>(count);
+}
+
+template<class HostIterator, class DeviceIterator>
+inline future<DeviceIterator> copy_to_device_async(HostIterator first,
+ HostIterator last,
+ DeviceIterator result,
+ command_queue &queue)
+{
+ typedef typename
+ std::iterator_traits<DeviceIterator>::value_type
+ value_type;
+ typedef typename
+ std::iterator_traits<DeviceIterator>::difference_type
+ difference_type;
+
+ size_t count = iterator_range_size(first, last);
+ if(count == 0){
+ return future<DeviceIterator>();
+ }
+
+ size_t offset = result.get_index();
+
+ event event_ =
+ queue.enqueue_write_buffer_async(result.get_buffer(),
+ offset * sizeof(value_type),
+ count * sizeof(value_type),
+ ::boost::addressof(*first));
+
+ return make_future(result + static_cast<difference_type>(count), event_);
+}
+
+#ifdef CL_VERSION_2_0
+// copy_to_device() specialization for svm_ptr
+template<class HostIterator, class T>
+inline svm_ptr<T> copy_to_device(HostIterator first,
+ HostIterator last,
+ svm_ptr<T> result,
+ command_queue &queue)
+{
+ size_t count = iterator_range_size(first, last);
+ if(count == 0){
+ return result;
+ }
+
+ queue.enqueue_svm_memcpy(
+ result.get(), ::boost::addressof(*first), count * sizeof(T)
+ );
+
+ return result + count;
+}
+
+template<class HostIterator, class T>
+inline future<svm_ptr<T> > copy_to_device_async(HostIterator first,
+ HostIterator last,
+ svm_ptr<T> result,
+ command_queue &queue)
+{
+ size_t count = iterator_range_size(first, last);
+ if(count == 0){
+ return result;
+ }
+
+ event event_ = queue.enqueue_svm_memcpy_async(
+ result.get(), ::boost::addressof(*first), count * sizeof(T)
+ );
+
+ return make_future(result + count, event_);
+}
+#endif // CL_VERSION_2_0
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_TO_DEVICE_HPP
diff --git a/boost/compute/algorithm/detail/copy_to_host.hpp b/boost/compute/algorithm/detail/copy_to_host.hpp
new file mode 100644
index 0000000000..b889e0c871
--- /dev/null
+++ b/boost/compute/algorithm/detail/copy_to_host.hpp
@@ -0,0 +1,137 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_TO_HOST_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_TO_HOST_HPP
+
+#include <iterator>
+
+#include <boost/utility/addressof.hpp>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/async/future.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+#include <boost/compute/memory/svm_ptr.hpp>
+#include <boost/compute/detail/iterator_plus_distance.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class DeviceIterator, class HostIterator>
+inline HostIterator copy_to_host(DeviceIterator first,
+ DeviceIterator last,
+ HostIterator result,
+ command_queue &queue)
+{
+ typedef typename
+ std::iterator_traits<DeviceIterator>::value_type
+ value_type;
+
+ size_t count = iterator_range_size(first, last);
+ if(count == 0){
+ return result;
+ }
+
+ const buffer &buffer = first.get_buffer();
+ size_t offset = first.get_index();
+
+ queue.enqueue_read_buffer(buffer,
+ offset * sizeof(value_type),
+ count * sizeof(value_type),
+ ::boost::addressof(*result));
+
+ return iterator_plus_distance(result, count);
+}
+
+// copy_to_host() specialization for std::vector<bool>
+template<class DeviceIterator>
+inline std::vector<bool>::iterator
+copy_to_host(DeviceIterator first,
+ DeviceIterator last,
+ std::vector<bool>::iterator result,
+ command_queue &queue)
+{
+ std::vector<uint8_t> temp(std::distance(first, last));
+ copy_to_host(first, last, temp.begin(), queue);
+ return std::copy(temp.begin(), temp.end(), result);
+}
+
+template<class DeviceIterator, class HostIterator>
+inline future<HostIterator> copy_to_host_async(DeviceIterator first,
+ DeviceIterator last,
+ HostIterator result,
+ command_queue &queue)
+{
+ typedef typename
+ std::iterator_traits<DeviceIterator>::value_type
+ value_type;
+
+ size_t count = iterator_range_size(first, last);
+ if(count == 0){
+ return future<HostIterator>();
+ }
+
+ const buffer &buffer = first.get_buffer();
+ size_t offset = first.get_index();
+
+ event event_ =
+ queue.enqueue_read_buffer_async(buffer,
+ offset * sizeof(value_type),
+ count * sizeof(value_type),
+ ::boost::addressof(*result));
+
+ return make_future(iterator_plus_distance(result, count), event_);
+}
+
+#ifdef CL_VERSION_2_0
+// copy_to_host() specialization for svm_ptr
+template<class T, class HostIterator>
+inline HostIterator copy_to_host(svm_ptr<T> first,
+ svm_ptr<T> last,
+ HostIterator result,
+ command_queue &queue)
+{
+ size_t count = iterator_range_size(first, last);
+ if(count == 0){
+ return result;
+ }
+
+ queue.enqueue_svm_memcpy(
+ ::boost::addressof(*result), first.get(), count * sizeof(T)
+ );
+
+ return result + count;
+}
+
+template<class T, class HostIterator>
+inline future<HostIterator> copy_to_host_async(svm_ptr<T> first,
+ svm_ptr<T> last,
+ HostIterator result,
+ command_queue &queue)
+{
+ size_t count = iterator_range_size(first, last);
+ if(count == 0){
+ return result;
+ }
+
+ event event_ = queue.enqueue_svm_memcpy_async(
+ ::boost::addressof(*result), first.get(), count * sizeof(T)
+ );
+
+ return make_future(iterator_plus_distance(result, count), event_);
+}
+#endif // CL_VERSION_2_0
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_TO_HOST_HPP
diff --git a/boost/compute/algorithm/detail/count_if_with_ballot.hpp b/boost/compute/algorithm/detail/count_if_with_ballot.hpp
new file mode 100644
index 0000000000..584ef37ab9
--- /dev/null
+++ b/boost/compute/algorithm/detail/count_if_with_ballot.hpp
@@ -0,0 +1,78 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_COUNT_IF_WITH_BALLOT_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_COUNT_IF_WITH_BALLOT_HPP
+
+#include <boost/compute/context.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/algorithm/reduce.hpp>
+#include <boost/compute/functional/detail/nvidia_ballot.hpp>
+#include <boost/compute/functional/detail/nvidia_popcount.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator, class Predicate>
+inline size_t count_if_with_ballot(InputIterator first,
+ InputIterator last,
+ Predicate predicate,
+ command_queue &queue)
+{
+ size_t count = iterator_range_size(first, last);
+ size_t block_size = 32;
+ size_t block_count = count / block_size;
+ if(block_count * block_size != count){
+ block_count++;
+ }
+
+ const ::boost::compute::context &context = queue.get_context();
+
+ ::boost::compute::vector<uint_> counts(block_count, context);
+
+ ::boost::compute::detail::nvidia_popcount<uint_> popc;
+ ::boost::compute::detail::nvidia_ballot<uint_> ballot;
+
+ meta_kernel k("count_if_with_ballot");
+ k <<
+ "const uint gid = get_global_id(0);\n" <<
+
+ "bool value = false;\n" <<
+ "if(gid < count)\n" <<
+ " value = " << predicate(first[k.var<const uint_>("gid")]) << ";\n" <<
+
+ "uint bits = " << ballot(k.var<const uint_>("value")) << ";\n" <<
+
+ "if(get_local_id(0) == 0)\n" <<
+ counts.begin()[k.var<uint_>("get_group_id(0)") ]
+ << " = " << popc(k.var<uint_>("bits")) << ";\n";
+
+ k.add_set_arg<const uint_>("count", count);
+
+ k.exec_1d(queue, 0, block_size * block_count, block_size);
+
+ uint_ result;
+ ::boost::compute::reduce(
+ counts.begin(),
+ counts.end(),
+ &result,
+ queue
+ );
+ return result;
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_COUNT_IF_WITH_BALLOT_HPP
diff --git a/boost/compute/algorithm/detail/count_if_with_reduce.hpp b/boost/compute/algorithm/detail/count_if_with_reduce.hpp
new file mode 100644
index 0000000000..f9449f4a41
--- /dev/null
+++ b/boost/compute/algorithm/detail/count_if_with_reduce.hpp
@@ -0,0 +1,87 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_COUNT_IF_WITH_REDUCE_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_COUNT_IF_WITH_REDUCE_HPP
+
+#include <boost/compute/algorithm/reduce.hpp>
+#include <boost/compute/iterator/transform_iterator.hpp>
+#include <boost/compute/types/fundamental.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class Predicate, class Arg>
+struct invoked_countable_predicate
+{
+ invoked_countable_predicate(Predicate p, Arg a)
+ : predicate(p), arg(a)
+ {
+ }
+
+ Predicate predicate;
+ Arg arg;
+};
+
+template<class Predicate, class Arg>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const invoked_countable_predicate<Predicate, Arg> &expr)
+{
+ return kernel << "(" << expr.predicate(expr.arg) << " ? 1 : 0)";
+}
+
+// the countable_predicate wraps Predicate and converts its result from
+// bool to ulong so that it can be used with reduce()
+template<class Predicate>
+struct countable_predicate
+{
+ typedef ulong_ result_type;
+
+ countable_predicate(Predicate predicate)
+ : m_predicate(predicate)
+ {
+ }
+
+ template<class Arg>
+ invoked_countable_predicate<Predicate, Arg> operator()(const Arg &arg) const
+ {
+ return invoked_countable_predicate<Predicate, Arg>(m_predicate, arg);
+ }
+
+ Predicate m_predicate;
+};
+
+// counts the number of elements matching predicate using reduce()
+template<class InputIterator, class Predicate>
+inline size_t count_if_with_reduce(InputIterator first,
+ InputIterator last,
+ Predicate predicate,
+ command_queue &queue)
+{
+ countable_predicate<Predicate> reduce_predicate(predicate);
+
+ ulong_ count = 0;
+ ::boost::compute::reduce(
+ ::boost::compute::make_transform_iterator(first, reduce_predicate),
+ ::boost::compute::make_transform_iterator(last, reduce_predicate),
+ &count,
+ ::boost::compute::plus<ulong_>(),
+ queue
+ );
+
+ return static_cast<size_t>(count);
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_COUNT_IF_WITH_REDUCE_HPP
diff --git a/boost/compute/algorithm/detail/count_if_with_threads.hpp b/boost/compute/algorithm/detail/count_if_with_threads.hpp
new file mode 100644
index 0000000000..6f282982e0
--- /dev/null
+++ b/boost/compute/algorithm/detail/count_if_with_threads.hpp
@@ -0,0 +1,129 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_COUNT_IF_WITH_THREADS_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_COUNT_IF_WITH_THREADS_HPP
+
+#include <numeric>
+
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/container/vector.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator, class Predicate>
+class count_if_with_threads_kernel : meta_kernel
+{
+public:
+ typedef typename
+ std::iterator_traits<InputIterator>::value_type
+ value_type;
+
+ count_if_with_threads_kernel()
+ : meta_kernel("count_if_with_threads")
+ {
+ }
+
+ void set_args(InputIterator first,
+ InputIterator last,
+ Predicate predicate)
+
+ {
+ typedef typename std::iterator_traits<InputIterator>::value_type T;
+
+ m_size = detail::iterator_range_size(first, last);
+
+ m_size_arg = add_arg<const ulong_>("size");
+ m_counts_arg = add_arg<ulong_ *>(memory_object::global_memory, "counts");
+
+ *this <<
+ // thread parameters
+ "const uint gid = get_global_id(0);\n" <<
+ "const uint block_size = size / get_global_size(0);\n" <<
+ "const uint start = block_size * gid;\n" <<
+ "uint end = 0;\n" <<
+ "if(gid == get_global_size(0) - 1)\n" <<
+ " end = size;\n" <<
+ "else\n" <<
+ " end = block_size * gid + block_size;\n" <<
+
+ // count values
+ "uint count = 0;\n" <<
+ "for(uint i = start; i < end; i++){\n" <<
+ decl<const T>("value") << "="
+ << first[expr<uint_>("i")] << ";\n" <<
+ if_(predicate(var<const T>("value"))) << "{\n" <<
+ "count++;\n" <<
+ "}\n" <<
+ "}\n" <<
+
+ // write count
+ "counts[gid] = count;\n";
+ }
+
+ size_t exec(command_queue &queue)
+ {
+ const device &device = queue.get_device();
+ const context &context = queue.get_context();
+
+ size_t threads = device.compute_units();
+
+ const size_t minimum_block_size = 2048;
+ if(m_size / threads < minimum_block_size){
+ threads = static_cast<size_t>(
+ (std::max)(
+ std::ceil(float(m_size) / minimum_block_size),
+ 1.0f
+ )
+ );
+ }
+
+ // storage for counts
+ ::boost::compute::vector<ulong_> counts(threads, context);
+
+ // exec kernel
+ set_arg(m_size_arg, static_cast<ulong_>(m_size));
+ set_arg(m_counts_arg, counts.get_buffer());
+ exec_1d(queue, 0, threads, 1);
+
+ // copy counts to the host
+ std::vector<ulong_> host_counts(threads);
+ ::boost::compute::copy(counts.begin(), counts.end(), host_counts.begin(), queue);
+
+ // return sum of counts
+ return std::accumulate(host_counts.begin(), host_counts.end(), size_t(0));
+ }
+
+private:
+ size_t m_size;
+ size_t m_size_arg;
+ size_t m_counts_arg;
+};
+
+// counts values that match the predicate using one thread per block. this is
+// optimized for cpu-type devices with a small number of compute units.
+template<class InputIterator, class Predicate>
+inline size_t count_if_with_threads(InputIterator first,
+ InputIterator last,
+ Predicate predicate,
+ command_queue &queue)
+{
+ count_if_with_threads_kernel<InputIterator, Predicate> kernel;
+ kernel.set_args(first, last, predicate);
+ return kernel.exec(queue);
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_COUNT_IF_WITH_THREADS_HPP
diff --git a/boost/compute/algorithm/detail/find_extrema.hpp b/boost/compute/algorithm/detail/find_extrema.hpp
new file mode 100644
index 0000000000..6e756c3904
--- /dev/null
+++ b/boost/compute/algorithm/detail/find_extrema.hpp
@@ -0,0 +1,64 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_FIND_EXTREMA_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_FIND_EXTREMA_HPP
+
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/algorithm/detail/find_extrema_with_reduce.hpp>
+#include <boost/compute/algorithm/detail/find_extrema_with_atomics.hpp>
+#include <boost/compute/algorithm/detail/serial_find_extrema.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator, class Compare>
+inline InputIterator find_extrema(InputIterator first,
+ InputIterator last,
+ Compare compare,
+ const bool find_minimum,
+ command_queue &queue)
+{
+ size_t count = iterator_range_size(first, last);
+
+ // handle trivial cases
+ if(count == 0 || count == 1){
+ return first;
+ }
+
+ const device &device = queue.get_device();
+
+ // use serial method for small inputs
+ // and when device is a CPU
+ if(count < 512 || (device.type() & device::cpu)){
+ return serial_find_extrema(first, last, compare, find_minimum, queue);
+ }
+
+ // find_extrema_with_reduce() is used only if requirements are met
+ if(find_extrema_with_reduce_requirements_met(first, last, queue))
+ {
+ return find_extrema_with_reduce(first, last, compare, find_minimum, queue);
+ }
+
+ // use serial method for OpenCL version 1.0 due to
+ // problems with atomic_cmpxchg()
+ #ifndef CL_VERSION_1_1
+ return serial_find_extrema(first, last, compare, find_minimum, queue);
+ #endif
+
+ return find_extrema_with_atomics(first, last, compare, find_minimum, queue);
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_FIND_EXTREMA_HPP
diff --git a/boost/compute/algorithm/detail/find_extrema_with_atomics.hpp b/boost/compute/algorithm/detail/find_extrema_with_atomics.hpp
new file mode 100644
index 0000000000..406d1becb7
--- /dev/null
+++ b/boost/compute/algorithm/detail/find_extrema_with_atomics.hpp
@@ -0,0 +1,108 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_FIND_EXTREMA_WITH_ATOMICS_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_FIND_EXTREMA_WITH_ATOMICS_HPP
+
+#include <boost/compute/types.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/container/detail/scalar.hpp>
+#include <boost/compute/functional/atomic.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator, class Compare>
+inline InputIterator find_extrema_with_atomics(InputIterator first,
+ InputIterator last,
+ Compare compare,
+ const bool find_minimum,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+ typedef typename std::iterator_traits<InputIterator>::difference_type difference_type;
+
+ const context &context = queue.get_context();
+
+ meta_kernel k("find_extrema");
+ atomic_cmpxchg<uint_> atomic_cmpxchg_uint;
+
+ k <<
+ "const uint gid = get_global_id(0);\n" <<
+ "uint old_index = *index;\n" <<
+
+ k.decl<value_type>("old") <<
+ " = " << first[k.var<uint_>("old_index")] << ";\n" <<
+ k.decl<value_type>("new") <<
+ " = " << first[k.var<uint_>("gid")] << ";\n" <<
+
+ k.decl<bool>("compare_result") << ";\n" <<
+ "#ifdef BOOST_COMPUTE_FIND_MAXIMUM\n" <<
+ "while(" <<
+ "(compare_result = " << compare(k.var<value_type>("old"),
+ k.var<value_type>("new")) << ")" <<
+ " || (!(compare_result" <<
+ " || " << compare(k.var<value_type>("new"),
+ k.var<value_type>("old")) << ") "
+ "&& gid < old_index)){\n" <<
+ "#else\n" <<
+ // while condition explained for minimum case with less (<)
+ // as comparison function:
+ // while(new_value < old_value
+ // OR (new_value == old_value AND new_index < old_index))
+ "while(" <<
+ "(compare_result = " << compare(k.var<value_type>("new"),
+ k.var<value_type>("old")) << ")" <<
+ " || (!(compare_result" <<
+ " || " << compare(k.var<value_type>("old"),
+ k.var<value_type>("new")) << ") "
+ "&& gid < old_index)){\n" <<
+ "#endif\n" <<
+
+ " if(" << atomic_cmpxchg_uint(k.var<uint_ *>("index"),
+ k.var<uint_>("old_index"),
+ k.var<uint_>("gid")) << " == old_index)\n" <<
+ " break;\n" <<
+ " else\n" <<
+ " old_index = *index;\n" <<
+ "old = " << first[k.var<uint_>("old_index")] << ";\n" <<
+ "}\n";
+
+ size_t index_arg_index = k.add_arg<uint_ *>(memory_object::global_memory, "index");
+
+ std::string options;
+ if(!find_minimum){
+ options = "-DBOOST_COMPUTE_FIND_MAXIMUM";
+ }
+ kernel kernel = k.compile(context, options);
+
+ // setup index buffer
+ scalar<uint_> index(context);
+ kernel.set_arg(index_arg_index, index.get_buffer());
+
+ // initialize index
+ index.write(0, queue);
+
+ // run kernel
+ size_t count = iterator_range_size(first, last);
+ queue.enqueue_1d_range_kernel(kernel, 0, count, 0);
+
+ // read index and return iterator
+ return first + static_cast<difference_type>(index.read(queue));
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_FIND_EXTREMA_WITH_ATOMICS_HPP
diff --git a/boost/compute/algorithm/detail/find_extrema_with_reduce.hpp b/boost/compute/algorithm/detail/find_extrema_with_reduce.hpp
new file mode 100644
index 0000000000..1fbb7dee19
--- /dev/null
+++ b/boost/compute/algorithm/detail/find_extrema_with_reduce.hpp
@@ -0,0 +1,443 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2015 Jakub Szuppe <j.szuppe@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_FIND_EXTREMA_WITH_REDUCE_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_FIND_EXTREMA_WITH_REDUCE_HPP
+
+#include <algorithm>
+
+#include <boost/compute/types.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/allocator/pinned_allocator.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/parameter_cache.hpp>
+#include <boost/compute/memory/local_buffer.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/utility/program_cache.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator>
+bool find_extrema_with_reduce_requirements_met(InputIterator first,
+ InputIterator last,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type input_type;
+
+ const device &device = queue.get_device();
+
+ // device must have dedicated local memory storage
+ // otherwise reduction would be highly inefficient
+ if(device.get_info<CL_DEVICE_LOCAL_MEM_TYPE>() != CL_LOCAL)
+ {
+ return false;
+ }
+
+ const size_t max_work_group_size = device.get_info<CL_DEVICE_MAX_WORK_GROUP_SIZE>();
+ // local memory size in bytes (per compute unit)
+ const size_t local_mem_size = device.get_info<CL_DEVICE_LOCAL_MEM_SIZE>();
+
+ std::string cache_key = std::string("__boost_find_extrema_reduce_")
+ + type_name<input_type>();
+ // load parameters
+ boost::shared_ptr<parameter_cache> parameters =
+ detail::parameter_cache::get_global_cache(device);
+
+ // Get preferred work group size
+ size_t work_group_size = parameters->get(cache_key, "wgsize", 256);
+
+ work_group_size = (std::min)(max_work_group_size, work_group_size);
+
+ // local memory size needed to perform parallel reduction
+ size_t required_local_mem_size = 0;
+ // indices size
+ required_local_mem_size += sizeof(uint_) * work_group_size;
+ // values size
+ required_local_mem_size += sizeof(input_type) * work_group_size;
+
+ // at least 4 work groups per compute unit otherwise reduction
+ // would be highly inefficient
+ return ((required_local_mem_size * 4) <= local_mem_size);
+}
+
+/// \internal_
+/// Algorithm finds the first extremum in given range, i.e., with the lowest
+/// index.
+///
+/// If \p use_input_idx is false, it's assumed that input data is ordered by
+/// increasing index and \p input_idx is not used in the algorithm.
+template<class InputIterator, class ResultIterator, class Compare>
+inline void find_extrema_with_reduce(InputIterator input,
+ vector<uint_>::iterator input_idx,
+ size_t count,
+ ResultIterator result,
+ vector<uint_>::iterator result_idx,
+ size_t work_groups_no,
+ size_t work_group_size,
+ Compare compare,
+ const bool find_minimum,
+ const bool use_input_idx,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type input_type;
+
+ const context &context = queue.get_context();
+
+ meta_kernel k("find_extrema_reduce");
+ size_t count_arg = k.add_arg<uint_>("count");
+ size_t block_arg = k.add_arg<input_type *>(memory_object::local_memory, "block");
+ size_t block_idx_arg = k.add_arg<uint_ *>(memory_object::local_memory, "block_idx");
+
+ k <<
+ // Work item global id
+ k.decl<const uint_>("gid") << " = get_global_id(0);\n" <<
+
+ // Index of element that will be read from input buffer
+ k.decl<uint_>("idx") << " = gid;\n" <<
+
+ k.decl<input_type>("acc") << ";\n" <<
+ k.decl<uint_>("acc_idx") << ";\n" <<
+ "if(gid < count) {\n" <<
+ // Real index of currently best element
+ "#ifdef BOOST_COMPUTE_USE_INPUT_IDX\n" <<
+ k.var<uint_>("acc_idx") << " = " << input_idx[k.var<uint_>("idx")] << ";\n" <<
+ "#else\n" <<
+ k.var<uint_>("acc_idx") << " = idx;\n" <<
+ "#endif\n" <<
+
+ // Init accumulator with first[get_global_id(0)]
+ "acc = " << input[k.var<uint_>("idx")] << ";\n" <<
+ "idx += get_global_size(0);\n" <<
+ "}\n" <<
+
+ k.decl<bool>("compare_result") << ";\n" <<
+ k.decl<bool>("equal") << ";\n\n" <<
+ "while( idx < count ){\n" <<
+ // Next element
+ k.decl<input_type>("next") << " = " << input[k.var<uint_>("idx")] << ";\n" <<
+ "#ifdef BOOST_COMPUTE_USE_INPUT_IDX\n" <<
+ k.decl<input_type>("next_idx") << " = " << input_idx[k.var<uint_>("idx")] << ";\n" <<
+ "#endif\n" <<
+
+ // Comparison between currently best element (acc) and next element
+ "#ifdef BOOST_COMPUTE_FIND_MAXIMUM\n" <<
+ "compare_result = " << compare(k.var<input_type>("next"),
+ k.var<input_type>("acc")) << ";\n" <<
+ "# ifdef BOOST_COMPUTE_USE_INPUT_IDX\n" <<
+ "equal = !compare_result && !" <<
+ compare(k.var<input_type>("acc"),
+ k.var<input_type>("next")) << ";\n" <<
+ "# endif\n" <<
+ "#else\n" <<
+ "compare_result = " << compare(k.var<input_type>("acc"),
+ k.var<input_type>("next")) << ";\n" <<
+ "# ifdef BOOST_COMPUTE_USE_INPUT_IDX\n" <<
+ "equal = !compare_result && !" <<
+ compare(k.var<input_type>("next"),
+ k.var<input_type>("acc")) << ";\n" <<
+ "# endif\n" <<
+ "#endif\n" <<
+
+ // save the winner
+ "acc = compare_result ? acc : next;\n" <<
+ "#ifdef BOOST_COMPUTE_USE_INPUT_IDX\n" <<
+ "acc_idx = compare_result ? " <<
+ "acc_idx : " <<
+ "(equal ? min(acc_idx, next_idx) : next_idx);\n" <<
+ "#else\n" <<
+ "acc_idx = compare_result ? acc_idx : idx;\n" <<
+ "#endif\n" <<
+ "idx += get_global_size(0);\n" <<
+ "}\n\n" <<
+
+ // Work item local id
+ k.decl<const uint_>("lid") << " = get_local_id(0);\n" <<
+ "block[lid] = acc;\n" <<
+ "block_idx[lid] = acc_idx;\n" <<
+ "barrier(CLK_LOCAL_MEM_FENCE);\n" <<
+
+ k.decl<uint_>("group_offset") <<
+ " = count - (get_local_size(0) * get_group_id(0));\n\n";
+
+ k <<
+ "#pragma unroll\n"
+ "for(" << k.decl<uint_>("offset") << " = " << uint_(work_group_size) << " / 2; offset > 0; " <<
+ "offset = offset / 2) {\n" <<
+ "if((lid < offset) && ((lid + offset) < group_offset)) { \n" <<
+ k.decl<input_type>("mine") << " = block[lid];\n" <<
+ k.decl<input_type>("other") << " = block[lid+offset];\n" <<
+ "#ifdef BOOST_COMPUTE_FIND_MAXIMUM\n" <<
+ "compare_result = " << compare(k.var<input_type>("other"),
+ k.var<input_type>("mine")) << ";\n" <<
+ "equal = !compare_result && !" <<
+ compare(k.var<input_type>("mine"),
+ k.var<input_type>("other")) << ";\n" <<
+ "#else\n" <<
+ "compare_result = " << compare(k.var<input_type>("mine"),
+ k.var<input_type>("other")) << ";\n" <<
+ "equal = !compare_result && !" <<
+ compare(k.var<input_type>("other"),
+ k.var<input_type>("mine")) << ";\n" <<
+ "#endif\n" <<
+ "block[lid] = compare_result ? mine : other;\n" <<
+ k.decl<uint_>("mine_idx") << " = block_idx[lid];\n" <<
+ k.decl<uint_>("other_idx") << " = block_idx[lid+offset];\n" <<
+ "block_idx[lid] = compare_result ? " <<
+ "mine_idx : " <<
+ "(equal ? min(mine_idx, other_idx) : other_idx);\n" <<
+ "}\n"
+ "barrier(CLK_LOCAL_MEM_FENCE);\n" <<
+ "}\n\n" <<
+
+ // write block result to global output
+ "if(lid == 0){\n" <<
+ result[k.var<uint_>("get_group_id(0)")] << " = block[0];\n" <<
+ result_idx[k.var<uint_>("get_group_id(0)")] << " = block_idx[0];\n" <<
+ "}";
+
+ std::string options;
+ if(!find_minimum){
+ options = "-DBOOST_COMPUTE_FIND_MAXIMUM";
+ }
+ if(use_input_idx){
+ options += " -DBOOST_COMPUTE_USE_INPUT_IDX";
+ }
+
+ kernel kernel = k.compile(context, options);
+
+ kernel.set_arg(count_arg, static_cast<uint_>(count));
+ kernel.set_arg(block_arg, local_buffer<input_type>(work_group_size));
+ kernel.set_arg(block_idx_arg, local_buffer<uint_>(work_group_size));
+
+ queue.enqueue_1d_range_kernel(kernel,
+ 0,
+ work_groups_no * work_group_size,
+ work_group_size);
+}
+
+template<class InputIterator, class ResultIterator, class Compare>
+inline void find_extrema_with_reduce(InputIterator input,
+ size_t count,
+ ResultIterator result,
+ vector<uint_>::iterator result_idx,
+ size_t work_groups_no,
+ size_t work_group_size,
+ Compare compare,
+ const bool find_minimum,
+ command_queue &queue)
+{
+ // dummy will not be used
+ buffer_iterator<uint_> dummy = result_idx;
+ return find_extrema_with_reduce(
+ input, dummy, count, result, result_idx, work_groups_no,
+ work_group_size, compare, find_minimum, false, queue
+ );
+}
+
+template<class InputIterator, class Compare>
+InputIterator find_extrema_with_reduce(InputIterator first,
+ InputIterator last,
+ Compare compare,
+ const bool find_minimum,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<InputIterator>::difference_type difference_type;
+ typedef typename std::iterator_traits<InputIterator>::value_type input_type;
+
+ const context &context = queue.get_context();
+ const device &device = queue.get_device();
+
+ // Getting information about used queue and device
+ const size_t compute_units_no = device.get_info<CL_DEVICE_MAX_COMPUTE_UNITS>();
+ const size_t max_work_group_size = device.get_info<CL_DEVICE_MAX_WORK_GROUP_SIZE>();
+
+ const size_t count = detail::iterator_range_size(first, last);
+
+ std::string cache_key = std::string("__boost_find_extrema_with_reduce_")
+ + type_name<input_type>();
+
+ // load parameters
+ boost::shared_ptr<parameter_cache> parameters =
+ detail::parameter_cache::get_global_cache(device);
+
+ // get preferred work group size and preferred number
+ // of work groups per compute unit
+ size_t work_group_size = parameters->get(cache_key, "wgsize", 256);
+ size_t work_groups_per_cu = parameters->get(cache_key, "wgpcu", 100);
+
+ // calculate work group size and number of work groups
+ work_group_size = (std::min)(max_work_group_size, work_group_size);
+ size_t work_groups_no = compute_units_no * work_groups_per_cu;
+ work_groups_no = (std::min)(
+ work_groups_no,
+ static_cast<size_t>(std::ceil(float(count) / work_group_size))
+ );
+
+ // phase I: finding candidates for extremum
+
+ // device buffors for extremum candidates and their indices
+ // each work-group computes its candidate
+ vector<input_type> candidates(work_groups_no, context);
+ vector<uint_> candidates_idx(work_groups_no, context);
+
+ // finding candidates for first extremum and their indices
+ find_extrema_with_reduce(
+ first, count, candidates.begin(), candidates_idx.begin(),
+ work_groups_no, work_group_size, compare, find_minimum, queue
+ );
+
+ // phase II: finding extremum from among the candidates
+
+ // zero-copy buffers for final result (value and index)
+ vector<input_type, ::boost::compute::pinned_allocator<input_type> >
+ result(1, context);
+ vector<uint_, ::boost::compute::pinned_allocator<uint_> >
+ result_idx(1, context);
+
+ // get extremum from among the candidates
+ find_extrema_with_reduce(
+ candidates.begin(), candidates_idx.begin(), work_groups_no, result.begin(),
+ result_idx.begin(), 1, work_group_size, compare, find_minimum, true, queue
+ );
+
+ // mapping extremum index to host
+ uint_* result_idx_host_ptr =
+ static_cast<uint_*>(
+ queue.enqueue_map_buffer(
+ result_idx.get_buffer(), command_queue::map_read,
+ 0, sizeof(uint_)
+ )
+ );
+
+ return first + static_cast<difference_type>(*result_idx_host_ptr);
+}
+
+template<class InputIterator>
+InputIterator find_extrema_with_reduce(InputIterator first,
+ InputIterator last,
+ ::boost::compute::less<
+ typename std::iterator_traits<
+ InputIterator
+ >::value_type
+ >
+ compare,
+ const bool find_minimum,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<InputIterator>::difference_type difference_type;
+ typedef typename std::iterator_traits<InputIterator>::value_type input_type;
+
+ const context &context = queue.get_context();
+ const device &device = queue.get_device();
+
+ // Getting information about used queue and device
+ const size_t compute_units_no = device.get_info<CL_DEVICE_MAX_COMPUTE_UNITS>();
+ const size_t max_work_group_size = device.get_info<CL_DEVICE_MAX_WORK_GROUP_SIZE>();
+
+ const size_t count = detail::iterator_range_size(first, last);
+
+ std::string cache_key = std::string("__boost_find_extrema_with_reduce_")
+ + type_name<input_type>();
+
+ // load parameters
+ boost::shared_ptr<parameter_cache> parameters =
+ detail::parameter_cache::get_global_cache(device);
+
+ // get preferred work group size and preferred number
+ // of work groups per compute unit
+ size_t work_group_size = parameters->get(cache_key, "wgsize", 256);
+ size_t work_groups_per_cu = parameters->get(cache_key, "wgpcu", 64);
+
+ // calculate work group size and number of work groups
+ work_group_size = (std::min)(max_work_group_size, work_group_size);
+ size_t work_groups_no = compute_units_no * work_groups_per_cu;
+ work_groups_no = (std::min)(
+ work_groups_no,
+ static_cast<size_t>(std::ceil(float(count) / work_group_size))
+ );
+
+ // phase I: finding candidates for extremum
+
+ // device buffors for extremum candidates and their indices
+ // each work-group computes its candidate
+ // zero-copy buffers are used to eliminate copying data back to host
+ vector<input_type, ::boost::compute::pinned_allocator<input_type> >
+ candidates(work_groups_no, context);
+ vector<uint_, ::boost::compute::pinned_allocator <uint_> >
+ candidates_idx(work_groups_no, context);
+
+ // finding candidates for first extremum and their indices
+ find_extrema_with_reduce(
+ first, count, candidates.begin(), candidates_idx.begin(),
+ work_groups_no, work_group_size, compare, find_minimum, queue
+ );
+
+ // phase II: finding extremum from among the candidates
+
+ // mapping candidates and their indices to host
+ input_type* candidates_host_ptr =
+ static_cast<input_type*>(
+ queue.enqueue_map_buffer(
+ candidates.get_buffer(), command_queue::map_read,
+ 0, work_groups_no * sizeof(input_type)
+ )
+ );
+
+ uint_* candidates_idx_host_ptr =
+ static_cast<uint_*>(
+ queue.enqueue_map_buffer(
+ candidates_idx.get_buffer(), command_queue::map_read,
+ 0, work_groups_no * sizeof(uint_)
+ )
+ );
+
+ input_type* i = candidates_host_ptr;
+ uint_* idx = candidates_idx_host_ptr;
+ uint_* extremum_idx = idx;
+ input_type extremum = *candidates_host_ptr;
+ i++; idx++;
+
+ // find extremum (serial) from among the candidates on host
+ if(!find_minimum) {
+ while(idx != (candidates_idx_host_ptr + work_groups_no)) {
+ input_type next = *i;
+ bool compare_result = next > extremum;
+ bool equal = next == extremum;
+ extremum = compare_result ? next : extremum;
+ extremum_idx = compare_result ? idx : extremum_idx;
+ extremum_idx = equal ? ((*extremum_idx < *idx) ? extremum_idx : idx) : extremum_idx;
+ idx++, i++;
+ }
+ }
+ else {
+ while(idx != (candidates_idx_host_ptr + work_groups_no)) {
+ input_type next = *i;
+ bool compare_result = next < extremum;
+ bool equal = next == extremum;
+ extremum = compare_result ? next : extremum;
+ extremum_idx = compare_result ? idx : extremum_idx;
+ extremum_idx = equal ? ((*extremum_idx < *idx) ? extremum_idx : idx) : extremum_idx;
+ idx++, i++;
+ }
+ }
+
+ return first + static_cast<difference_type>(*extremum_idx);
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_FIND_EXTREMA_WITH_REDUCE_HPP
diff --git a/boost/compute/algorithm/detail/find_if_with_atomics.hpp b/boost/compute/algorithm/detail/find_if_with_atomics.hpp
new file mode 100644
index 0000000000..112c34cf00
--- /dev/null
+++ b/boost/compute/algorithm/detail/find_if_with_atomics.hpp
@@ -0,0 +1,212 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_FIND_IF_WITH_ATOMICS_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_FIND_IF_WITH_ATOMICS_HPP
+
+#include <iterator>
+
+#include <boost/compute/types.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/container/detail/scalar.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/parameter_cache.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator, class UnaryPredicate>
+inline InputIterator find_if_with_atomics_one_vpt(InputIterator first,
+ InputIterator last,
+ UnaryPredicate predicate,
+ const size_t count,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+ typedef typename std::iterator_traits<InputIterator>::difference_type difference_type;
+
+ const context &context = queue.get_context();
+
+ detail::meta_kernel k("find_if");
+ size_t index_arg = k.add_arg<int *>(memory_object::global_memory, "index");
+ atomic_min<uint_> atomic_min_uint;
+
+ k << k.decl<const uint_>("i") << " = get_global_id(0);\n"
+ << k.decl<const value_type>("value") << "="
+ << first[k.var<const uint_>("i")] << ";\n"
+ << "if(" << predicate(k.var<const value_type>("value")) << "){\n"
+ << " " << atomic_min_uint(k.var<uint_ *>("index"), k.var<uint_>("i")) << ";\n"
+ << "}\n";
+
+ kernel kernel = k.compile(context);
+
+ scalar<uint_> index(context);
+ kernel.set_arg(index_arg, index.get_buffer());
+
+ // initialize index to the last iterator's index
+ index.write(static_cast<uint_>(count), queue);
+ queue.enqueue_1d_range_kernel(kernel, 0, count, 0);
+
+ // read index and return iterator
+ return first + static_cast<difference_type>(index.read(queue));
+}
+
+template<class InputIterator, class UnaryPredicate>
+inline InputIterator find_if_with_atomics_multiple_vpt(InputIterator first,
+ InputIterator last,
+ UnaryPredicate predicate,
+ const size_t count,
+ const size_t vpt,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+ typedef typename std::iterator_traits<InputIterator>::difference_type difference_type;
+
+ const context &context = queue.get_context();
+ const device &device = queue.get_device();
+
+ detail::meta_kernel k("find_if");
+ size_t index_arg = k.add_arg<uint_ *>(memory_object::global_memory, "index");
+ size_t count_arg = k.add_arg<const uint_>("count");
+ size_t vpt_arg = k.add_arg<const uint_>("vpt");
+ atomic_min<uint_> atomic_min_uint;
+
+ // for GPUs reads from global memory are coalesced
+ if(device.type() & device::gpu) {
+ k <<
+ k.decl<const uint_>("lsize") << " = get_local_size(0);\n" <<
+ k.decl<uint_>("id") << " = get_local_id(0) + get_group_id(0) * lsize * vpt;\n" <<
+ k.decl<const uint_>("end") << " = min(" <<
+ "id + (lsize *" << k.var<uint_>("vpt") << ")," <<
+ "count" <<
+ ");\n" <<
+
+ // checking if the index is already found
+ "__local uint local_index;\n" <<
+ "if(get_local_id(0) == 0){\n" <<
+ " local_index = *index;\n " <<
+ "};\n" <<
+ "barrier(CLK_LOCAL_MEM_FENCE);\n" <<
+ "if(local_index < id){\n" <<
+ " return;\n" <<
+ "}\n" <<
+
+ "while(id < end){\n" <<
+ " " << k.decl<const value_type>("value") << " = " <<
+ first[k.var<const uint_>("id")] << ";\n"
+ " if(" << predicate(k.var<const value_type>("value")) << "){\n" <<
+ " " << atomic_min_uint(k.var<uint_ *>("index"),
+ k.var<uint_>("id")) << ";\n" <<
+ " return;\n"
+ " }\n" <<
+ " id+=lsize;\n" <<
+ "}\n";
+ // for CPUs (and other devices) reads are ordered so the big cache is
+ // efficiently used.
+ } else {
+ k <<
+ k.decl<uint_>("id") << " = get_global_id(0) * " << k.var<uint_>("vpt") << ";\n" <<
+ k.decl<const uint_>("end") << " = min(" <<
+ "id + " << k.var<uint_>("vpt") << "," <<
+ "count" <<
+ ");\n" <<
+ "while(id < end && (*index) > id){\n" <<
+ " " << k.decl<const value_type>("value") << " = " <<
+ first[k.var<const uint_>("id")] << ";\n"
+ " if(" << predicate(k.var<const value_type>("value")) << "){\n" <<
+ " " << atomic_min_uint(k.var<uint_ *>("index"),
+ k.var<uint_>("id")) << ";\n" <<
+ " return;\n" <<
+ " }\n" <<
+ " id++;\n" <<
+ "}\n";
+ }
+
+ kernel kernel = k.compile(context);
+
+ scalar<uint_> index(context);
+ kernel.set_arg(index_arg, index.get_buffer());
+ kernel.set_arg(count_arg, static_cast<uint_>(count));
+ kernel.set_arg(vpt_arg, static_cast<uint_>(vpt));
+
+ // initialize index to the last iterator's index
+ index.write(static_cast<uint_>(count), queue);
+
+ const size_t global_wg_size = static_cast<size_t>(
+ std::ceil(float(count) / vpt)
+ );
+ queue.enqueue_1d_range_kernel(kernel, 0, global_wg_size, 0);
+
+ // read index and return iterator
+ return first + static_cast<difference_type>(index.read(queue));
+}
+
+template<class InputIterator, class UnaryPredicate>
+inline InputIterator find_if_with_atomics(InputIterator first,
+ InputIterator last,
+ UnaryPredicate predicate,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ size_t count = detail::iterator_range_size(first, last);
+ if(count == 0){
+ return last;
+ }
+
+ const device &device = queue.get_device();
+
+ // load cached parameters
+ std::string cache_key = std::string("__boost_find_if_with_atomics_")
+ + type_name<value_type>();
+ boost::shared_ptr<parameter_cache> parameters =
+ detail::parameter_cache::get_global_cache(device);
+
+ // for relatively small inputs on GPUs kernel checking one value per thread
+ // (work-item) is more efficient than its multiple values per thread version
+ if(device.type() & device::gpu){
+ const size_t one_vpt_threshold =
+ parameters->get(cache_key, "one_vpt_threshold", 1048576);
+ if(count <= one_vpt_threshold){
+ return find_if_with_atomics_one_vpt(
+ first, last, predicate, count, queue
+ );
+ }
+ }
+
+ // values per thread
+ size_t vpt;
+ if(device.type() & device::gpu){
+ // get vpt parameter
+ vpt = parameters->get(cache_key, "vpt", 32);
+ } else {
+ // for CPUs work is split equally between compute units
+ const size_t max_compute_units =
+ device.get_info<CL_DEVICE_MAX_COMPUTE_UNITS>();
+ vpt = static_cast<size_t>(
+ std::ceil(float(count) / max_compute_units)
+ );
+ }
+
+ return find_if_with_atomics_multiple_vpt(
+ first, last, predicate, count, vpt, queue
+ );
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_FIND_IF_WITH_ATOMICS_HPP
diff --git a/boost/compute/algorithm/detail/inplace_reduce.hpp b/boost/compute/algorithm/detail/inplace_reduce.hpp
new file mode 100644
index 0000000000..60c61e83fe
--- /dev/null
+++ b/boost/compute/algorithm/detail/inplace_reduce.hpp
@@ -0,0 +1,136 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_INPLACE_REDUCE_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_INPLACE_REDUCE_HPP
+
+#include <iterator>
+
+#include <boost/utility/result_of.hpp>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/memory/local_buffer.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class Iterator, class BinaryFunction>
+inline void inplace_reduce(Iterator first,
+ Iterator last,
+ BinaryFunction function,
+ command_queue &queue)
+{
+ typedef typename
+ std::iterator_traits<Iterator>::value_type
+ value_type;
+
+ size_t input_size = iterator_range_size(first, last);
+ if(input_size < 2){
+ return;
+ }
+
+ const context &context = queue.get_context();
+
+ size_t block_size = 64;
+ size_t values_per_thread = 8;
+ size_t block_count = input_size / (block_size * values_per_thread);
+ if(block_count * block_size * values_per_thread != input_size)
+ block_count++;
+
+ vector<value_type> output(block_count, context);
+
+ meta_kernel k("inplace_reduce");
+ size_t input_arg = k.add_arg<value_type *>(memory_object::global_memory, "input");
+ size_t input_size_arg = k.add_arg<const uint_>("input_size");
+ size_t output_arg = k.add_arg<value_type *>(memory_object::global_memory, "output");
+ size_t scratch_arg = k.add_arg<value_type *>(memory_object::local_memory, "scratch");
+ k <<
+ "const uint gid = get_global_id(0);\n" <<
+ "const uint lid = get_local_id(0);\n" <<
+ "const uint values_per_thread =\n"
+ << uint_(values_per_thread) << ";\n" <<
+
+ // thread reduce
+ "const uint index = gid * values_per_thread;\n" <<
+ "if(index < input_size){\n" <<
+ k.decl<value_type>("sum") << " = input[index];\n" <<
+ "for(uint i = 1;\n" <<
+ "i < values_per_thread && (index + i) < input_size;\n" <<
+ "i++){\n" <<
+ " sum = " <<
+ function(k.var<value_type>("sum"),
+ k.var<value_type>("input[index+i]")) << ";\n" <<
+ "}\n" <<
+ "scratch[lid] = sum;\n" <<
+ "}\n" <<
+
+ // local reduce
+ "for(uint i = 1; i < get_local_size(0); i <<= 1){\n" <<
+ " barrier(CLK_LOCAL_MEM_FENCE);\n" <<
+ " uint mask = (i << 1) - 1;\n" <<
+ " uint next_index = (gid + i) * values_per_thread;\n"
+ " if((lid & mask) == 0 && next_index < input_size){\n" <<
+ " scratch[lid] = " <<
+ function(k.var<value_type>("scratch[lid]"),
+ k.var<value_type>("scratch[lid+i]")) << ";\n" <<
+ " }\n" <<
+ "}\n" <<
+
+ // write output for block
+ "if(lid == 0){\n" <<
+ " output[get_group_id(0)] = scratch[0];\n" <<
+ "}\n"
+ ;
+
+ const buffer *input_buffer = &first.get_buffer();
+ const buffer *output_buffer = &output.get_buffer();
+
+ kernel kernel = k.compile(context);
+
+ while(input_size > 1){
+ kernel.set_arg(input_arg, *input_buffer);
+ kernel.set_arg(input_size_arg, static_cast<uint_>(input_size));
+ kernel.set_arg(output_arg, *output_buffer);
+ kernel.set_arg(scratch_arg, local_buffer<value_type>(block_size));
+
+ queue.enqueue_1d_range_kernel(kernel,
+ 0,
+ block_count * block_size,
+ block_size);
+
+ input_size =
+ static_cast<size_t>(
+ std::ceil(float(input_size) / (block_size * values_per_thread)
+ )
+ );
+
+ block_count = input_size / (block_size * values_per_thread);
+ if(block_count * block_size * values_per_thread != input_size)
+ block_count++;
+
+ std::swap(input_buffer, output_buffer);
+ }
+
+ if(input_buffer != &first.get_buffer()){
+ ::boost::compute::copy(output.begin(),
+ output.begin() + 1,
+ first,
+ queue);
+ }
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_INPLACE_REDUCE_HPP
diff --git a/boost/compute/algorithm/detail/insertion_sort.hpp b/boost/compute/algorithm/detail/insertion_sort.hpp
new file mode 100644
index 0000000000..4b5b95139a
--- /dev/null
+++ b/boost/compute/algorithm/detail/insertion_sort.hpp
@@ -0,0 +1,165 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_INSERTION_SORT_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_INSERTION_SORT_HPP
+
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/program.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/memory/local_buffer.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class Iterator, class Compare>
+inline void serial_insertion_sort(Iterator first,
+ Iterator last,
+ Compare compare,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<Iterator>::value_type T;
+
+ size_t count = iterator_range_size(first, last);
+ if(count < 2){
+ return;
+ }
+
+ meta_kernel k("serial_insertion_sort");
+ size_t local_data_arg = k.add_arg<T *>(memory_object::local_memory, "data");
+ size_t count_arg = k.add_arg<uint_>("n");
+
+ k <<
+ // copy data to local memory
+ "for(uint i = 0; i < n; i++){\n" <<
+ " data[i] = " << first[k.var<uint_>("i")] << ";\n"
+ "}\n"
+
+ // sort data in local memory
+ "for(uint i = 1; i < n; i++){\n" <<
+ " " << k.decl<const T>("value") << " = data[i];\n" <<
+ " uint pos = i;\n" <<
+ " while(pos > 0 && " <<
+ compare(k.var<const T>("value"),
+ k.var<const T>("data[pos-1]")) << "){\n" <<
+ " data[pos] = data[pos-1];\n" <<
+ " pos--;\n" <<
+ " }\n" <<
+ " data[pos] = value;\n" <<
+ "}\n" <<
+
+ // copy sorted data to output
+ "for(uint i = 0; i < n; i++){\n" <<
+ " " << first[k.var<uint_>("i")] << " = data[i];\n"
+ "}\n";
+
+ const context &context = queue.get_context();
+ ::boost::compute::kernel kernel = k.compile(context);
+ kernel.set_arg(local_data_arg, local_buffer<T>(count));
+ kernel.set_arg(count_arg, static_cast<uint_>(count));
+
+ queue.enqueue_task(kernel);
+}
+
+template<class Iterator>
+inline void serial_insertion_sort(Iterator first,
+ Iterator last,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<Iterator>::value_type T;
+
+ ::boost::compute::less<T> less;
+
+ return serial_insertion_sort(first, last, less, queue);
+}
+
+template<class KeyIterator, class ValueIterator, class Compare>
+inline void serial_insertion_sort_by_key(KeyIterator keys_first,
+ KeyIterator keys_last,
+ ValueIterator values_first,
+ Compare compare,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<KeyIterator>::value_type key_type;
+ typedef typename std::iterator_traits<ValueIterator>::value_type value_type;
+
+ size_t count = iterator_range_size(keys_first, keys_last);
+ if(count < 2){
+ return;
+ }
+
+ meta_kernel k("serial_insertion_sort_by_key");
+ size_t local_keys_arg = k.add_arg<key_type *>(memory_object::local_memory, "keys");
+ size_t local_data_arg = k.add_arg<value_type *>(memory_object::local_memory, "data");
+ size_t count_arg = k.add_arg<uint_>("n");
+
+ k <<
+ // copy data to local memory
+ "for(uint i = 0; i < n; i++){\n" <<
+ " keys[i] = " << keys_first[k.var<uint_>("i")] << ";\n"
+ " data[i] = " << values_first[k.var<uint_>("i")] << ";\n"
+ "}\n"
+
+ // sort data in local memory
+ "for(uint i = 1; i < n; i++){\n" <<
+ " " << k.decl<const key_type>("key") << " = keys[i];\n" <<
+ " " << k.decl<const value_type>("value") << " = data[i];\n" <<
+ " uint pos = i;\n" <<
+ " while(pos > 0 && " <<
+ compare(k.var<const key_type>("key"),
+ k.var<const key_type>("keys[pos-1]")) << "){\n" <<
+ " keys[pos] = keys[pos-1];\n" <<
+ " data[pos] = data[pos-1];\n" <<
+ " pos--;\n" <<
+ " }\n" <<
+ " keys[pos] = key;\n" <<
+ " data[pos] = value;\n" <<
+ "}\n" <<
+
+ // copy sorted data to output
+ "for(uint i = 0; i < n; i++){\n" <<
+ " " << keys_first[k.var<uint_>("i")] << " = keys[i];\n"
+ " " << values_first[k.var<uint_>("i")] << " = data[i];\n"
+ "}\n";
+
+ const context &context = queue.get_context();
+ ::boost::compute::kernel kernel = k.compile(context);
+ kernel.set_arg(local_keys_arg, static_cast<uint_>(count * sizeof(key_type)), 0);
+ kernel.set_arg(local_data_arg, static_cast<uint_>(count * sizeof(value_type)), 0);
+ kernel.set_arg(count_arg, static_cast<uint_>(count));
+
+ queue.enqueue_task(kernel);
+}
+
+template<class KeyIterator, class ValueIterator>
+inline void serial_insertion_sort_by_key(KeyIterator keys_first,
+ KeyIterator keys_last,
+ ValueIterator values_first,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<KeyIterator>::value_type key_type;
+
+ serial_insertion_sort_by_key(
+ keys_first,
+ keys_last,
+ values_first,
+ boost::compute::less<key_type>(),
+ queue
+ );
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_INSERTION_SORT_HPP
diff --git a/boost/compute/algorithm/detail/merge_path.hpp b/boost/compute/algorithm/detail/merge_path.hpp
new file mode 100644
index 0000000000..bc2c8fa88c
--- /dev/null
+++ b/boost/compute/algorithm/detail/merge_path.hpp
@@ -0,0 +1,116 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_MERGE_PATH_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_MERGE_PATH_HPP
+
+#include <iterator>
+
+#include <boost/compute/algorithm/find_if.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/system.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+///
+/// \brief Merge Path kernel class
+///
+/// Subclass of meta_kernel to break two sets into tiles according
+/// to their merge path
+///
+class merge_path_kernel : public meta_kernel
+{
+public:
+ unsigned int tile_size;
+
+ merge_path_kernel() : meta_kernel("merge_path")
+ {
+ tile_size = 4;
+ }
+
+ template<class InputIterator1, class InputIterator2,
+ class OutputIterator1, class OutputIterator2,
+ class Compare>
+ void set_range(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator1 result_a,
+ OutputIterator2 result_b,
+ Compare comp)
+ {
+ m_a_count = iterator_range_size(first1, last1);
+ m_a_count_arg = add_arg<uint_>("a_count");
+
+ m_b_count = iterator_range_size(first2, last2);
+ m_b_count_arg = add_arg<uint_>("b_count");
+
+ *this <<
+ "uint i = get_global_id(0);\n" <<
+ "uint target = (i+1)*" << tile_size << ";\n" <<
+ "uint start = max(convert_int(0),convert_int(target)-convert_int(b_count));\n" <<
+ "uint end = min(target,a_count);\n" <<
+ "uint a_index, b_index;\n" <<
+ "while(start<end)\n" <<
+ "{\n" <<
+ " a_index = (start + end)/2;\n" <<
+ " b_index = target - a_index - 1;\n" <<
+ " if(!(" << comp(first2[expr<uint_>("b_index")],
+ first1[expr<uint_>("a_index")]) << "))\n" <<
+ " start = a_index + 1;\n" <<
+ " else end = a_index;\n" <<
+ "}\n" <<
+ result_a[expr<uint_>("i")] << " = start;\n" <<
+ result_b[expr<uint_>("i")] << " = target - start;\n";
+ }
+
+ template<class InputIterator1, class InputIterator2,
+ class OutputIterator1, class OutputIterator2>
+ void set_range(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator1 result_a,
+ OutputIterator2 result_b)
+ {
+ typedef typename std::iterator_traits<InputIterator1>::value_type value_type;
+ ::boost::compute::less<value_type> less_than;
+ set_range(first1, last1, first2, last2, result_a, result_b, less_than);
+ }
+
+ event exec(command_queue &queue)
+ {
+ if((m_a_count + m_b_count)/tile_size == 0) {
+ return event();
+ }
+
+ set_arg(m_a_count_arg, uint_(m_a_count));
+ set_arg(m_b_count_arg, uint_(m_b_count));
+
+ return exec_1d(queue, 0, (m_a_count + m_b_count)/tile_size);
+ }
+
+private:
+ size_t m_a_count;
+ size_t m_a_count_arg;
+ size_t m_b_count;
+ size_t m_b_count_arg;
+};
+
+} //end detail namespace
+} //end compute namespace
+} //end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_MERGE_PATH_HPP
diff --git a/boost/compute/algorithm/detail/merge_sort_on_cpu.hpp b/boost/compute/algorithm/detail/merge_sort_on_cpu.hpp
new file mode 100644
index 0000000000..f4b53f10ae
--- /dev/null
+++ b/boost/compute/algorithm/detail/merge_sort_on_cpu.hpp
@@ -0,0 +1,366 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2015 Jakub Szuppe <j.szuppe@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_MERGE_SORT_ON_CPU_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_MERGE_SORT_ON_CPU_HPP
+
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/program.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/detail/merge_with_merge_path.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class KeyIterator, class ValueIterator, class Compare>
+inline void merge_blocks(KeyIterator keys_first,
+ ValueIterator values_first,
+ KeyIterator keys_result,
+ ValueIterator values_result,
+ Compare compare,
+ size_t count,
+ const size_t block_size,
+ const bool sort_by_key,
+ command_queue &queue)
+{
+ (void) values_result;
+ (void) values_first;
+
+ meta_kernel k("merge_sort_on_cpu_merge_blocks");
+ size_t count_arg = k.add_arg<const uint_>("count");
+ size_t block_size_arg = k.add_arg<uint_>("block_size");
+
+ k <<
+ k.decl<uint_>("b1_start") << " = get_global_id(0) * block_size * 2;\n" <<
+ k.decl<uint_>("b1_end") << " = min(count, b1_start + block_size);\n" <<
+ k.decl<uint_>("b2_start") << " = min(count, b1_start + block_size);\n" <<
+ k.decl<uint_>("b2_end") << " = min(count, b2_start + block_size);\n" <<
+ k.decl<uint_>("result_idx") << " = b1_start;\n" <<
+
+ // merging block 1 and block 2 (stable)
+ "while(b1_start < b1_end && b2_start < b2_end){\n" <<
+ " if( " << compare(keys_first[k.var<uint_>("b2_start")],
+ keys_first[k.var<uint_>("b1_start")]) << "){\n" <<
+ " " << keys_result[k.var<uint_>("result_idx")] << " = " <<
+ keys_first[k.var<uint_>("b2_start")] << ";\n";
+ if(sort_by_key){
+ k <<
+ " " << values_result[k.var<uint_>("result_idx")] << " = " <<
+ values_first[k.var<uint_>("b2_start")] << ";\n";
+ }
+ k <<
+ " b2_start++;\n" <<
+ " }\n" <<
+ " else {\n" <<
+ " " << keys_result[k.var<uint_>("result_idx")] << " = " <<
+ keys_first[k.var<uint_>("b1_start")] << ";\n";
+ if(sort_by_key){
+ k <<
+ " " << values_result[k.var<uint_>("result_idx")] << " = " <<
+ values_first[k.var<uint_>("b1_start")] << ";\n";
+ }
+ k <<
+ " b1_start++;\n" <<
+ " }\n" <<
+ " result_idx++;\n" <<
+ "}\n" <<
+ "while(b1_start < b1_end){\n" <<
+ " " << keys_result[k.var<uint_>("result_idx")] << " = " <<
+ keys_first[k.var<uint_>("b1_start")] << ";\n";
+ if(sort_by_key){
+ k <<
+ " " << values_result[k.var<uint_>("result_idx")] << " = " <<
+ values_first[k.var<uint_>("b1_start")] << ";\n";
+ }
+ k <<
+ " b1_start++;\n" <<
+ " result_idx++;\n" <<
+ "}\n" <<
+ "while(b2_start < b2_end){\n" <<
+ " " << keys_result[k.var<uint_>("result_idx")] << " = " <<
+ keys_first[k.var<uint_>("b2_start")] << ";\n";
+ if(sort_by_key){
+ k <<
+ " " << values_result[k.var<uint_>("result_idx")] << " = " <<
+ values_first[k.var<uint_>("b2_start")] << ";\n";
+ }
+ k <<
+ " b2_start++;\n" <<
+ " result_idx++;\n" <<
+ "}\n";
+
+ const context &context = queue.get_context();
+ ::boost::compute::kernel kernel = k.compile(context);
+ kernel.set_arg(count_arg, static_cast<const uint_>(count));
+ kernel.set_arg(block_size_arg, static_cast<uint_>(block_size));
+
+ const size_t global_size = static_cast<size_t>(
+ std::ceil(float(count) / (2 * block_size))
+ );
+ queue.enqueue_1d_range_kernel(kernel, 0, global_size, 0);
+}
+
+template<class Iterator, class Compare>
+inline void merge_blocks(Iterator first,
+ Iterator result,
+ Compare compare,
+ size_t count,
+ const size_t block_size,
+ const bool sort_by_key,
+ command_queue &queue)
+{
+ // dummy iterator as it's not sort by key
+ Iterator dummy;
+ merge_blocks(first, dummy, result, dummy, compare, count, block_size, false, queue);
+}
+
+template<class Iterator, class Compare>
+inline void dispatch_merge_blocks(Iterator first,
+ Iterator result,
+ Compare compare,
+ size_t count,
+ const size_t block_size,
+ const size_t input_size_threshold,
+ const size_t blocks_no_threshold,
+ command_queue &queue)
+{
+ const size_t blocks_no = static_cast<size_t>(
+ std::ceil(float(count) / block_size)
+ );
+ // merge with merge path should used only for the large arrays and at the
+ // end of merging part when there are only a few big blocks left to be merged
+ if(blocks_no <= blocks_no_threshold && count >= input_size_threshold){
+ Iterator last = first + count;
+ for(size_t i = 0; i < count; i+= 2*block_size)
+ {
+ Iterator first1 = (std::min)(first + i, last);
+ Iterator last1 = (std::min)(first1 + block_size, last);
+ Iterator first2 = last1;
+ Iterator last2 = (std::min)(first2 + block_size, last);
+ Iterator block_result = (std::min)(result + i, result + count);
+ merge_with_merge_path(first1, last1, first2, last2,
+ block_result, compare, queue);
+ }
+ }
+ else {
+ merge_blocks(first, result, compare, count, block_size, false, queue);
+ }
+}
+
+template<class KeyIterator, class ValueIterator, class Compare>
+inline void block_insertion_sort(KeyIterator keys_first,
+ ValueIterator values_first,
+ Compare compare,
+ const size_t count,
+ const size_t block_size,
+ const bool sort_by_key,
+ command_queue &queue)
+{
+ (void) values_first;
+
+ typedef typename std::iterator_traits<KeyIterator>::value_type K;
+ typedef typename std::iterator_traits<ValueIterator>::value_type T;
+
+ meta_kernel k("merge_sort_on_cpu_block_insertion_sort");
+ size_t count_arg = k.add_arg<uint_>("count");
+ size_t block_size_arg = k.add_arg<uint_>("block_size");
+
+ k <<
+ k.decl<uint_>("start") << " = get_global_id(0) * block_size;\n" <<
+ k.decl<uint_>("end") << " = min(count, start + block_size);\n" <<
+
+ // block insertion sort (stable)
+ "for(uint i = start+1; i < end; i++){\n" <<
+ " " << k.decl<const K>("key") << " = " <<
+ keys_first[k.var<uint_>("i")] << ";\n";
+ if(sort_by_key){
+ k <<
+ " " << k.decl<const T>("value") << " = " <<
+ values_first[k.var<uint_>("i")] << ";\n";
+ }
+ k <<
+ " uint pos = i;\n" <<
+ " while(pos > start && " <<
+ compare(k.var<const K>("key"),
+ keys_first[k.var<uint_>("pos-1")]) << "){\n" <<
+ " " << keys_first[k.var<uint_>("pos")] << " = " <<
+ keys_first[k.var<uint_>("pos-1")] << ";\n";
+ if(sort_by_key){
+ k <<
+ " " << values_first[k.var<uint_>("pos")] << " = " <<
+ values_first[k.var<uint_>("pos-1")] << ";\n";
+ }
+ k <<
+ " pos--;\n" <<
+ " }\n" <<
+ " " << keys_first[k.var<uint_>("pos")] << " = key;\n";
+ if(sort_by_key) {
+ k <<
+ " " << values_first[k.var<uint_>("pos")] << " = value;\n";
+ }
+ k <<
+ "}\n"; // block insertion sort
+
+ const context &context = queue.get_context();
+ ::boost::compute::kernel kernel = k.compile(context);
+ kernel.set_arg(count_arg, static_cast<uint_>(count));
+ kernel.set_arg(block_size_arg, static_cast<uint_>(block_size));
+
+ const size_t global_size = static_cast<size_t>(std::ceil(float(count) / block_size));
+ queue.enqueue_1d_range_kernel(kernel, 0, global_size, 0);
+}
+
+template<class Iterator, class Compare>
+inline void block_insertion_sort(Iterator first,
+ Compare compare,
+ const size_t count,
+ const size_t block_size,
+ command_queue &queue)
+{
+ // dummy iterator as it's not sort by key
+ Iterator dummy;
+ block_insertion_sort(first, dummy, compare, count, block_size, false, queue);
+}
+
+// This sort is stable.
+template<class Iterator, class Compare>
+inline void merge_sort_on_cpu(Iterator first,
+ Iterator last,
+ Compare compare,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<Iterator>::value_type value_type;
+
+ size_t count = iterator_range_size(first, last);
+ if(count < 2){
+ return;
+ }
+ // for small input size only insertion sort is performed
+ else if(count <= 512){
+ block_insertion_sort(first, compare, count, count, queue);
+ return;
+ }
+
+ const context &context = queue.get_context();
+ const device &device = queue.get_device();
+
+ // loading parameters
+ std::string cache_key =
+ std::string("__boost_merge_sort_on_cpu_") + type_name<value_type>();
+ boost::shared_ptr<parameter_cache> parameters =
+ detail::parameter_cache::get_global_cache(device);
+
+ // When there is merge_with_path_blocks_no_threshold or less blocks left to
+ // merge AND input size is merge_with_merge_path_input_size_threshold or more
+ // merge_with_merge_path() algorithm is used to merge sorted blocks;
+ // otherwise merge_blocks() is used.
+ const size_t merge_with_path_blocks_no_threshold =
+ parameters->get(cache_key, "merge_with_merge_path_blocks_no_threshold", 8);
+ const size_t merge_with_path_input_size_threshold =
+ parameters->get(cache_key, "merge_with_merge_path_input_size_threshold", 2097152);
+
+ const size_t block_size =
+ parameters->get(cache_key, "insertion_sort_block_size", 64);
+ block_insertion_sort(first, compare, count, block_size, queue);
+
+ // temporary buffer for merge result
+ vector<value_type> temp(count, context);
+ bool result_in_temporary_buffer = false;
+
+ for(size_t i = block_size; i < count; i *= 2){
+ result_in_temporary_buffer = !result_in_temporary_buffer;
+ if(result_in_temporary_buffer) {
+ dispatch_merge_blocks(first, temp.begin(), compare, count, i,
+ merge_with_path_input_size_threshold,
+ merge_with_path_blocks_no_threshold,
+ queue);
+ } else {
+ dispatch_merge_blocks(temp.begin(), first, compare, count, i,
+ merge_with_path_input_size_threshold,
+ merge_with_path_blocks_no_threshold,
+ queue);
+ }
+ }
+
+ if(result_in_temporary_buffer) {
+ copy(temp.begin(), temp.end(), first, queue);
+ }
+}
+
+// This sort is stable.
+template<class KeyIterator, class ValueIterator, class Compare>
+inline void merge_sort_by_key_on_cpu(KeyIterator keys_first,
+ KeyIterator keys_last,
+ ValueIterator values_first,
+ Compare compare,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<KeyIterator>::value_type key_type;
+ typedef typename std::iterator_traits<ValueIterator>::value_type value_type;
+
+ size_t count = iterator_range_size(keys_first, keys_last);
+ if(count < 2){
+ return;
+ }
+ // for small input size only insertion sort is performed
+ else if(count <= 512){
+ block_insertion_sort(keys_first, values_first, compare,
+ count, count, true, queue);
+ return;
+ }
+
+ const context &context = queue.get_context();
+ const device &device = queue.get_device();
+
+ // loading parameters
+ std::string cache_key =
+ std::string("__boost_merge_sort_by_key_on_cpu_") + type_name<value_type>()
+ + "_with_" + type_name<key_type>();
+ boost::shared_ptr<parameter_cache> parameters =
+ detail::parameter_cache::get_global_cache(device);
+
+ const size_t block_size =
+ parameters->get(cache_key, "insertion_sort_by_key_block_size", 64);
+ block_insertion_sort(keys_first, values_first, compare,
+ count, block_size, true, queue);
+
+ // temporary buffer for merge results
+ vector<value_type> values_temp(count, context);
+ vector<key_type> keys_temp(count, context);
+ bool result_in_temporary_buffer = false;
+
+ for(size_t i = block_size; i < count; i *= 2){
+ result_in_temporary_buffer = !result_in_temporary_buffer;
+ if(result_in_temporary_buffer) {
+ merge_blocks(keys_first, values_first,
+ keys_temp.begin(), values_temp.begin(),
+ compare, count, i, true, queue);
+ } else {
+ merge_blocks(keys_temp.begin(), values_temp.begin(),
+ keys_first, values_first,
+ compare, count, i, true, queue);
+ }
+ }
+
+ if(result_in_temporary_buffer) {
+ copy(keys_temp.begin(), keys_temp.end(), keys_first, queue);
+ copy(values_temp.begin(), values_temp.end(), values_first, queue);
+ }
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_MERGE_SORT_ON_CPU_HPP
diff --git a/boost/compute/algorithm/detail/merge_with_merge_path.hpp b/boost/compute/algorithm/detail/merge_with_merge_path.hpp
new file mode 100644
index 0000000000..c3cc5e8e9c
--- /dev/null
+++ b/boost/compute/algorithm/detail/merge_with_merge_path.hpp
@@ -0,0 +1,203 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_MERGE_WIH_MERGE_PATH_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_MERGE_WIH_MERGE_PATH_HPP
+
+#include <iterator>
+
+#include <boost/compute/algorithm/detail/merge_path.hpp>
+#include <boost/compute/algorithm/fill_n.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/system.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+///
+/// \brief Serial merge kernel class
+///
+/// Subclass of meta_kernel to perform serial merge after tiling
+///
+class serial_merge_kernel : meta_kernel
+{
+public:
+ unsigned int tile_size;
+
+ serial_merge_kernel() : meta_kernel("merge")
+ {
+ tile_size = 4;
+ }
+
+ template<class InputIterator1, class InputIterator2,
+ class InputIterator3, class InputIterator4,
+ class OutputIterator, class Compare>
+ void set_range(InputIterator1 first1,
+ InputIterator2 first2,
+ InputIterator3 tile_first1,
+ InputIterator3 tile_last1,
+ InputIterator4 tile_first2,
+ OutputIterator result,
+ Compare comp)
+ {
+ m_count = iterator_range_size(tile_first1, tile_last1) - 1;
+
+ *this <<
+ "uint i = get_global_id(0);\n" <<
+ "uint start1 = " << tile_first1[expr<uint_>("i")] << ";\n" <<
+ "uint end1 = " << tile_first1[expr<uint_>("i+1")] << ";\n" <<
+ "uint start2 = " << tile_first2[expr<uint_>("i")] << ";\n" <<
+ "uint end2 = " << tile_first2[expr<uint_>("i+1")] << ";\n" <<
+ "uint index = i*" << tile_size << ";\n" <<
+ "while(start1<end1 && start2<end2)\n" <<
+ "{\n" <<
+ " if(!(" << comp(first2[expr<uint_>("start2")],
+ first1[expr<uint_>("start1")]) << "))\n" <<
+ " {\n" <<
+ result[expr<uint_>("index")] <<
+ " = " << first1[expr<uint_>("start1")] << ";\n" <<
+ " index++;\n" <<
+ " start1++;\n" <<
+ " }\n" <<
+ " else\n" <<
+ " {\n" <<
+ result[expr<uint_>("index")] <<
+ " = " << first2[expr<uint_>("start2")] << ";\n" <<
+ " index++;\n" <<
+ " start2++;\n" <<
+ " }\n" <<
+ "}\n" <<
+ "while(start1<end1)\n" <<
+ "{\n" <<
+ result[expr<uint_>("index")] <<
+ " = " << first1[expr<uint_>("start1")] << ";\n" <<
+ " index++;\n" <<
+ " start1++;\n" <<
+ "}\n" <<
+ "while(start2<end2)\n" <<
+ "{\n" <<
+ result[expr<uint_>("index")] <<
+ " = " << first2[expr<uint_>("start2")] << ";\n" <<
+ " index++;\n" <<
+ " start2++;\n" <<
+ "}\n";
+ }
+
+ template<class InputIterator1, class InputIterator2,
+ class InputIterator3, class InputIterator4,
+ class OutputIterator>
+ void set_range(InputIterator1 first1,
+ InputIterator2 first2,
+ InputIterator3 tile_first1,
+ InputIterator3 tile_last1,
+ InputIterator4 tile_first2,
+ OutputIterator result)
+ {
+ typedef typename std::iterator_traits<InputIterator1>::value_type value_type;
+ ::boost::compute::less<value_type> less_than;
+ set_range(first1, first2, tile_first1, tile_last1, tile_first2, result, less_than);
+ }
+
+ event exec(command_queue &queue)
+ {
+ if(m_count == 0) {
+ return event();
+ }
+
+ return exec_1d(queue, 0, m_count);
+ }
+
+private:
+ size_t m_count;
+};
+
+///
+/// \brief Merge algorithm with merge path
+///
+/// Merges the sorted values in the range [\p first1, \p last1) with
+/// the sorted values in the range [\p first2, last2) and stores the
+/// result in the range beginning at \p result
+///
+/// \param first1 Iterator pointing to start of first set
+/// \param last1 Iterator pointing to end of first set
+/// \param first2 Iterator pointing to start of second set
+/// \param last2 Iterator pointing to end of second set
+/// \param result Iterator pointing to start of range in which the result
+/// will be stored
+/// \param comp Comparator which performs less than function
+/// \param queue Queue on which to execute
+///
+template<class InputIterator1, class InputIterator2, class OutputIterator, class Compare>
+inline OutputIterator
+merge_with_merge_path(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator result,
+ Compare comp,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename
+ std::iterator_traits<OutputIterator>::difference_type result_difference_type;
+
+ size_t tile_size = 1024;
+
+ size_t count1 = iterator_range_size(first1, last1);
+ size_t count2 = iterator_range_size(first2, last2);
+
+ vector<uint_> tile_a((count1+count2+tile_size-1)/tile_size+1, queue.get_context());
+ vector<uint_> tile_b((count1+count2+tile_size-1)/tile_size+1, queue.get_context());
+
+ // Tile the sets
+ merge_path_kernel tiling_kernel;
+ tiling_kernel.tile_size = static_cast<unsigned int>(tile_size);
+ tiling_kernel.set_range(first1, last1, first2, last2,
+ tile_a.begin()+1, tile_b.begin()+1, comp);
+ fill_n(tile_a.begin(), 1, uint_(0), queue);
+ fill_n(tile_b.begin(), 1, uint_(0), queue);
+ tiling_kernel.exec(queue);
+
+ fill_n(tile_a.end()-1, 1, static_cast<uint_>(count1), queue);
+ fill_n(tile_b.end()-1, 1, static_cast<uint_>(count2), queue);
+
+ // Merge
+ serial_merge_kernel merge_kernel;
+ merge_kernel.tile_size = static_cast<unsigned int>(tile_size);
+ merge_kernel.set_range(first1, first2, tile_a.begin(), tile_a.end(),
+ tile_b.begin(), result, comp);
+
+ merge_kernel.exec(queue);
+
+ return result + static_cast<result_difference_type>(count1 + count2);
+}
+
+/// \overload
+template<class InputIterator1, class InputIterator2, class OutputIterator>
+inline OutputIterator
+merge_with_merge_path(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator1>::value_type value_type;
+ ::boost::compute::less<value_type> less_than;
+ return merge_with_merge_path(first1, last1, first2, last2, result, less_than, queue);
+}
+
+} //end detail namespace
+} //end compute namespace
+} //end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_MERGE_WIH_MERGE_PATH_HPP
diff --git a/boost/compute/algorithm/detail/radix_sort.hpp b/boost/compute/algorithm/detail/radix_sort.hpp
new file mode 100644
index 0000000000..c2ba4ed17c
--- /dev/null
+++ b/boost/compute/algorithm/detail/radix_sort.hpp
@@ -0,0 +1,415 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_RADIX_SORT_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_RADIX_SORT_HPP
+
+#include <iterator>
+
+#include <boost/assert.hpp>
+#include <boost/type_traits/is_signed.hpp>
+#include <boost/type_traits/is_floating_point.hpp>
+
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/program.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/exclusive_scan.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/parameter_cache.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/type_traits/is_fundamental.hpp>
+#include <boost/compute/type_traits/is_vector_type.hpp>
+#include <boost/compute/utility/program_cache.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+// meta-function returning true if type T is radix-sortable
+template<class T>
+struct is_radix_sortable :
+ boost::mpl::and_<
+ typename ::boost::compute::is_fundamental<T>::type,
+ typename boost::mpl::not_<typename is_vector_type<T>::type>::type
+ >
+{
+};
+
+template<size_t N>
+struct radix_sort_value_type
+{
+};
+
+template<>
+struct radix_sort_value_type<1>
+{
+ typedef uchar_ type;
+};
+
+template<>
+struct radix_sort_value_type<2>
+{
+ typedef ushort_ type;
+};
+
+template<>
+struct radix_sort_value_type<4>
+{
+ typedef uint_ type;
+};
+
+template<>
+struct radix_sort_value_type<8>
+{
+ typedef ulong_ type;
+};
+
+template<typename T>
+inline const char* enable_double()
+{
+ return " -DT2_double=0";
+}
+
+template<>
+inline const char* enable_double<double>()
+{
+ return " -DT2_double=1";
+}
+
+const char radix_sort_source[] =
+"#if T2_double\n"
+"#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"
+"#endif\n"
+"#define K2_BITS (1 << K_BITS)\n"
+"#define RADIX_MASK ((((T)(1)) << K_BITS) - 1)\n"
+"#define SIGN_BIT ((sizeof(T) * CHAR_BIT) - 1)\n"
+
+"inline uint radix(const T x, const uint low_bit)\n"
+"{\n"
+"#if defined(IS_FLOATING_POINT)\n"
+" const T mask = -(x >> SIGN_BIT) | (((T)(1)) << SIGN_BIT);\n"
+" return ((x ^ mask) >> low_bit) & RADIX_MASK;\n"
+"#elif defined(IS_SIGNED)\n"
+" return ((x ^ (((T)(1)) << SIGN_BIT)) >> low_bit) & RADIX_MASK;\n"
+"#else\n"
+" return (x >> low_bit) & RADIX_MASK;\n"
+"#endif\n"
+"}\n"
+
+"__kernel void count(__global const T *input,\n"
+" const uint input_offset,\n"
+" const uint input_size,\n"
+" __global uint *global_counts,\n"
+" __global uint *global_offsets,\n"
+" __local uint *local_counts,\n"
+" const uint low_bit)\n"
+"{\n"
+ // work-item parameters
+" const uint gid = get_global_id(0);\n"
+" const uint lid = get_local_id(0);\n"
+
+ // zero local counts
+" if(lid < K2_BITS){\n"
+" local_counts[lid] = 0;\n"
+" }\n"
+" barrier(CLK_LOCAL_MEM_FENCE);\n"
+
+ // reduce local counts
+" if(gid < input_size){\n"
+" T value = input[input_offset+gid];\n"
+" uint bucket = radix(value, low_bit);\n"
+" atomic_inc(local_counts + bucket);\n"
+" }\n"
+" barrier(CLK_LOCAL_MEM_FENCE);\n"
+
+ // write block-relative offsets
+" if(lid < K2_BITS){\n"
+" global_counts[K2_BITS*get_group_id(0) + lid] = local_counts[lid];\n"
+
+ // write global offsets
+" if(get_group_id(0) == (get_num_groups(0) - 1)){\n"
+" global_offsets[lid] = local_counts[lid];\n"
+" }\n"
+" }\n"
+"}\n"
+
+"__kernel void scan(__global const uint *block_offsets,\n"
+" __global uint *global_offsets,\n"
+" const uint block_count)\n"
+"{\n"
+" __global const uint *last_block_offsets =\n"
+" block_offsets + K2_BITS * (block_count - 1);\n"
+
+ // calculate and scan global_offsets
+" uint sum = 0;\n"
+" for(uint i = 0; i < K2_BITS; i++){\n"
+" uint x = global_offsets[i] + last_block_offsets[i];\n"
+" global_offsets[i] = sum;\n"
+" sum += x;\n"
+" }\n"
+"}\n"
+
+"__kernel void scatter(__global const T *input,\n"
+" const uint input_offset,\n"
+" const uint input_size,\n"
+" const uint low_bit,\n"
+" __global const uint *counts,\n"
+" __global const uint *global_offsets,\n"
+"#ifndef SORT_BY_KEY\n"
+" __global T *output,\n"
+" const uint output_offset)\n"
+"#else\n"
+" __global T *keys_output,\n"
+" const uint keys_output_offset,\n"
+" __global T2 *values_input,\n"
+" const uint values_input_offset,\n"
+" __global T2 *values_output,\n"
+" const uint values_output_offset)\n"
+"#endif\n"
+"{\n"
+ // work-item parameters
+" const uint gid = get_global_id(0);\n"
+" const uint lid = get_local_id(0);\n"
+
+ // copy input to local memory
+" T value;\n"
+" uint bucket;\n"
+" __local uint local_input[BLOCK_SIZE];\n"
+" if(gid < input_size){\n"
+" value = input[input_offset+gid];\n"
+" bucket = radix(value, low_bit);\n"
+" local_input[lid] = bucket;\n"
+" }\n"
+
+ // copy block counts to local memory
+" __local uint local_counts[(1 << K_BITS)];\n"
+" if(lid < K2_BITS){\n"
+" local_counts[lid] = counts[get_group_id(0) * K2_BITS + lid];\n"
+" }\n"
+
+ // wait until local memory is ready
+" barrier(CLK_LOCAL_MEM_FENCE);\n"
+
+" if(gid >= input_size){\n"
+" return;\n"
+" }\n"
+
+ // get global offset
+" uint offset = global_offsets[bucket] + local_counts[bucket];\n"
+
+ // calculate local offset
+" uint local_offset = 0;\n"
+" for(uint i = 0; i < lid; i++){\n"
+" if(local_input[i] == bucket)\n"
+" local_offset++;\n"
+" }\n"
+
+"#ifndef SORT_BY_KEY\n"
+ // write value to output
+" output[output_offset + offset + local_offset] = value;\n"
+"#else\n"
+ // write key and value if doing sort_by_key
+" keys_output[keys_output_offset+offset + local_offset] = value;\n"
+" values_output[values_output_offset+offset + local_offset] =\n"
+" values_input[values_input_offset+gid];\n"
+"#endif\n"
+"}\n";
+
+template<class T, class T2>
+inline void radix_sort_impl(const buffer_iterator<T> first,
+ const buffer_iterator<T> last,
+ const buffer_iterator<T2> values_first,
+ command_queue &queue)
+{
+
+ typedef T value_type;
+ typedef typename radix_sort_value_type<sizeof(T)>::type sort_type;
+
+ const device &device = queue.get_device();
+ const context &context = queue.get_context();
+
+
+ // if we have a valid values iterator then we are doing a
+ // sort by key and have to set up the values buffer
+ bool sort_by_key = (values_first.get_buffer().get() != 0);
+
+ // load (or create) radix sort program
+ std::string cache_key =
+ std::string("__boost_radix_sort_") + type_name<value_type>();
+
+ if(sort_by_key){
+ cache_key += std::string("_with_") + type_name<T2>();
+ }
+
+ boost::shared_ptr<program_cache> cache =
+ program_cache::get_global_cache(context);
+ boost::shared_ptr<parameter_cache> parameters =
+ detail::parameter_cache::get_global_cache(device);
+
+ // sort parameters
+ const uint_ k = parameters->get(cache_key, "k", 4);
+ const uint_ k2 = 1 << k;
+ const uint_ block_size = parameters->get(cache_key, "tpb", 128);
+
+ // sort program compiler options
+ std::stringstream options;
+ options << "-DK_BITS=" << k;
+ options << " -DT=" << type_name<sort_type>();
+ options << " -DBLOCK_SIZE=" << block_size;
+
+ if(boost::is_floating_point<value_type>::value){
+ options << " -DIS_FLOATING_POINT";
+ }
+
+ if(boost::is_signed<value_type>::value){
+ options << " -DIS_SIGNED";
+ }
+
+ if(sort_by_key){
+ options << " -DSORT_BY_KEY";
+ options << " -DT2=" << type_name<T2>();
+ options << enable_double<T2>();
+ }
+
+ // load radix sort program
+ program radix_sort_program = cache->get_or_build(
+ cache_key, options.str(), radix_sort_source, context
+ );
+
+ kernel count_kernel(radix_sort_program, "count");
+ kernel scan_kernel(radix_sort_program, "scan");
+ kernel scatter_kernel(radix_sort_program, "scatter");
+
+ size_t count = detail::iterator_range_size(first, last);
+
+ uint_ block_count = static_cast<uint_>(count / block_size);
+ if(block_count * block_size != count){
+ block_count++;
+ }
+
+ // setup temporary buffers
+ vector<value_type> output(count, context);
+ vector<T2> values_output(sort_by_key ? count : 0, context);
+ vector<uint_> offsets(k2, context);
+ vector<uint_> counts(block_count * k2, context);
+
+ const buffer *input_buffer = &first.get_buffer();
+ uint_ input_offset = static_cast<uint_>(first.get_index());
+ const buffer *output_buffer = &output.get_buffer();
+ uint_ output_offset = 0;
+ const buffer *values_input_buffer = &values_first.get_buffer();
+ uint_ values_input_offset = static_cast<uint_>(values_first.get_index());
+ const buffer *values_output_buffer = &values_output.get_buffer();
+ uint_ values_output_offset = 0;
+
+ for(uint_ i = 0; i < sizeof(sort_type) * CHAR_BIT / k; i++){
+ // write counts
+ count_kernel.set_arg(0, *input_buffer);
+ count_kernel.set_arg(1, input_offset);
+ count_kernel.set_arg(2, static_cast<uint_>(count));
+ count_kernel.set_arg(3, counts);
+ count_kernel.set_arg(4, offsets);
+ count_kernel.set_arg(5, block_size * sizeof(uint_), 0);
+ count_kernel.set_arg(6, i * k);
+ queue.enqueue_1d_range_kernel(count_kernel,
+ 0,
+ block_count * block_size,
+ block_size);
+
+ // scan counts
+ if(k == 1){
+ typedef uint2_ counter_type;
+ ::boost::compute::exclusive_scan(
+ make_buffer_iterator<counter_type>(counts.get_buffer(), 0),
+ make_buffer_iterator<counter_type>(counts.get_buffer(), counts.size() / 2),
+ make_buffer_iterator<counter_type>(counts.get_buffer()),
+ queue
+ );
+ }
+ else if(k == 2){
+ typedef uint4_ counter_type;
+ ::boost::compute::exclusive_scan(
+ make_buffer_iterator<counter_type>(counts.get_buffer(), 0),
+ make_buffer_iterator<counter_type>(counts.get_buffer(), counts.size() / 4),
+ make_buffer_iterator<counter_type>(counts.get_buffer()),
+ queue
+ );
+ }
+ else if(k == 4){
+ typedef uint16_ counter_type;
+ ::boost::compute::exclusive_scan(
+ make_buffer_iterator<counter_type>(counts.get_buffer(), 0),
+ make_buffer_iterator<counter_type>(counts.get_buffer(), counts.size() / 16),
+ make_buffer_iterator<counter_type>(counts.get_buffer()),
+ queue
+ );
+ }
+ else {
+ BOOST_ASSERT(false && "unknown k");
+ break;
+ }
+
+ // scan global offsets
+ scan_kernel.set_arg(0, counts);
+ scan_kernel.set_arg(1, offsets);
+ scan_kernel.set_arg(2, block_count);
+ queue.enqueue_task(scan_kernel);
+
+ // scatter values
+ scatter_kernel.set_arg(0, *input_buffer);
+ scatter_kernel.set_arg(1, input_offset);
+ scatter_kernel.set_arg(2, static_cast<uint_>(count));
+ scatter_kernel.set_arg(3, i * k);
+ scatter_kernel.set_arg(4, counts);
+ scatter_kernel.set_arg(5, offsets);
+ scatter_kernel.set_arg(6, *output_buffer);
+ scatter_kernel.set_arg(7, output_offset);
+ if(sort_by_key){
+ scatter_kernel.set_arg(8, *values_input_buffer);
+ scatter_kernel.set_arg(9, values_input_offset);
+ scatter_kernel.set_arg(10, *values_output_buffer);
+ scatter_kernel.set_arg(11, values_output_offset);
+ }
+ queue.enqueue_1d_range_kernel(scatter_kernel,
+ 0,
+ block_count * block_size,
+ block_size);
+
+ // swap buffers
+ std::swap(input_buffer, output_buffer);
+ std::swap(values_input_buffer, values_output_buffer);
+ std::swap(input_offset, output_offset);
+ std::swap(values_input_offset, values_output_offset);
+ }
+}
+
+template<class Iterator>
+inline void radix_sort(Iterator first,
+ Iterator last,
+ command_queue &queue)
+{
+ radix_sort_impl(first, last, buffer_iterator<int>(), queue);
+}
+
+template<class KeyIterator, class ValueIterator>
+inline void radix_sort_by_key(KeyIterator keys_first,
+ KeyIterator keys_last,
+ ValueIterator values_first,
+ command_queue &queue)
+{
+ radix_sort_impl(keys_first, keys_last, values_first, queue);
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_RADIX_SORT_HPP
diff --git a/boost/compute/algorithm/detail/random_fill.hpp b/boost/compute/algorithm/detail/random_fill.hpp
new file mode 100644
index 0000000000..5c3827a9f8
--- /dev/null
+++ b/boost/compute/algorithm/detail/random_fill.hpp
@@ -0,0 +1,57 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_RANDOM_FILL_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_RANDOM_FILL_HPP
+
+#include <iterator>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/random/default_random_engine.hpp>
+#include <boost/compute/random/uniform_real_distribution.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class OutputIterator, class Generator>
+inline void random_fill(OutputIterator first,
+ OutputIterator last,
+ Generator &g,
+ command_queue &queue)
+{
+ g.fill(first, last, queue);
+}
+
+template<class OutputIterator>
+inline void
+random_fill(OutputIterator first,
+ OutputIterator last,
+ typename std::iterator_traits<OutputIterator>::value_type lo,
+ typename std::iterator_traits<OutputIterator>::value_type hi,
+ command_queue &queue)
+{
+ typedef typename
+ std::iterator_traits<OutputIterator>::value_type value_type;
+ typedef typename
+ boost::compute::default_random_engine engine_type;
+ typedef typename
+ boost::compute::uniform_real_distribution<value_type> distribution_type;
+
+ engine_type engine(queue);
+ distribution_type generator(lo, hi);
+ generator.fill(first, last, engine, queue);
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_RANDOM_FILL_HPP
diff --git a/boost/compute/algorithm/detail/reduce_by_key.hpp b/boost/compute/algorithm/detail/reduce_by_key.hpp
new file mode 100644
index 0000000000..65844c9ebf
--- /dev/null
+++ b/boost/compute/algorithm/detail/reduce_by_key.hpp
@@ -0,0 +1,119 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2015 Jakub Szuppe <j.szuppe@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_REDUCE_BY_KEY_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_REDUCE_BY_KEY_HPP
+
+#include <algorithm>
+#include <iterator>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/algorithm/detail/serial_reduce_by_key.hpp>
+#include <boost/compute/algorithm/detail/reduce_by_key_with_scan.hpp>
+#include <boost/compute/type_traits.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputKeyIterator, class InputValueIterator,
+ class OutputKeyIterator, class OutputValueIterator,
+ class BinaryFunction, class BinaryPredicate>
+size_t reduce_by_key_on_gpu(InputKeyIterator keys_first,
+ InputKeyIterator keys_last,
+ InputValueIterator values_first,
+ OutputKeyIterator keys_result,
+ OutputValueIterator values_result,
+ BinaryFunction function,
+ BinaryPredicate predicate,
+ command_queue &queue)
+{
+ return detail::reduce_by_key_with_scan(keys_first, keys_last, values_first,
+ keys_result, values_result, function,
+ predicate, queue);
+}
+
+template<class InputKeyIterator, class InputValueIterator,
+ class OutputKeyIterator, class OutputValueIterator>
+bool reduce_by_key_on_gpu_requirements_met(InputKeyIterator keys_first,
+ InputValueIterator values_first,
+ OutputKeyIterator keys_result,
+ OutputValueIterator values_result,
+ const size_t count,
+ command_queue &queue)
+{
+ const device &device = queue.get_device();
+ return (count > 256)
+ && !(device.type() & device::cpu)
+ && reduce_by_key_with_scan_requirements_met(keys_first, values_first,
+ keys_result,values_result,
+ count, queue);
+ return true;
+}
+
+template<class InputKeyIterator, class InputValueIterator,
+ class OutputKeyIterator, class OutputValueIterator,
+ class BinaryFunction, class BinaryPredicate>
+inline std::pair<OutputKeyIterator, OutputValueIterator>
+dispatch_reduce_by_key(InputKeyIterator keys_first,
+ InputKeyIterator keys_last,
+ InputValueIterator values_first,
+ OutputKeyIterator keys_result,
+ OutputValueIterator values_result,
+ BinaryFunction function,
+ BinaryPredicate predicate,
+ command_queue &queue)
+{
+ typedef typename
+ std::iterator_traits<OutputKeyIterator>::difference_type key_difference_type;
+ typedef typename
+ std::iterator_traits<OutputValueIterator>::difference_type value_difference_type;
+
+ const size_t count = detail::iterator_range_size(keys_first, keys_last);
+ if (count < 2) {
+ boost::compute::copy_n(keys_first, count, keys_result, queue);
+ boost::compute::copy_n(values_first, count, values_result, queue);
+ return
+ std::make_pair<OutputKeyIterator, OutputValueIterator>(
+ keys_result + static_cast<key_difference_type>(count),
+ values_result + static_cast<value_difference_type>(count)
+ );
+ }
+
+ size_t result_size = 0;
+ if(reduce_by_key_on_gpu_requirements_met(keys_first, values_first, keys_result,
+ values_result, count, queue)){
+ result_size =
+ detail::reduce_by_key_on_gpu(keys_first, keys_last, values_first,
+ keys_result, values_result, function,
+ predicate, queue);
+ }
+ else {
+ result_size =
+ detail::serial_reduce_by_key(keys_first, keys_last, values_first,
+ keys_result, values_result, function,
+ predicate, queue);
+ }
+
+ return
+ std::make_pair<OutputKeyIterator, OutputValueIterator>(
+ keys_result + static_cast<key_difference_type>(result_size),
+ values_result + static_cast<value_difference_type>(result_size)
+ );
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_REDUCE_BY_KEY_HPP
diff --git a/boost/compute/algorithm/detail/reduce_by_key_with_scan.hpp b/boost/compute/algorithm/detail/reduce_by_key_with_scan.hpp
new file mode 100644
index 0000000000..e6852a67eb
--- /dev/null
+++ b/boost/compute/algorithm/detail/reduce_by_key_with_scan.hpp
@@ -0,0 +1,541 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2015 Jakub Szuppe <j.szuppe@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_REDUCE_BY_KEY_WITH_SCAN_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_REDUCE_BY_KEY_WITH_SCAN_HPP
+
+#include <algorithm>
+#include <iterator>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/algorithm/inclusive_scan.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/container/detail/scalar.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/read_write_single_value.hpp>
+#include <boost/compute/type_traits.hpp>
+#include <boost/compute/utility/program_cache.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+/// \internal_
+///
+/// Fills \p new_keys_first with unsigned integer keys generated from vector
+/// of original keys \p keys_first. New keys can be distinguish by simple equality
+/// predicate.
+///
+/// \param keys_first iterator pointing to the first key
+/// \param number_of_keys number of keys
+/// \param predicate binary predicate for key comparison
+/// \param new_keys_first iterator pointing to the new keys vector
+/// \param preferred_work_group_size preferred work group size
+/// \param queue command queue to perform the operation
+///
+/// Binary function \p predicate must take two keys as arguments and
+/// return true only if they are considered the same.
+///
+/// The first new key equals zero and the last equals number of unique keys
+/// minus one.
+///
+/// No local memory usage.
+template<class InputKeyIterator, class BinaryPredicate>
+inline void generate_uint_keys(InputKeyIterator keys_first,
+ size_t number_of_keys,
+ BinaryPredicate predicate,
+ vector<uint_>::iterator new_keys_first,
+ size_t preferred_work_group_size,
+ command_queue &queue)
+{
+ typedef typename
+ std::iterator_traits<InputKeyIterator>::value_type key_type;
+
+ detail::meta_kernel k("reduce_by_key_new_key_flags");
+ k.add_set_arg<const uint_>("count", uint_(number_of_keys));
+
+ k <<
+ k.decl<const uint_>("gid") << " = get_global_id(0);\n" <<
+ k.decl<uint_>("value") << " = 0;\n" <<
+ "if(gid >= count){\n return;\n}\n" <<
+ "if(gid > 0){ \n" <<
+ k.decl<key_type>("key") << " = " <<
+ keys_first[k.var<const uint_>("gid")] << ";\n" <<
+ k.decl<key_type>("previous_key") << " = " <<
+ keys_first[k.var<const uint_>("gid - 1")] << ";\n" <<
+ " value = " << predicate(k.var<key_type>("previous_key"),
+ k.var<key_type>("key")) <<
+ " ? 0 : 1;\n" <<
+ "}\n else {\n" <<
+ " value = 0;\n" <<
+ "}\n" <<
+ new_keys_first[k.var<const uint_>("gid")] << " = value;\n";
+
+ const context &context = queue.get_context();
+ kernel kernel = k.compile(context);
+
+ size_t work_group_size = preferred_work_group_size;
+ size_t work_groups_no = static_cast<size_t>(
+ std::ceil(float(number_of_keys) / work_group_size)
+ );
+
+ queue.enqueue_1d_range_kernel(kernel,
+ 0,
+ work_groups_no * work_group_size,
+ work_group_size);
+
+ inclusive_scan(new_keys_first, new_keys_first + number_of_keys,
+ new_keys_first, queue);
+}
+
+/// \internal_
+/// Calculate carry-out for each work group.
+/// Carry-out is a pair of the last key processed by a work group and sum of all
+/// values under this key in this work group.
+template<class InputValueIterator, class OutputValueIterator, class BinaryFunction>
+inline void carry_outs(vector<uint_>::iterator keys_first,
+ InputValueIterator values_first,
+ size_t count,
+ vector<uint_>::iterator carry_out_keys_first,
+ OutputValueIterator carry_out_values_first,
+ BinaryFunction function,
+ size_t work_group_size,
+ command_queue &queue)
+{
+ typedef typename
+ std::iterator_traits<OutputValueIterator>::value_type value_out_type;
+
+ detail::meta_kernel k("reduce_by_key_with_scan_carry_outs");
+ k.add_set_arg<const uint_>("count", uint_(count));
+ size_t local_keys_arg = k.add_arg<uint_ *>(memory_object::local_memory, "lkeys");
+ size_t local_vals_arg = k.add_arg<value_out_type *>(memory_object::local_memory, "lvals");
+
+ k <<
+ k.decl<const uint_>("gid") << " = get_global_id(0);\n" <<
+ k.decl<const uint_>("wg_size") << " = get_local_size(0);\n" <<
+ k.decl<const uint_>("lid") << " = get_local_id(0);\n" <<
+ k.decl<const uint_>("group_id") << " = get_group_id(0);\n" <<
+
+ k.decl<uint_>("key") << ";\n" <<
+ k.decl<value_out_type>("value") << ";\n" <<
+ "if(gid < count){\n" <<
+ k.var<uint_>("key") << " = " <<
+ keys_first[k.var<const uint_>("gid")] << ";\n" <<
+ k.var<value_out_type>("value") << " = " <<
+ values_first[k.var<const uint_>("gid")] << ";\n" <<
+ "lkeys[lid] = key;\n" <<
+ "lvals[lid] = value;\n" <<
+ "}\n" <<
+
+ // Calculate carry out for each work group by performing Hillis/Steele scan
+ // where only last element (key-value pair) is saved
+ k.decl<value_out_type>("result") << " = value;\n" <<
+ k.decl<uint_>("other_key") << ";\n" <<
+ k.decl<value_out_type>("other_value") << ";\n" <<
+
+ "for(" << k.decl<uint_>("offset") << " = 1; " <<
+ "offset < wg_size; offset *= 2){\n"
+ " barrier(CLK_LOCAL_MEM_FENCE);\n" <<
+ " if(lid >= offset){\n"
+ " other_key = lkeys[lid - offset];\n" <<
+ " if(other_key == key){\n" <<
+ " other_value = lvals[lid - offset];\n" <<
+ " result = " << function(k.var<value_out_type>("result"),
+ k.var<value_out_type>("other_value")) << ";\n" <<
+ " }\n" <<
+ " }\n" <<
+ " barrier(CLK_LOCAL_MEM_FENCE);\n" <<
+ " lvals[lid] = result;\n" <<
+ "}\n" <<
+
+ // save carry out
+ "if(lid == (wg_size - 1)){\n" <<
+ carry_out_keys_first[k.var<const uint_>("group_id")] << " = key;\n" <<
+ carry_out_values_first[k.var<const uint_>("group_id")] << " = result;\n" <<
+ "}\n";
+
+ size_t work_groups_no = static_cast<size_t>(
+ std::ceil(float(count) / work_group_size)
+ );
+
+ const context &context = queue.get_context();
+ kernel kernel = k.compile(context);
+ kernel.set_arg(local_keys_arg, local_buffer<uint_>(work_group_size));
+ kernel.set_arg(local_vals_arg, local_buffer<value_out_type>(work_group_size));
+
+ queue.enqueue_1d_range_kernel(kernel,
+ 0,
+ work_groups_no * work_group_size,
+ work_group_size);
+}
+
+/// \internal_
+/// Calculate carry-in by performing inclusive scan by key on carry-outs vector.
+template<class OutputValueIterator, class BinaryFunction>
+inline void carry_ins(vector<uint_>::iterator carry_out_keys_first,
+ OutputValueIterator carry_out_values_first,
+ OutputValueIterator carry_in_values_first,
+ size_t carry_out_size,
+ BinaryFunction function,
+ size_t work_group_size,
+ command_queue &queue)
+{
+ typedef typename
+ std::iterator_traits<OutputValueIterator>::value_type value_out_type;
+
+ uint_ values_pre_work_item = static_cast<uint_>(
+ std::ceil(float(carry_out_size) / work_group_size)
+ );
+
+ detail::meta_kernel k("reduce_by_key_with_scan_carry_ins");
+ k.add_set_arg<const uint_>("carry_out_size", uint_(carry_out_size));
+ k.add_set_arg<const uint_>("values_per_work_item", values_pre_work_item);
+ size_t local_keys_arg = k.add_arg<uint_ *>(memory_object::local_memory, "lkeys");
+ size_t local_vals_arg = k.add_arg<value_out_type *>(memory_object::local_memory, "lvals");
+
+ k <<
+ k.decl<uint_>("id") << " = get_global_id(0) * values_per_work_item;\n" <<
+ k.decl<uint_>("idx") << " = id;\n" <<
+ k.decl<const uint_>("wg_size") << " = get_local_size(0);\n" <<
+ k.decl<const uint_>("lid") << " = get_local_id(0);\n" <<
+ k.decl<const uint_>("group_id") << " = get_group_id(0);\n" <<
+
+ k.decl<uint_>("key") << ";\n" <<
+ k.decl<value_out_type>("value") << ";\n" <<
+ k.decl<uint_>("previous_key") << ";\n" <<
+ k.decl<value_out_type>("result") << ";\n" <<
+
+ "if(id < carry_out_size){\n" <<
+ k.var<uint_>("previous_key") << " = " <<
+ carry_out_keys_first[k.var<const uint_>("id")] << ";\n" <<
+ k.var<value_out_type>("result") << " = " <<
+ carry_out_values_first[k.var<const uint_>("id")] << ";\n" <<
+ carry_in_values_first[k.var<const uint_>("id")] << " = result;\n" <<
+ "}\n" <<
+
+ k.decl<const uint_>("end") << " = (id + values_per_work_item) <= carry_out_size" <<
+ " ? (values_per_work_item + id) : carry_out_size;\n" <<
+
+ "for(idx = idx + 1; idx < end; idx += 1){\n" <<
+ " key = " << carry_out_keys_first[k.var<const uint_>("idx")] << ";\n" <<
+ " value = " << carry_out_values_first[k.var<const uint_>("idx")] << ";\n" <<
+ " if(previous_key == key){\n" <<
+ " result = " << function(k.var<value_out_type>("result"),
+ k.var<value_out_type>("value")) << ";\n" <<
+ " }\n else { \n" <<
+ " result = value;\n"
+ " }\n" <<
+ " " << carry_in_values_first[k.var<const uint_>("idx")] << " = result;\n" <<
+ " previous_key = key;\n"
+ "}\n" <<
+
+ // save the last key and result to local memory
+ "lkeys[lid] = previous_key;\n" <<
+ "lvals[lid] = result;\n" <<
+
+ // Hillis/Steele scan
+ "for(" << k.decl<uint_>("offset") << " = 1; " <<
+ "offset < wg_size; offset *= 2){\n"
+ " barrier(CLK_LOCAL_MEM_FENCE);\n" <<
+ " if(lid >= offset){\n"
+ " key = lkeys[lid - offset];\n" <<
+ " if(previous_key == key){\n" <<
+ " value = lvals[lid - offset];\n" <<
+ " result = " << function(k.var<value_out_type>("result"),
+ k.var<value_out_type>("value")) << ";\n" <<
+ " }\n" <<
+ " }\n" <<
+ " barrier(CLK_LOCAL_MEM_FENCE);\n" <<
+ " lvals[lid] = result;\n" <<
+ "}\n" <<
+ "barrier(CLK_LOCAL_MEM_FENCE);\n" <<
+
+ "if(lid > 0){\n" <<
+ // load key-value reduced by previous work item
+ " previous_key = lkeys[lid - 1];\n" <<
+ " result = lvals[lid - 1];\n" <<
+ "}\n" <<
+
+ // add key-value reduced by previous work item
+ "for(idx = id; idx < id + values_per_work_item; idx += 1){\n" <<
+ // make sure all carry-ins are saved in global memory
+ " barrier( CLK_GLOBAL_MEM_FENCE );\n" <<
+ " if(lid > 0 && idx < carry_out_size) {\n"
+ " key = " << carry_out_keys_first[k.var<const uint_>("idx")] << ";\n" <<
+ " value = " << carry_in_values_first[k.var<const uint_>("idx")] << ";\n" <<
+ " if(previous_key == key){\n" <<
+ " value = " << function(k.var<value_out_type>("result"),
+ k.var<value_out_type>("value")) << ";\n" <<
+ " }\n" <<
+ " " << carry_in_values_first[k.var<const uint_>("idx")] << " = value;\n" <<
+ " }\n" <<
+ "}\n";
+
+
+ const context &context = queue.get_context();
+ kernel kernel = k.compile(context);
+ kernel.set_arg(local_keys_arg, local_buffer<uint_>(work_group_size));
+ kernel.set_arg(local_vals_arg, local_buffer<value_out_type>(work_group_size));
+
+ queue.enqueue_1d_range_kernel(kernel,
+ 0,
+ work_group_size,
+ work_group_size);
+}
+
+/// \internal_
+///
+/// Perform final reduction by key. Each work item:
+/// 1. Perform local work-group reduction (Hillis/Steele scan)
+/// 2. Add carry-in (if keys are right)
+/// 3. Save reduced value if next key is different than processed one
+template<class InputKeyIterator, class InputValueIterator,
+ class OutputKeyIterator, class OutputValueIterator,
+ class BinaryFunction>
+inline void final_reduction(InputKeyIterator keys_first,
+ InputValueIterator values_first,
+ OutputKeyIterator keys_result,
+ OutputValueIterator values_result,
+ size_t count,
+ BinaryFunction function,
+ vector<uint_>::iterator new_keys_first,
+ vector<uint_>::iterator carry_in_keys_first,
+ OutputValueIterator carry_in_values_first,
+ size_t carry_in_size,
+ size_t work_group_size,
+ command_queue &queue)
+{
+ typedef typename
+ std::iterator_traits<OutputValueIterator>::value_type value_out_type;
+
+ detail::meta_kernel k("reduce_by_key_with_scan_final_reduction");
+ k.add_set_arg<const uint_>("count", uint_(count));
+ size_t local_keys_arg = k.add_arg<uint_ *>(memory_object::local_memory, "lkeys");
+ size_t local_vals_arg = k.add_arg<value_out_type *>(memory_object::local_memory, "lvals");
+
+ k <<
+ k.decl<const uint_>("gid") << " = get_global_id(0);\n" <<
+ k.decl<const uint_>("wg_size") << " = get_local_size(0);\n" <<
+ k.decl<const uint_>("lid") << " = get_local_id(0);\n" <<
+ k.decl<const uint_>("group_id") << " = get_group_id(0);\n" <<
+
+ k.decl<uint_>("key") << ";\n" <<
+ k.decl<value_out_type>("value") << ";\n"
+
+ "if(gid < count){\n" <<
+ k.var<uint_>("key") << " = " <<
+ new_keys_first[k.var<const uint_>("gid")] << ";\n" <<
+ k.var<value_out_type>("value") << " = " <<
+ values_first[k.var<const uint_>("gid")] << ";\n" <<
+ "lkeys[lid] = key;\n" <<
+ "lvals[lid] = value;\n" <<
+ "}\n" <<
+
+ // Hillis/Steele scan
+ k.decl<value_out_type>("result") << " = value;\n" <<
+ k.decl<uint_>("other_key") << ";\n" <<
+ k.decl<value_out_type>("other_value") << ";\n" <<
+
+ "for(" << k.decl<uint_>("offset") << " = 1; " <<
+ "offset < wg_size ; offset *= 2){\n"
+ " barrier(CLK_LOCAL_MEM_FENCE);\n" <<
+ " if(lid >= offset) {\n" <<
+ " other_key = lkeys[lid - offset];\n" <<
+ " if(other_key == key){\n" <<
+ " other_value = lvals[lid - offset];\n" <<
+ " result = " << function(k.var<value_out_type>("result"),
+ k.var<value_out_type>("other_value")) << ";\n" <<
+ " }\n" <<
+ " }\n" <<
+ " barrier(CLK_LOCAL_MEM_FENCE);\n" <<
+ " lvals[lid] = result;\n" <<
+ "}\n" <<
+
+ "if(gid >= count) {\n return;\n};\n" <<
+
+ k.decl<const bool>("save") << " = (gid < (count - 1)) ?"
+ << new_keys_first[k.var<const uint_>("gid + 1")] << " != key" <<
+ ": true;\n" <<
+
+ // Add carry in
+ k.decl<uint_>("carry_in_key") << ";\n" <<
+ "if(group_id > 0 && save) {\n" <<
+ " carry_in_key = " << carry_in_keys_first[k.var<const uint_>("group_id - 1")] << ";\n" <<
+ " if(key == carry_in_key){\n" <<
+ " other_value = " << carry_in_values_first[k.var<const uint_>("group_id - 1")] << ";\n" <<
+ " result = " << function(k.var<value_out_type>("result"),
+ k.var<value_out_type>("other_value")) << ";\n" <<
+ " }\n" <<
+ "}\n" <<
+
+ // Save result only if the next key is different or it's the last element.
+ "if(save){\n" <<
+ keys_result[k.var<uint_>("key")] << " = " << keys_first[k.var<const uint_>("gid")] << ";\n" <<
+ values_result[k.var<uint_>("key")] << " = result;\n" <<
+ "}\n"
+ ;
+
+ size_t work_groups_no = static_cast<size_t>(
+ std::ceil(float(count) / work_group_size)
+ );
+
+ const context &context = queue.get_context();
+ kernel kernel = k.compile(context);
+ kernel.set_arg(local_keys_arg, local_buffer<uint_>(work_group_size));
+ kernel.set_arg(local_vals_arg, local_buffer<value_out_type>(work_group_size));
+
+ queue.enqueue_1d_range_kernel(kernel,
+ 0,
+ work_groups_no * work_group_size,
+ work_group_size);
+}
+
+/// \internal_
+/// Returns preferred work group size for reduce by key with scan algorithm.
+template<class KeyType, class ValueType>
+inline size_t get_work_group_size(const device& device)
+{
+ std::string cache_key = std::string("__boost_reduce_by_key_with_scan")
+ + "k_" + type_name<KeyType>() + "_v_" + type_name<ValueType>();
+
+ // load parameters
+ boost::shared_ptr<parameter_cache> parameters =
+ detail::parameter_cache::get_global_cache(device);
+
+ return (std::max)(
+ static_cast<size_t>(parameters->get(cache_key, "wgsize", 256)),
+ static_cast<size_t>(device.get_info<CL_DEVICE_MAX_WORK_GROUP_SIZE>())
+ );
+}
+
+/// \internal_
+///
+/// 1. For each work group carry-out value is calculated (it's done by key-oriented
+/// Hillis/Steele scan). Carry-out is a pair of the last key processed by work
+/// group and sum of all values under this key in work group.
+/// 2. From every carry-out carry-in is calculated by performing inclusive scan
+/// by key.
+/// 3. Final reduction by key is performed (key-oriented Hillis/Steele scan),
+/// carry-in values are added where needed.
+template<class InputKeyIterator, class InputValueIterator,
+ class OutputKeyIterator, class OutputValueIterator,
+ class BinaryFunction, class BinaryPredicate>
+inline size_t reduce_by_key_with_scan(InputKeyIterator keys_first,
+ InputKeyIterator keys_last,
+ InputValueIterator values_first,
+ OutputKeyIterator keys_result,
+ OutputValueIterator values_result,
+ BinaryFunction function,
+ BinaryPredicate predicate,
+ command_queue &queue)
+{
+ typedef typename
+ std::iterator_traits<InputValueIterator>::value_type value_type;
+ typedef typename
+ std::iterator_traits<InputKeyIterator>::value_type key_type;
+ typedef typename
+ std::iterator_traits<OutputValueIterator>::value_type value_out_type;
+
+ const context &context = queue.get_context();
+ size_t count = detail::iterator_range_size(keys_first, keys_last);
+
+ if(count == 0){
+ return size_t(0);
+ }
+
+ const device &device = queue.get_device();
+ size_t work_group_size = get_work_group_size<value_type, key_type>(device);
+
+ // Replace original key with unsigned integer keys generated based on given
+ // predicate. New key is also an index for keys_result and values_result vectors,
+ // which points to place where reduced value should be saved.
+ vector<uint_> new_keys(count, context);
+ vector<uint_>::iterator new_keys_first = new_keys.begin();
+ generate_uint_keys(keys_first, count, predicate, new_keys_first,
+ work_group_size, queue);
+
+ // Calculate carry-out and carry-in vectors size
+ const size_t carry_out_size = static_cast<size_t>(
+ std::ceil(float(count) / work_group_size)
+ );
+ vector<uint_> carry_out_keys(carry_out_size, context);
+ vector<value_out_type> carry_out_values(carry_out_size, context);
+ carry_outs(new_keys_first, values_first, count, carry_out_keys.begin(),
+ carry_out_values.begin(), function, work_group_size, queue);
+
+ vector<value_out_type> carry_in_values(carry_out_size, context);
+ carry_ins(carry_out_keys.begin(), carry_out_values.begin(),
+ carry_in_values.begin(), carry_out_size, function, work_group_size,
+ queue);
+
+ final_reduction(keys_first, values_first, keys_result, values_result,
+ count, function, new_keys_first, carry_out_keys.begin(),
+ carry_in_values.begin(), carry_out_size, work_group_size,
+ queue);
+
+ const size_t result = read_single_value<uint_>(new_keys.get_buffer(),
+ count - 1, queue);
+ return result + 1;
+}
+
+/// \internal_
+/// Return true if requirements for running reduce by key with scan on given
+/// device are met (at least one work group of preferred size can be run).
+template<class InputKeyIterator, class InputValueIterator,
+ class OutputKeyIterator, class OutputValueIterator>
+bool reduce_by_key_with_scan_requirements_met(InputKeyIterator keys_first,
+ InputValueIterator values_first,
+ OutputKeyIterator keys_result,
+ OutputValueIterator values_result,
+ const size_t count,
+ command_queue &queue)
+{
+ typedef typename
+ std::iterator_traits<InputValueIterator>::value_type value_type;
+ typedef typename
+ std::iterator_traits<InputKeyIterator>::value_type key_type;
+ typedef typename
+ std::iterator_traits<OutputValueIterator>::value_type value_out_type;
+
+ (void) keys_first;
+ (void) values_first;
+ (void) keys_result;
+ (void) values_result;
+
+ const device &device = queue.get_device();
+ // device must have dedicated local memory storage
+ if(device.get_info<CL_DEVICE_LOCAL_MEM_TYPE>() != CL_LOCAL)
+ {
+ return false;
+ }
+
+ // local memory size in bytes (per compute unit)
+ const size_t local_mem_size = device.get_info<CL_DEVICE_LOCAL_MEM_SIZE>();
+
+ // preferred work group size
+ size_t work_group_size = get_work_group_size<key_type, value_type>(device);
+
+ // local memory size needed to perform parallel reduction
+ size_t required_local_mem_size = 0;
+ // keys size
+ required_local_mem_size += sizeof(uint_) * work_group_size;
+ // reduced values size
+ required_local_mem_size += sizeof(value_out_type) * work_group_size;
+
+ return (required_local_mem_size <= local_mem_size);
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_REDUCE_BY_KEY_WITH_SCAN_HPP
diff --git a/boost/compute/algorithm/detail/reduce_on_gpu.hpp b/boost/compute/algorithm/detail/reduce_on_gpu.hpp
new file mode 100644
index 0000000000..335fba8724
--- /dev/null
+++ b/boost/compute/algorithm/detail/reduce_on_gpu.hpp
@@ -0,0 +1,286 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_REDUCE_ON_GPU_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_REDUCE_ON_GPU_HPP
+
+#include <iterator>
+
+#include <boost/compute/utility/source.hpp>
+#include <boost/compute/program.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/detail/vendor.hpp>
+#include <boost/compute/detail/parameter_cache.hpp>
+#include <boost/compute/detail/work_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/utility/program_cache.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+/// \internal
+/// body reduction inside a warp
+template<typename T,bool isNvidiaDevice>
+struct ReduceBody
+{
+ static std::string body()
+ {
+ std::stringstream k;
+ // local reduction
+ k << "for(int i = 1; i < TPB; i <<= 1){\n" <<
+ " barrier(CLK_LOCAL_MEM_FENCE);\n" <<
+ " uint mask = (i << 1) - 1;\n" <<
+ " if((lid & mask) == 0){\n" <<
+ " scratch[lid] += scratch[lid+i];\n" <<
+ " }\n" <<
+ "}\n";
+ return k.str();
+ }
+};
+
+/// \internal
+/// body reduction inside a warp
+/// for nvidia device we can use the "unsafe"
+/// memory optimisation
+template<typename T>
+struct ReduceBody<T,true>
+{
+ static std::string body()
+ {
+ std::stringstream k;
+ // local reduction
+ // we use TPB to compile only useful instruction
+ // local reduction when size is greater than warp size
+ k << "barrier(CLK_LOCAL_MEM_FENCE);\n" <<
+ "if(TPB >= 1024){\n" <<
+ "if(lid < 512) { sum += scratch[lid + 512]; scratch[lid] = sum;} barrier(CLK_LOCAL_MEM_FENCE);}\n" <<
+ "if(TPB >= 512){\n" <<
+ "if(lid < 256) { sum += scratch[lid + 256]; scratch[lid] = sum;} barrier(CLK_LOCAL_MEM_FENCE);}\n" <<
+ "if(TPB >= 256){\n" <<
+ "if(lid < 128) { sum += scratch[lid + 128]; scratch[lid] = sum;} barrier(CLK_LOCAL_MEM_FENCE);}\n" <<
+ "if(TPB >= 128){\n" <<
+ "if(lid < 64) { sum += scratch[lid + 64]; scratch[lid] = sum;} barrier(CLK_LOCAL_MEM_FENCE);} \n" <<
+
+ // warp reduction
+ "if(lid < 32){\n" <<
+ // volatile this way we don't need any barrier
+ "volatile __local " << type_name<T>() << " *lmem = scratch;\n" <<
+ "if(TPB >= 64) { lmem[lid] = sum = sum + lmem[lid+32];} \n" <<
+ "if(TPB >= 32) { lmem[lid] = sum = sum + lmem[lid+16];} \n" <<
+ "if(TPB >= 16) { lmem[lid] = sum = sum + lmem[lid+ 8];} \n" <<
+ "if(TPB >= 8) { lmem[lid] = sum = sum + lmem[lid+ 4];} \n" <<
+ "if(TPB >= 4) { lmem[lid] = sum = sum + lmem[lid+ 2];} \n" <<
+ "if(TPB >= 2) { lmem[lid] = sum = sum + lmem[lid+ 1];} \n" <<
+ "}\n";
+ return k.str();
+ }
+};
+
+template<class InputIterator, class Function>
+inline void initial_reduce(InputIterator first,
+ InputIterator last,
+ buffer result,
+ const Function &function,
+ kernel &reduce_kernel,
+ const uint_ vpt,
+ const uint_ tpb,
+ command_queue &queue)
+{
+ (void) function;
+ (void) reduce_kernel;
+
+ typedef typename std::iterator_traits<InputIterator>::value_type Arg;
+ typedef typename boost::tr1_result_of<Function(Arg, Arg)>::type T;
+
+ size_t count = std::distance(first, last);
+ detail::meta_kernel k("initial_reduce");
+ k.add_set_arg<const uint_>("count", uint_(count));
+ size_t output_arg = k.add_arg<T *>(memory_object::global_memory, "output");
+
+ k <<
+ k.decl<const uint_>("offset") << " = get_group_id(0) * VPT * TPB;\n" <<
+ k.decl<const uint_>("lid") << " = get_local_id(0);\n" <<
+
+ "__local " << type_name<T>() << " scratch[TPB];\n" <<
+
+ // private reduction
+ k.decl<T>("sum") << " = 0;\n" <<
+ "for(uint i = 0; i < VPT; i++){\n" <<
+ " if(offset + lid + i*TPB < count){\n" <<
+ " sum = sum + " << first[k.var<uint_>("offset+lid+i*TPB")] << ";\n" <<
+ " }\n" <<
+ "}\n" <<
+
+ "scratch[lid] = sum;\n" <<
+
+ // local reduction
+ ReduceBody<T,false>::body() <<
+
+ // write sum to output
+ "if(lid == 0){\n" <<
+ " output[get_group_id(0)] = scratch[0];\n" <<
+ "}\n";
+
+ const context &context = queue.get_context();
+ std::stringstream options;
+ options << "-DVPT=" << vpt << " -DTPB=" << tpb;
+ kernel generic_reduce_kernel = k.compile(context, options.str());
+ generic_reduce_kernel.set_arg(output_arg, result);
+
+ size_t work_size = calculate_work_size(count, vpt, tpb);
+
+ queue.enqueue_1d_range_kernel(generic_reduce_kernel, 0, work_size, tpb);
+}
+
+template<class T>
+inline void initial_reduce(const buffer_iterator<T> &first,
+ const buffer_iterator<T> &last,
+ const buffer &result,
+ const plus<T> &function,
+ kernel &reduce_kernel,
+ const uint_ vpt,
+ const uint_ tpb,
+ command_queue &queue)
+{
+ (void) function;
+
+ size_t count = std::distance(first, last);
+
+ reduce_kernel.set_arg(0, first.get_buffer());
+ reduce_kernel.set_arg(1, uint_(first.get_index()));
+ reduce_kernel.set_arg(2, uint_(count));
+ reduce_kernel.set_arg(3, result);
+ reduce_kernel.set_arg(4, uint_(0));
+
+ size_t work_size = calculate_work_size(count, vpt, tpb);
+
+ queue.enqueue_1d_range_kernel(reduce_kernel, 0, work_size, tpb);
+}
+
+template<class InputIterator, class T, class Function>
+inline void reduce_on_gpu(InputIterator first,
+ InputIterator last,
+ buffer_iterator<T> result,
+ Function function,
+ command_queue &queue)
+{
+ const device &device = queue.get_device();
+ const context &context = queue.get_context();
+
+ detail::meta_kernel k("reduce");
+ k.add_arg<const T*>(memory_object::global_memory, "input");
+ k.add_arg<const uint_>("offset");
+ k.add_arg<const uint_>("count");
+ k.add_arg<T*>(memory_object::global_memory, "output");
+ k.add_arg<const uint_>("output_offset");
+
+ k <<
+ k.decl<const uint_>("block_offset") << " = get_group_id(0) * VPT * TPB;\n" <<
+ "__global const " << type_name<T>() << " *block = input + offset + block_offset;\n" <<
+ k.decl<const uint_>("lid") << " = get_local_id(0);\n" <<
+
+ "__local " << type_name<T>() << " scratch[TPB];\n" <<
+ // private reduction
+ k.decl<T>("sum") << " = 0;\n" <<
+ "for(uint i = 0; i < VPT; i++){\n" <<
+ " if(block_offset + lid + i*TPB < count){\n" <<
+ " sum = sum + block[lid+i*TPB]; \n" <<
+ " }\n" <<
+ "}\n" <<
+
+ "scratch[lid] = sum;\n";
+
+ // discrimination on vendor name
+ if(is_nvidia_device(device))
+ k << ReduceBody<T,true>::body();
+ else
+ k << ReduceBody<T,false>::body();
+
+ k <<
+ // write sum to output
+ "if(lid == 0){\n" <<
+ " output[output_offset + get_group_id(0)] = scratch[0];\n" <<
+ "}\n";
+
+ std::string cache_key = std::string("__boost_reduce_on_gpu_") + type_name<T>();
+
+ // load parameters
+ boost::shared_ptr<parameter_cache> parameters =
+ detail::parameter_cache::get_global_cache(device);
+
+ uint_ vpt = parameters->get(cache_key, "vpt", 8);
+ uint_ tpb = parameters->get(cache_key, "tpb", 128);
+
+ // reduce program compiler flags
+ std::stringstream options;
+ options << "-DT=" << type_name<T>()
+ << " -DVPT=" << vpt
+ << " -DTPB=" << tpb;
+
+ // load program
+ boost::shared_ptr<program_cache> cache =
+ program_cache::get_global_cache(context);
+
+ program reduce_program = cache->get_or_build(
+ cache_key, options.str(), k.source(), context
+ );
+
+ // create reduce kernel
+ kernel reduce_kernel(reduce_program, "reduce");
+
+ size_t count = std::distance(first, last);
+
+ // first pass, reduce from input to ping
+ buffer ping(context, std::ceil(float(count) / vpt / tpb) * sizeof(T));
+ initial_reduce(first, last, ping, function, reduce_kernel, vpt, tpb, queue);
+
+ // update count after initial reduce
+ count = static_cast<size_t>(std::ceil(float(count) / vpt / tpb));
+
+ // middle pass(es), reduce between ping and pong
+ const buffer *input_buffer = &ping;
+ buffer pong(context, static_cast<size_t>(count / vpt / tpb * sizeof(T)));
+ const buffer *output_buffer = &pong;
+ if(count > vpt * tpb){
+ while(count > vpt * tpb){
+ reduce_kernel.set_arg(0, *input_buffer);
+ reduce_kernel.set_arg(1, uint_(0));
+ reduce_kernel.set_arg(2, uint_(count));
+ reduce_kernel.set_arg(3, *output_buffer);
+ reduce_kernel.set_arg(4, uint_(0));
+
+ size_t work_size = static_cast<size_t>(std::ceil(float(count) / vpt));
+ if(work_size % tpb != 0){
+ work_size += tpb - work_size % tpb;
+ }
+ queue.enqueue_1d_range_kernel(reduce_kernel, 0, work_size, tpb);
+
+ std::swap(input_buffer, output_buffer);
+ count = static_cast<size_t>(std::ceil(float(count) / vpt / tpb));
+ }
+ }
+
+ // final pass, reduce from ping/pong to result
+ reduce_kernel.set_arg(0, *input_buffer);
+ reduce_kernel.set_arg(1, uint_(0));
+ reduce_kernel.set_arg(2, uint_(count));
+ reduce_kernel.set_arg(3, result.get_buffer());
+ reduce_kernel.set_arg(4, uint_(result.get_index()));
+
+ queue.enqueue_1d_range_kernel(reduce_kernel, 0, tpb, tpb);
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_REDUCE_ON_GPU_HPP
diff --git a/boost/compute/algorithm/detail/scan.hpp b/boost/compute/algorithm/detail/scan.hpp
new file mode 100644
index 0000000000..154b6001be
--- /dev/null
+++ b/boost/compute/algorithm/detail/scan.hpp
@@ -0,0 +1,45 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_SCAN_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_SCAN_HPP
+
+#include <boost/compute/device.hpp>
+#include <boost/compute/algorithm/detail/scan_on_cpu.hpp>
+#include <boost/compute/algorithm/detail/scan_on_gpu.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator, class OutputIterator, class T, class BinaryOperator>
+inline OutputIterator scan(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ bool exclusive,
+ T init,
+ BinaryOperator op,
+ command_queue &queue)
+{
+ const device &device = queue.get_device();
+
+ if(device.type() & device::cpu){
+ return scan_on_cpu(first, last, result, exclusive, init, op, queue);
+ }
+ else {
+ return scan_on_gpu(first, last, result, exclusive, init, op, queue);
+ }
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_SCAN_HPP
diff --git a/boost/compute/algorithm/detail/scan_on_cpu.hpp b/boost/compute/algorithm/detail/scan_on_cpu.hpp
new file mode 100644
index 0000000000..6611c0ba3e
--- /dev/null
+++ b/boost/compute/algorithm/detail/scan_on_cpu.hpp
@@ -0,0 +1,103 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_SCAN_ON_CPU_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_SCAN_ON_CPU_HPP
+
+#include <iterator>
+
+#include <boost/compute/device.hpp>
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator, class OutputIterator, class T, class BinaryOperator>
+inline OutputIterator scan_on_cpu(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ bool exclusive,
+ T init,
+ BinaryOperator op,
+ command_queue &queue)
+{
+ if(first == last){
+ return result;
+ }
+
+ typedef typename
+ std::iterator_traits<InputIterator>::value_type input_type;
+ typedef typename
+ std::iterator_traits<OutputIterator>::value_type output_type;
+
+ const context &context = queue.get_context();
+
+ // create scan kernel
+ meta_kernel k("scan_on_cpu");
+
+ // Arguments
+ size_t n_arg = k.add_arg<ulong_>("n");
+ size_t init_arg = k.add_arg<output_type>("initial_value");
+
+ if(!exclusive){
+ k <<
+ k.decl<const ulong_>("start_idx") << " = 1;\n" <<
+ k.decl<output_type>("sum") << " = " << first[0] << ";\n" <<
+ result[0] << " = sum;\n";
+ }
+ else {
+ k <<
+ k.decl<const ulong_>("start_idx") << " = 0;\n" <<
+ k.decl<output_type>("sum") << " = initial_value;\n";
+ }
+
+ k <<
+ "for(ulong i = start_idx; i < n; i++){\n" <<
+ k.decl<const input_type>("x") << " = "
+ << first[k.var<ulong_>("i")] << ";\n";
+
+ if(exclusive){
+ k << result[k.var<ulong_>("i")] << " = sum;\n";
+ }
+
+ k << " sum = "
+ << op(k.var<output_type>("sum"), k.var<output_type>("x"))
+ << ";\n";
+
+ if(!exclusive){
+ k << result[k.var<ulong_>("i")] << " = sum;\n";
+ }
+
+ k << "}\n";
+
+ // compile scan kernel
+ kernel scan_kernel = k.compile(context);
+
+ // setup kernel arguments
+ size_t n = detail::iterator_range_size(first, last);
+ scan_kernel.set_arg<ulong_>(n_arg, n);
+ scan_kernel.set_arg<output_type>(init_arg, static_cast<output_type>(init));
+
+ // execute the kernel
+ queue.enqueue_1d_range_kernel(scan_kernel, 0, 1, 1);
+
+ // return iterator pointing to the end of the result range
+ return result + n;
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_SCAN_ON_CPU_HPP
diff --git a/boost/compute/algorithm/detail/scan_on_gpu.hpp b/boost/compute/algorithm/detail/scan_on_gpu.hpp
new file mode 100644
index 0000000000..07c6d6d3c0
--- /dev/null
+++ b/boost/compute/algorithm/detail/scan_on_gpu.hpp
@@ -0,0 +1,331 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_SCAN_ON_GPU_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_SCAN_ON_GPU_HPP
+
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/detail/scan_on_cpu.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/memory/local_buffer.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator, class OutputIterator, class BinaryOperator>
+class local_scan_kernel : public meta_kernel
+{
+public:
+ local_scan_kernel(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ bool exclusive,
+ BinaryOperator op)
+ : meta_kernel("local_scan")
+ {
+ typedef typename std::iterator_traits<InputIterator>::value_type T;
+
+ (void) last;
+
+ bool checked = true;
+
+ m_block_sums_arg = add_arg<T *>(memory_object::global_memory, "block_sums");
+ m_scratch_arg = add_arg<T *>(memory_object::local_memory, "scratch");
+ m_block_size_arg = add_arg<const cl_uint>("block_size");
+ m_count_arg = add_arg<const cl_uint>("count");
+ m_init_value_arg = add_arg<const T>("init");
+
+ // work-item parameters
+ *this <<
+ "const uint gid = get_global_id(0);\n" <<
+ "const uint lid = get_local_id(0);\n";
+
+ // check against data size
+ if(checked){
+ *this <<
+ "if(gid < count){\n";
+ }
+
+ // copy values from input to local memory
+ if(exclusive){
+ *this <<
+ decl<const T>("local_init") << "= (gid == 0) ? init : 0;\n" <<
+ "if(lid == 0){ scratch[lid] = local_init; }\n" <<
+ "else { scratch[lid] = " << first[expr<cl_uint>("gid-1")] << "; }\n";
+ }
+ else{
+ *this <<
+ "scratch[lid] = " << first[expr<cl_uint>("gid")] << ";\n";
+ }
+
+ if(checked){
+ *this <<
+ "}\n"
+ "else {\n" <<
+ " scratch[lid] = 0;\n" <<
+ "}\n";
+ }
+
+ // wait for all threads to read from input
+ *this <<
+ "barrier(CLK_LOCAL_MEM_FENCE);\n";
+
+ // perform scan
+ *this <<
+ "for(uint i = 1; i < block_size; i <<= 1){\n" <<
+ " " << decl<const T>("x") << " = lid >= i ? scratch[lid-i] : 0;\n" <<
+ " barrier(CLK_LOCAL_MEM_FENCE);\n" <<
+ " if(lid >= i){\n" <<
+ " scratch[lid] = " << op(var<T>("scratch[lid]"), var<T>("x")) << ";\n" <<
+ " }\n" <<
+ " barrier(CLK_LOCAL_MEM_FENCE);\n" <<
+ "}\n";
+
+ // copy results to output
+ if(checked){
+ *this <<
+ "if(gid < count){\n";
+ }
+
+ *this <<
+ result[expr<cl_uint>("gid")] << " = scratch[lid];\n";
+
+ if(checked){
+ *this << "}\n";
+ }
+
+ // store sum for the block
+ if(exclusive){
+ *this <<
+ "if(lid == block_size - 1){\n" <<
+ " block_sums[get_group_id(0)] = " <<
+ op(first[expr<cl_uint>("gid")], var<T>("scratch[lid]")) <<
+ ";\n" <<
+ "}\n";
+ }
+ else {
+ *this <<
+ "if(lid == block_size - 1){\n" <<
+ " block_sums[get_group_id(0)] = scratch[lid];\n" <<
+ "}\n";
+ }
+ }
+
+ size_t m_block_sums_arg;
+ size_t m_scratch_arg;
+ size_t m_block_size_arg;
+ size_t m_count_arg;
+ size_t m_init_value_arg;
+};
+
+template<class T, class BinaryOperator>
+class write_scanned_output_kernel : public meta_kernel
+{
+public:
+ write_scanned_output_kernel(BinaryOperator op)
+ : meta_kernel("write_scanned_output")
+ {
+ bool checked = true;
+
+ m_output_arg = add_arg<T *>(memory_object::global_memory, "output");
+ m_block_sums_arg = add_arg<const T *>(memory_object::global_memory, "block_sums");
+ m_count_arg = add_arg<const cl_uint>("count");
+
+ // work-item parameters
+ *this <<
+ "const uint gid = get_global_id(0);\n" <<
+ "const uint block_id = get_group_id(0);\n";
+
+ // check against data size
+ if(checked){
+ *this << "if(gid < count){\n";
+ }
+
+ // write output
+ *this <<
+ "output[gid] = " <<
+ op(var<T>("block_sums[block_id]"), var<T>("output[gid] ")) << ";\n";
+
+ if(checked){
+ *this << "}\n";
+ }
+ }
+
+ size_t m_output_arg;
+ size_t m_block_sums_arg;
+ size_t m_count_arg;
+};
+
+template<class InputIterator>
+inline size_t pick_scan_block_size(InputIterator first, InputIterator last)
+{
+ size_t count = iterator_range_size(first, last);
+
+ if(count == 0) { return 0; }
+ else if(count <= 1) { return 1; }
+ else if(count <= 2) { return 2; }
+ else if(count <= 4) { return 4; }
+ else if(count <= 8) { return 8; }
+ else if(count <= 16) { return 16; }
+ else if(count <= 32) { return 32; }
+ else if(count <= 64) { return 64; }
+ else if(count <= 128) { return 128; }
+ else { return 256; }
+}
+
+template<class InputIterator, class OutputIterator, class T, class BinaryOperator>
+inline OutputIterator scan_impl(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ bool exclusive,
+ T init,
+ BinaryOperator op,
+ command_queue &queue)
+{
+ typedef typename
+ std::iterator_traits<InputIterator>::value_type
+ input_type;
+ typedef typename
+ std::iterator_traits<InputIterator>::difference_type
+ difference_type;
+ typedef typename
+ std::iterator_traits<OutputIterator>::value_type
+ output_type;
+
+ const context &context = queue.get_context();
+ const size_t count = detail::iterator_range_size(first, last);
+
+ size_t block_size = pick_scan_block_size(first, last);
+ size_t block_count = count / block_size;
+
+ if(block_count * block_size < count){
+ block_count++;
+ }
+
+ ::boost::compute::vector<input_type> block_sums(block_count, context);
+
+ // zero block sums
+ input_type zero;
+ std::memset(&zero, 0, sizeof(input_type));
+ ::boost::compute::fill(block_sums.begin(), block_sums.end(), zero, queue);
+
+ // local scan
+ local_scan_kernel<InputIterator, OutputIterator, BinaryOperator>
+ local_scan_kernel(first, last, result, exclusive, op);
+
+ ::boost::compute::kernel kernel = local_scan_kernel.compile(context);
+ kernel.set_arg(local_scan_kernel.m_scratch_arg, local_buffer<input_type>(block_size));
+ kernel.set_arg(local_scan_kernel.m_block_sums_arg, block_sums);
+ kernel.set_arg(local_scan_kernel.m_block_size_arg, static_cast<cl_uint>(block_size));
+ kernel.set_arg(local_scan_kernel.m_count_arg, static_cast<cl_uint>(count));
+ kernel.set_arg(local_scan_kernel.m_init_value_arg, static_cast<output_type>(init));
+
+ queue.enqueue_1d_range_kernel(kernel,
+ 0,
+ block_count * block_size,
+ block_size);
+
+ // inclusive scan block sums
+ if(block_count > 1){
+ scan_impl(block_sums.begin(),
+ block_sums.end(),
+ block_sums.begin(),
+ false,
+ init,
+ op,
+ queue
+ );
+ }
+
+ // add block sums to each block
+ if(block_count > 1){
+ write_scanned_output_kernel<input_type, BinaryOperator>
+ write_output_kernel(op);
+ kernel = write_output_kernel.compile(context);
+ kernel.set_arg(write_output_kernel.m_output_arg, result.get_buffer());
+ kernel.set_arg(write_output_kernel.m_block_sums_arg, block_sums);
+ kernel.set_arg(write_output_kernel.m_count_arg, static_cast<cl_uint>(count));
+
+ queue.enqueue_1d_range_kernel(kernel,
+ block_size,
+ block_count * block_size,
+ block_size);
+ }
+
+ return result + static_cast<difference_type>(count);
+}
+
+template<class InputIterator, class OutputIterator, class T, class BinaryOperator>
+inline OutputIterator dispatch_scan(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ bool exclusive,
+ T init,
+ BinaryOperator op,
+ command_queue &queue)
+{
+ return scan_impl(first, last, result, exclusive, init, op, queue);
+}
+
+template<class InputIterator, class T, class BinaryOperator>
+inline InputIterator dispatch_scan(InputIterator first,
+ InputIterator last,
+ InputIterator result,
+ bool exclusive,
+ T init,
+ BinaryOperator op,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ if(first == result){
+ // scan input in-place
+ const context &context = queue.get_context();
+
+ // make a temporary copy the input
+ size_t count = iterator_range_size(first, last);
+ vector<value_type> tmp(count, context);
+ copy(first, last, tmp.begin(), queue);
+
+ // scan from temporary values
+ return scan_impl(tmp.begin(), tmp.end(), first, exclusive, init, op, queue);
+ }
+ else {
+ // scan input to output
+ return scan_impl(first, last, result, exclusive, init, op, queue);
+ }
+}
+
+template<class InputIterator, class OutputIterator, class T, class BinaryOperator>
+inline OutputIterator scan_on_gpu(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ bool exclusive,
+ T init,
+ BinaryOperator op,
+ command_queue &queue)
+{
+ if(first == last){
+ return result;
+ }
+
+ return dispatch_scan(first, last, result, exclusive, init, op, queue);
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_SCAN_ON_GPU_HPP
diff --git a/boost/compute/algorithm/detail/search_all.hpp b/boost/compute/algorithm/detail/search_all.hpp
new file mode 100644
index 0000000000..a874bcdebe
--- /dev/null
+++ b/boost/compute/algorithm/detail/search_all.hpp
@@ -0,0 +1,86 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_SEARCH_ALL_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_SEARCH_ALL_HPP
+
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/system.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+///
+/// \brief Search kernel class
+///
+/// Subclass of meta_kernel which is capable of performing pattern matching
+///
+template<class PatternIterator, class TextIterator, class OutputIterator>
+class search_kernel : public meta_kernel
+{
+public:
+ search_kernel() : meta_kernel("search")
+ {}
+
+ void set_range(PatternIterator p_first,
+ PatternIterator p_last,
+ TextIterator t_first,
+ TextIterator t_last,
+ OutputIterator result)
+ {
+ m_p_count = iterator_range_size(p_first, p_last);
+ m_p_count_arg = add_arg<uint_>("p_count");
+
+ m_count = iterator_range_size(t_first, t_last);
+ m_count = m_count + 1 - m_p_count;
+
+ *this <<
+ "uint i = get_global_id(0);\n" <<
+ "uint i1 = i;\n" <<
+ "uint j;\n" <<
+ "for(j = 0; j<p_count; j++,i++)\n" <<
+ "{\n" <<
+ " if(" << p_first[expr<uint_>("j")] << " != " <<
+ t_first[expr<uint_>("i")] << ")\n" <<
+ " j = p_count + 1;\n" <<
+ "}\n" <<
+ "if(j == p_count)\n" <<
+ result[expr<uint_>("i1")] << " = 1;\n" <<
+ "else\n" <<
+ result[expr<uint_>("i1")] << " = 0;\n";
+ }
+
+ event exec(command_queue &queue)
+ {
+ if(m_count == 0) {
+ return event();
+ }
+
+ set_arg(m_p_count_arg, uint_(m_p_count));
+
+ return exec_1d(queue, 0, m_count);
+ }
+
+private:
+ size_t m_p_count;
+ size_t m_p_count_arg;
+ size_t m_count;
+};
+
+} //end detail namespace
+} //end compute namespace
+} //end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_SEARCH_ALL_HPP
diff --git a/boost/compute/algorithm/detail/serial_accumulate.hpp b/boost/compute/algorithm/detail/serial_accumulate.hpp
new file mode 100644
index 0000000000..84f9910122
--- /dev/null
+++ b/boost/compute/algorithm/detail/serial_accumulate.hpp
@@ -0,0 +1,56 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_SERIAL_ACCUMULATE_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_SERIAL_ACCUMULATE_HPP
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator, class OutputIterator, class T, class BinaryFunction>
+inline void serial_accumulate(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ T init,
+ BinaryFunction function,
+ command_queue &queue)
+{
+ const context &context = queue.get_context();
+ size_t count = detail::iterator_range_size(first, last);
+
+ meta_kernel k("serial_accumulate");
+ size_t init_arg = k.add_arg<T>("init");
+ size_t count_arg = k.add_arg<cl_uint>("count");
+
+ k <<
+ k.decl<T>("result") << " = init;\n" <<
+ "for(uint i = 0; i < count; i++)\n" <<
+ " result = " << function(k.var<T>("result"),
+ first[k.var<cl_uint>("i")]) << ";\n" <<
+ result[0] << " = result;\n";
+
+ kernel kernel = k.compile(context);
+
+ kernel.set_arg(init_arg, init);
+ kernel.set_arg(count_arg, static_cast<cl_uint>(count));
+
+ queue.enqueue_task(kernel);
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_SERIAL_ACCUMULATE_HPP
diff --git a/boost/compute/algorithm/detail/serial_count_if.hpp b/boost/compute/algorithm/detail/serial_count_if.hpp
new file mode 100644
index 0000000000..be6794c426
--- /dev/null
+++ b/boost/compute/algorithm/detail/serial_count_if.hpp
@@ -0,0 +1,68 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_SERIAL_COUNT_IF_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_SERIAL_COUNT_IF_HPP
+
+#include <iterator>
+
+#include <boost/compute/container/detail/scalar.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+// counts values that match the predicate using a single thread
+template<class InputIterator, class Predicate>
+inline size_t serial_count_if(InputIterator first,
+ InputIterator last,
+ Predicate predicate,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ const context &context = queue.get_context();
+ size_t size = iterator_range_size(first, last);
+
+ meta_kernel k("serial_count_if");
+ k.add_set_arg("size", static_cast<uint_>(size));
+ size_t result_arg = k.add_arg<uint_ *>(memory_object::global_memory, "result");
+
+ k <<
+ "uint count = 0;\n" <<
+ "for(uint i = 0; i < size; i++){\n" <<
+ k.decl<const value_type>("value") << "="
+ << first[k.var<uint_>("i")] << ";\n" <<
+ "if(" << predicate(k.var<const value_type>("value")) << "){\n" <<
+ "count++;\n" <<
+ "}\n"
+ "}\n"
+ "*result = count;\n";
+
+ kernel kernel = k.compile(context);
+
+ // setup result buffer
+ scalar<uint_> result(context);
+ kernel.set_arg(result_arg, result.get_buffer());
+
+ // run kernel
+ queue.enqueue_task(kernel);
+
+ // read index
+ return result.read(queue);
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_SERIAL_COUNT_IF_HPP
diff --git a/boost/compute/algorithm/detail/serial_find_extrema.hpp b/boost/compute/algorithm/detail/serial_find_extrema.hpp
new file mode 100644
index 0000000000..8407c88129
--- /dev/null
+++ b/boost/compute/algorithm/detail/serial_find_extrema.hpp
@@ -0,0 +1,87 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_SERIAL_FIND_EXTREMA_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_SERIAL_FIND_EXTREMA_HPP
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/types/fundamental.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/container/detail/scalar.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator, class Compare>
+inline InputIterator serial_find_extrema(InputIterator first,
+ InputIterator last,
+ Compare compare,
+ const bool find_minimum,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+ typedef typename std::iterator_traits<InputIterator>::difference_type difference_type;
+
+ const context &context = queue.get_context();
+
+ meta_kernel k("serial_find_extrema");
+
+ k <<
+ k.decl<value_type>("value") << " = " << first[k.expr<uint_>("0")] << ";\n" <<
+ k.decl<uint_>("value_index") << " = 0;\n" <<
+ "for(uint i = 1; i < size; i++){\n" <<
+ " " << k.decl<value_type>("candidate") << "="
+ << first[k.expr<uint_>("i")] << ";\n" <<
+
+ "#ifndef BOOST_COMPUTE_FIND_MAXIMUM\n" <<
+ " if(" << compare(k.var<value_type>("candidate"),
+ k.var<value_type>("value")) << "){\n" <<
+ "#else\n" <<
+ " if(" << compare(k.var<value_type>("value"),
+ k.var<value_type>("candidate")) << "){\n" <<
+ "#endif\n" <<
+
+ " value = candidate;\n" <<
+ " value_index = i;\n" <<
+ " }\n" <<
+ "}\n" <<
+ "*index = value_index;\n";
+
+ size_t index_arg_index = k.add_arg<uint_ *>(memory_object::global_memory, "index");
+ size_t size_arg_index = k.add_arg<uint_>("size");
+
+ std::string options;
+ if(!find_minimum){
+ options = "-DBOOST_COMPUTE_FIND_MAXIMUM";
+ }
+ kernel kernel = k.compile(context, options);
+
+ // setup index buffer
+ scalar<uint_> index(context);
+ kernel.set_arg(index_arg_index, index.get_buffer());
+
+ // setup count
+ size_t count = iterator_range_size(first, last);
+ kernel.set_arg(size_arg_index, static_cast<uint_>(count));
+
+ // run kernel
+ queue.enqueue_task(kernel);
+
+ // read index and return iterator
+ return first + static_cast<difference_type>(index.read(queue));
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_SERIAL_FIND_EXTREMA_HPP
diff --git a/boost/compute/algorithm/detail/serial_merge.hpp b/boost/compute/algorithm/detail/serial_merge.hpp
new file mode 100644
index 0000000000..85e38f704c
--- /dev/null
+++ b/boost/compute/algorithm/detail/serial_merge.hpp
@@ -0,0 +1,97 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_SERIAL_MERGE_HPP
+#define BOOST_COMPUTE_ALGORITHM_SERIAL_MERGE_HPP
+
+#include <iterator>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator1,
+ class InputIterator2,
+ class OutputIterator,
+ class Compare>
+inline OutputIterator serial_merge(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator result,
+ Compare comp,
+ command_queue &queue)
+{
+ typedef typename
+ std::iterator_traits<InputIterator1>::value_type
+ input_type1;
+ typedef typename
+ std::iterator_traits<InputIterator2>::value_type
+ input_type2;
+ typedef typename
+ std::iterator_traits<OutputIterator>::difference_type
+ result_difference_type;
+
+ std::ptrdiff_t size1 = std::distance(first1, last1);
+ std::ptrdiff_t size2 = std::distance(first2, last2);
+
+ meta_kernel k("serial_merge");
+ k.add_set_arg<uint_>("size1", static_cast<uint_>(size1));
+ k.add_set_arg<uint_>("size2", static_cast<uint_>(size2));
+
+ k <<
+ "uint i = 0;\n" << // index in result range
+ "uint j = 0;\n" << // index in first input range
+ "uint k = 0;\n" << // index in second input range
+
+ // fetch initial values from each range
+ k.decl<input_type1>("j_value") << " = " << first1[0] << ";\n" <<
+ k.decl<input_type2>("k_value") << " = " << first2[0] << ";\n" <<
+
+ // merge values from both input ranges to the result range
+ "while(j < size1 && k < size2){\n" <<
+ " if(" << comp(k.var<input_type1>("j_value"),
+ k.var<input_type2>("k_value")) << "){\n" <<
+ " " << result[k.var<uint_>("i++")] << " = j_value;\n" <<
+ " j_value = " << first1[k.var<uint_>("++j")] << ";\n" <<
+ " }\n" <<
+ " else{\n"
+ " " << result[k.var<uint_>("i++")] << " = k_value;\n"
+ " k_value = " << first2[k.var<uint_>("++k")] << ";\n" <<
+ " }\n"
+ "}\n"
+
+ // copy any remaining values from first range
+ "while(j < size1){\n" <<
+ result[k.var<uint_>("i++")] << " = " <<
+ first1[k.var<uint_>("j++")] << ";\n" <<
+ "}\n"
+
+ // copy any remaining values from second range
+ "while(k < size2){\n" <<
+ result[k.var<uint_>("i++")] << " = " <<
+ first2[k.var<uint_>("k++")] << ";\n" <<
+ "}\n";
+
+ // run kernel
+ k.exec(queue);
+
+ return result + static_cast<result_difference_type>(size1 + size2);
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_SERIAL_MERGE_HPP
diff --git a/boost/compute/algorithm/detail/serial_reduce.hpp b/boost/compute/algorithm/detail/serial_reduce.hpp
new file mode 100644
index 0000000000..53aaf140fe
--- /dev/null
+++ b/boost/compute/algorithm/detail/serial_reduce.hpp
@@ -0,0 +1,62 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_SERIAL_REDUCE_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_SERIAL_REDUCE_HPP
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/type_traits/result_of.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator, class OutputIterator, class BinaryFunction>
+inline void serial_reduce(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ BinaryFunction function,
+ command_queue &queue)
+{
+ typedef typename
+ std::iterator_traits<InputIterator>::value_type T;
+ typedef typename
+ ::boost::compute::result_of<BinaryFunction(T, T)>::type result_type;
+
+ const context &context = queue.get_context();
+ size_t count = detail::iterator_range_size(first, last);
+ if(count == 0){
+ return;
+ }
+
+ meta_kernel k("serial_reduce");
+ size_t count_arg = k.add_arg<cl_uint>("count");
+
+ k <<
+ k.decl<result_type>("result") << " = " << first[0] << ";\n" <<
+ "for(uint i = 1; i < count; i++)\n" <<
+ " result = " << function(k.var<T>("result"),
+ first[k.var<uint_>("i")]) << ";\n" <<
+ result[0] << " = result;\n";
+
+ kernel kernel = k.compile(context);
+
+ kernel.set_arg(count_arg, static_cast<uint_>(count));
+
+ queue.enqueue_task(kernel);
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_SERIAL_REDUCE_HPP
diff --git a/boost/compute/algorithm/detail/serial_reduce_by_key.hpp b/boost/compute/algorithm/detail/serial_reduce_by_key.hpp
new file mode 100644
index 0000000000..f9bda8e476
--- /dev/null
+++ b/boost/compute/algorithm/detail/serial_reduce_by_key.hpp
@@ -0,0 +1,108 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2015 Jakub Szuppe <j.szuppe@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_SERIAL_REDUCE_BY_KEY_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_SERIAL_REDUCE_BY_KEY_HPP
+
+#include <iterator>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/container/detail/scalar.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/type_traits/result_of.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputKeyIterator, class InputValueIterator,
+ class OutputKeyIterator, class OutputValueIterator,
+ class BinaryFunction, class BinaryPredicate>
+inline size_t serial_reduce_by_key(InputKeyIterator keys_first,
+ InputKeyIterator keys_last,
+ InputValueIterator values_first,
+ OutputKeyIterator keys_result,
+ OutputValueIterator values_result,
+ BinaryFunction function,
+ BinaryPredicate predicate,
+ command_queue &queue)
+{
+ typedef typename
+ std::iterator_traits<InputValueIterator>::value_type value_type;
+ typedef typename
+ std::iterator_traits<InputKeyIterator>::value_type key_type;
+ typedef typename
+ ::boost::compute::result_of<BinaryFunction(value_type, value_type)>::type result_type;
+
+ const context &context = queue.get_context();
+ size_t count = detail::iterator_range_size(keys_first, keys_last);
+ if(count < 1){
+ return count;
+ }
+
+ meta_kernel k("serial_reduce_by_key");
+ size_t count_arg = k.add_arg<uint_>("count");
+ size_t result_size_arg = k.add_arg<uint_ *>(memory_object::global_memory,
+ "result_size");
+
+ convert<result_type> to_result_type;
+
+ k <<
+ k.decl<result_type>("result") <<
+ " = " << to_result_type(values_first[0]) << ";\n" <<
+ k.decl<key_type>("previous_key") << " = " << keys_first[0] << ";\n" <<
+ k.decl<result_type>("value") << ";\n" <<
+ k.decl<key_type>("key") << ";\n" <<
+
+ k.decl<uint_>("size") << " = 1;\n" <<
+
+ keys_result[0] << " = previous_key;\n" <<
+ values_result[0] << " = result;\n" <<
+
+ "for(ulong i = 1; i < count; i++) {\n" <<
+ " value = " << to_result_type(values_first[k.var<uint_>("i")]) << ";\n" <<
+ " key = " << keys_first[k.var<uint_>("i")] << ";\n" <<
+ " if (" << predicate(k.var<key_type>("previous_key"),
+ k.var<key_type>("key")) << ") {\n" <<
+
+ " result = " << function(k.var<result_type>("result"),
+ k.var<result_type>("value")) << ";\n" <<
+ " }\n " <<
+ " else { \n" <<
+ keys_result[k.var<uint_>("size - 1")] << " = previous_key;\n" <<
+ values_result[k.var<uint_>("size - 1")] << " = result;\n" <<
+ " result = value;\n" <<
+ " size++;\n" <<
+ " } \n" <<
+ " previous_key = key;\n" <<
+ "}\n" <<
+ keys_result[k.var<uint_>("size - 1")] << " = previous_key;\n" <<
+ values_result[k.var<uint_>("size - 1")] << " = result;\n" <<
+ "*result_size = size;";
+
+ kernel kernel = k.compile(context);
+
+ scalar<uint_> result_size(context);
+ kernel.set_arg(result_size_arg, result_size.get_buffer());
+ kernel.set_arg(count_arg, static_cast<uint_>(count));
+
+ queue.enqueue_task(kernel);
+
+ return static_cast<size_t>(result_size.read(queue));
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_SERIAL_REDUCE_BY_KEY_HPP
diff --git a/boost/compute/algorithm/equal.hpp b/boost/compute/algorithm/equal.hpp
new file mode 100644
index 0000000000..35d0c5f0ea
--- /dev/null
+++ b/boost/compute/algorithm/equal.hpp
@@ -0,0 +1,53 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_EQUAL_HPP
+#define BOOST_COMPUTE_ALGORITHM_EQUAL_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/mismatch.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns \c true if the range [\p first1, \p last1) and the range
+/// beginning at \p first2 are equal.
+template<class InputIterator1, class InputIterator2>
+inline bool equal(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ command_queue &queue = system::default_queue())
+{
+ return ::boost::compute::mismatch(first1,
+ last1,
+ first2,
+ queue).first == last1;
+}
+
+/// \overload
+template<class InputIterator1, class InputIterator2>
+inline bool equal(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ command_queue &queue = system::default_queue())
+{
+ if(std::distance(first1, last1) != std::distance(first2, last2)){
+ return false;
+ }
+
+ return ::boost::compute::equal(first1, last1, first2, queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_EQUAL_HPP
diff --git a/boost/compute/algorithm/equal_range.hpp b/boost/compute/algorithm/equal_range.hpp
new file mode 100644
index 0000000000..fd82177324
--- /dev/null
+++ b/boost/compute/algorithm/equal_range.hpp
@@ -0,0 +1,42 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_EQUAL_RANGE_HPP
+#define BOOST_COMPUTE_ALGORITHM_EQUAL_RANGE_HPP
+
+#include <utility>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/lower_bound.hpp>
+#include <boost/compute/algorithm/upper_bound.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns a pair of iterators containing the range of values equal
+/// to \p value in the sorted range [\p first, \p last).
+template<class InputIterator, class T>
+inline std::pair<InputIterator, InputIterator>
+equal_range(InputIterator first,
+ InputIterator last,
+ const T &value,
+ command_queue &queue = system::default_queue())
+{
+ return std::make_pair(
+ ::boost::compute::lower_bound(first, last, value, queue),
+ ::boost::compute::upper_bound(first, last, value, queue)
+ );
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_EQUAL_RANGE_HPP
diff --git a/boost/compute/algorithm/exclusive_scan.hpp b/boost/compute/algorithm/exclusive_scan.hpp
new file mode 100644
index 0000000000..205d3de658
--- /dev/null
+++ b/boost/compute/algorithm/exclusive_scan.hpp
@@ -0,0 +1,96 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_EXCLUSIVE_SCAN_HPP
+#define BOOST_COMPUTE_ALGORITHM_EXCLUSIVE_SCAN_HPP
+
+#include <boost/compute/functional.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/detail/scan.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Performs an exclusive scan of the elements in the range [\p first, \p last)
+/// and stores the results in the range beginning at \p result.
+///
+/// Each element in the output is assigned to the sum of all the previous
+/// values in the input.
+///
+/// \param first first element in the range to scan
+/// \param last last element in the range to scan
+/// \param result first element in the result range
+/// \param init value used to initialize the scan sequence
+/// \param binary_op associative binary operator
+/// \param queue command queue to perform the operation
+///
+/// \return \c OutputIterator to the end of the result range
+///
+/// The default operation is to add the elements up.
+///
+/// \snippet test/test_scan.cpp exclusive_scan_int
+///
+/// But different associative operation can be specified as \p binary_op
+/// instead (e.g., multiplication, maximum, minimum). Also value used to
+/// initialized the scan sequence can be specified.
+///
+/// \snippet test/test_scan.cpp exclusive_scan_int_multiplies
+///
+/// \see inclusive_scan()
+template<class InputIterator, class OutputIterator, class T, class BinaryOperator>
+inline OutputIterator
+exclusive_scan(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ T init,
+ BinaryOperator binary_op,
+ command_queue &queue = system::default_queue())
+{
+ return detail::scan(first, last, result, true, init, binary_op, queue);
+}
+
+/// \overload
+template<class InputIterator, class OutputIterator, class T>
+inline OutputIterator
+exclusive_scan(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ T init,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename
+ std::iterator_traits<OutputIterator>::value_type output_type;
+
+ return detail::scan(first, last, result, true,
+ init, boost::compute::plus<output_type>(),
+ queue);
+}
+
+/// \overload
+template<class InputIterator, class OutputIterator>
+inline OutputIterator
+exclusive_scan(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename
+ std::iterator_traits<OutputIterator>::value_type output_type;
+
+ return detail::scan(first, last, result, true,
+ output_type(0), boost::compute::plus<output_type>(),
+ queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_EXCLUSIVE_SCAN_HPP
diff --git a/boost/compute/algorithm/fill.hpp b/boost/compute/algorithm/fill.hpp
new file mode 100644
index 0000000000..c711f46b94
--- /dev/null
+++ b/boost/compute/algorithm/fill.hpp
@@ -0,0 +1,306 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_FILL_HPP
+#define BOOST_COMPUTE_ALGORITHM_FILL_HPP
+
+#include <iterator>
+
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/contains.hpp>
+#include <boost/utility/enable_if.hpp>
+
+#include <boost/compute/cl.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/async/future.hpp>
+#include <boost/compute/iterator/constant_iterator.hpp>
+#include <boost/compute/iterator/discard_iterator.hpp>
+#include <boost/compute/detail/is_buffer_iterator.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+namespace mpl = boost::mpl;
+
+// fills the range [first, first + count) with value using copy()
+template<class BufferIterator, class T>
+inline void fill_with_copy(BufferIterator first,
+ size_t count,
+ const T &value,
+ command_queue &queue)
+{
+ ::boost::compute::copy(
+ ::boost::compute::make_constant_iterator(value, 0),
+ ::boost::compute::make_constant_iterator(value, count),
+ first,
+ queue
+ );
+}
+
+// fills the range [first, first + count) with value using copy_async()
+template<class BufferIterator, class T>
+inline future<void> fill_async_with_copy(BufferIterator first,
+ size_t count,
+ const T &value,
+ command_queue &queue)
+{
+ return ::boost::compute::copy_async(
+ ::boost::compute::make_constant_iterator(value, 0),
+ ::boost::compute::make_constant_iterator(value, count),
+ first,
+ queue
+ );
+}
+
+#if defined(CL_VERSION_1_2)
+
+// meta-function returing true if Iterator points to a range of values
+// that can be filled using clEnqueueFillBuffer(). to meet this criteria
+// it must have a buffer accessible through iter.get_buffer() and the
+// size of its value_type must by in {1, 2, 4, 8, 16, 32, 64, 128}.
+template<class Iterator>
+struct is_valid_fill_buffer_iterator :
+ public mpl::and_<
+ is_buffer_iterator<Iterator>,
+ mpl::contains<
+ mpl::vector<
+ mpl::int_<1>,
+ mpl::int_<2>,
+ mpl::int_<4>,
+ mpl::int_<8>,
+ mpl::int_<16>,
+ mpl::int_<32>,
+ mpl::int_<64>,
+ mpl::int_<128>
+ >,
+ mpl::int_<
+ sizeof(typename std::iterator_traits<Iterator>::value_type)
+ >
+ >
+ >::type { };
+
+template<>
+struct is_valid_fill_buffer_iterator<discard_iterator> : public boost::false_type {};
+
+// specialization which uses clEnqueueFillBuffer for buffer iterators
+template<class BufferIterator, class T>
+inline void
+dispatch_fill(BufferIterator first,
+ size_t count,
+ const T &value,
+ command_queue &queue,
+ typename boost::enable_if<
+ is_valid_fill_buffer_iterator<BufferIterator>
+ >::type* = 0)
+{
+ typedef typename std::iterator_traits<BufferIterator>::value_type value_type;
+
+ if(count == 0){
+ // nothing to do
+ return;
+ }
+
+ // check if the device supports OpenCL 1.2 (required for enqueue_fill_buffer)
+ if(!queue.check_device_version(1, 2)){
+ return fill_with_copy(first, count, value, queue);
+ }
+
+ value_type pattern = static_cast<value_type>(value);
+ size_t offset = static_cast<size_t>(first.get_index());
+
+ if(count == 1){
+ // use clEnqueueWriteBuffer() directly when writing a single value
+ // to the device buffer. this is potentially more efficient and also
+ // works around a bug in the intel opencl driver.
+ queue.enqueue_write_buffer(
+ first.get_buffer(),
+ offset * sizeof(value_type),
+ sizeof(value_type),
+ &pattern
+ );
+ }
+ else {
+ queue.enqueue_fill_buffer(
+ first.get_buffer(),
+ &pattern,
+ sizeof(value_type),
+ offset * sizeof(value_type),
+ count * sizeof(value_type)
+ );
+ }
+}
+
+template<class BufferIterator, class T>
+inline future<void>
+dispatch_fill_async(BufferIterator first,
+ size_t count,
+ const T &value,
+ command_queue &queue,
+ typename boost::enable_if<
+ is_valid_fill_buffer_iterator<BufferIterator>
+ >::type* = 0)
+{
+ typedef typename std::iterator_traits<BufferIterator>::value_type value_type;
+
+ // check if the device supports OpenCL 1.2 (required for enqueue_fill_buffer)
+ if(!queue.check_device_version(1, 2)){
+ return fill_async_with_copy(first, count, value, queue);
+ }
+
+ value_type pattern = static_cast<value_type>(value);
+ size_t offset = static_cast<size_t>(first.get_index());
+
+ event event_ =
+ queue.enqueue_fill_buffer(first.get_buffer(),
+ &pattern,
+ sizeof(value_type),
+ offset * sizeof(value_type),
+ count * sizeof(value_type));
+
+ return future<void>(event_);
+}
+
+#ifdef CL_VERSION_2_0
+// specializations for svm_ptr<T>
+template<class T>
+inline void dispatch_fill(svm_ptr<T> first,
+ size_t count,
+ const T &value,
+ command_queue &queue)
+{
+ if(count == 0){
+ return;
+ }
+
+ queue.enqueue_svm_fill(
+ first.get(), &value, sizeof(T), count * sizeof(T)
+ );
+}
+
+template<class T>
+inline future<void> dispatch_fill_async(svm_ptr<T> first,
+ size_t count,
+ const T &value,
+ command_queue &queue)
+{
+ if(count == 0){
+ return future<void>();
+ }
+
+ event event_ = queue.enqueue_svm_fill(
+ first.get(), &value, sizeof(T), count * sizeof(T)
+ );
+
+ return future<void>(event_);
+}
+#endif // CL_VERSION_2_0
+
+// default implementations
+template<class BufferIterator, class T>
+inline void
+dispatch_fill(BufferIterator first,
+ size_t count,
+ const T &value,
+ command_queue &queue,
+ typename boost::disable_if<
+ is_valid_fill_buffer_iterator<BufferIterator>
+ >::type* = 0)
+{
+ fill_with_copy(first, count, value, queue);
+}
+
+template<class BufferIterator, class T>
+inline future<void>
+dispatch_fill_async(BufferIterator first,
+ size_t count,
+ const T &value,
+ command_queue &queue,
+ typename boost::disable_if<
+ is_valid_fill_buffer_iterator<BufferIterator>
+ >::type* = 0)
+{
+ return fill_async_with_copy(first, count, value, queue);
+}
+#else
+template<class BufferIterator, class T>
+inline void dispatch_fill(BufferIterator first,
+ size_t count,
+ const T &value,
+ command_queue &queue)
+{
+ fill_with_copy(first, count, value, queue);
+}
+
+template<class BufferIterator, class T>
+inline future<void> dispatch_fill_async(BufferIterator first,
+ size_t count,
+ const T &value,
+ command_queue &queue)
+{
+ return fill_async_with_copy(first, count, value, queue);
+}
+#endif // !defined(CL_VERSION_1_2)
+
+} // end detail namespace
+
+/// Fills the range [\p first, \p last) with \p value.
+///
+/// \param first first element in the range to fill
+/// \param last last element in the range to fill
+/// \param value value to copy to each element
+/// \param queue command queue to perform the operation
+///
+/// For example, to fill a vector on the device with sevens:
+/// \code
+/// // vector on the device
+/// boost::compute::vector<int> vec(10, context);
+///
+/// // fill vector with sevens
+/// boost::compute::fill(vec.begin(), vec.end(), 7, queue);
+/// \endcode
+///
+/// \see boost::compute::fill_n()
+template<class BufferIterator, class T>
+inline void fill(BufferIterator first,
+ BufferIterator last,
+ const T &value,
+ command_queue &queue = system::default_queue())
+{
+ size_t count = detail::iterator_range_size(first, last);
+ if(count == 0){
+ return;
+ }
+
+ detail::dispatch_fill(first, count, value, queue);
+}
+
+template<class BufferIterator, class T>
+inline future<void> fill_async(BufferIterator first,
+ BufferIterator last,
+ const T &value,
+ command_queue &queue = system::default_queue())
+{
+ size_t count = detail::iterator_range_size(first, last);
+ if(count == 0){
+ return future<void>();
+ }
+
+ return detail::dispatch_fill_async(first, count, value, queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_FILL_HPP
diff --git a/boost/compute/algorithm/fill_n.hpp b/boost/compute/algorithm/fill_n.hpp
new file mode 100644
index 0000000000..18a8f706a5
--- /dev/null
+++ b/boost/compute/algorithm/fill_n.hpp
@@ -0,0 +1,36 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_FILL_N_HPP
+#define BOOST_COMPUTE_ALGORITHM_FILL_N_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Fills the range [\p first, \p first + count) with \p value.
+///
+/// \see fill()
+template<class BufferIterator, class Size, class T>
+inline void fill_n(BufferIterator first,
+ Size count,
+ const T &value,
+ command_queue &queue = system::default_queue())
+{
+ ::boost::compute::fill(first, first + count, value, queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_FILL_N_HPP
diff --git a/boost/compute/algorithm/find.hpp b/boost/compute/algorithm/find.hpp
new file mode 100644
index 0000000000..ef3ebf0c47
--- /dev/null
+++ b/boost/compute/algorithm/find.hpp
@@ -0,0 +1,57 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_FIND_HPP
+#define BOOST_COMPUTE_ALGORITHM_FIND_HPP
+
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/find_if.hpp>
+#include <boost/compute/type_traits/vector_size.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns an iterator pointing to the first element in the range
+/// [\p first, \p last) that equals \p value.
+template<class InputIterator, class T>
+inline InputIterator find(InputIterator first,
+ InputIterator last,
+ const T &value,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ using ::boost::compute::_1;
+ using ::boost::compute::lambda::all;
+
+ if(vector_size<value_type>::value == 1){
+ return ::boost::compute::find_if(
+ first,
+ last,
+ _1 == value,
+ queue
+ );
+ }
+ else {
+ return ::boost::compute::find_if(
+ first,
+ last,
+ all(_1 == value),
+ queue
+ );
+ }
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_FIND_HPP
diff --git a/boost/compute/algorithm/find_end.hpp b/boost/compute/algorithm/find_end.hpp
new file mode 100644
index 0000000000..5c40055113
--- /dev/null
+++ b/boost/compute/algorithm/find_end.hpp
@@ -0,0 +1,119 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_FIND_END_HPP
+#define BOOST_COMPUTE_ALGORITHM_FIND_END_HPP
+
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/detail/search_all.hpp>
+#include <boost/compute/container/detail/scalar.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/system.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+///
+/// \brief Helper function for find_end
+///
+/// Basically a copy of find_if which returns last occurence
+/// instead of first occurence
+///
+template<class InputIterator, class UnaryPredicate>
+inline InputIterator find_end_helper(InputIterator first,
+ InputIterator last,
+ UnaryPredicate predicate,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ size_t count = detail::iterator_range_size(first, last);
+ if(count == 0){
+ return last;
+ }
+
+ const context &context = queue.get_context();
+
+ detail::meta_kernel k("find_end");
+ size_t index_arg = k.add_arg<int *>(memory_object::global_memory, "index");
+ atomic_max<int_> atomic_max_int;
+
+ k << k.decl<const int_>("i") << " = get_global_id(0);\n"
+ << k.decl<const value_type>("value") << "="
+ << first[k.var<const int_>("i")] << ";\n"
+ << "if(" << predicate(k.var<const value_type>("value")) << "){\n"
+ << " " << atomic_max_int(k.var<int_ *>("index"), k.var<int_>("i")) << ";\n"
+ << "}\n";
+
+ kernel kernel = k.compile(context);
+
+ scalar<int_> index(context);
+ kernel.set_arg(index_arg, index.get_buffer());
+
+ index.write(static_cast<int_>(-1), queue);
+
+ queue.enqueue_1d_range_kernel(kernel, 0, count, 0);
+
+ int result = static_cast<int>(index.read(queue));
+ if(result == -1) return last;
+ else return first + result;
+}
+
+} // end detail namespace
+
+///
+/// \brief Substring matching algorithm
+///
+/// Searches for the last match of the pattern [p_first, p_last)
+/// in text [t_first, t_last).
+/// \return Iterator pointing to beginning of last occurence
+///
+/// \param t_first Iterator pointing to start of text
+/// \param t_last Iterator pointing to end of text
+/// \param p_first Iterator pointing to start of pattern
+/// \param p_last Iterator pointing to end of pattern
+/// \param queue Queue on which to execute
+///
+template<class TextIterator, class PatternIterator>
+inline TextIterator find_end(TextIterator t_first,
+ TextIterator t_last,
+ PatternIterator p_first,
+ PatternIterator p_last,
+ command_queue &queue = system::default_queue())
+{
+ const context &context = queue.get_context();
+ vector<uint_> matching_indices(detail::iterator_range_size(t_first, t_last),
+ context);
+
+ detail::search_kernel<PatternIterator,
+ TextIterator,
+ vector<uint_>::iterator> kernel;
+
+ kernel.set_range(p_first, p_last, t_first, t_last, matching_indices.begin());
+ kernel.exec(queue);
+
+ using boost::compute::_1;
+
+ vector<uint_>::iterator index =
+ detail::find_end_helper(matching_indices.begin(),
+ matching_indices.end(),
+ _1 == 1,
+ queue);
+
+ return t_first + detail::iterator_range_size(matching_indices.begin(), index);
+}
+
+} //end compute namespace
+} //end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_FIND_END_HPP
diff --git a/boost/compute/algorithm/find_if.hpp b/boost/compute/algorithm/find_if.hpp
new file mode 100644
index 0000000000..db99cc0396
--- /dev/null
+++ b/boost/compute/algorithm/find_if.hpp
@@ -0,0 +1,35 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_FIND_IF_HPP
+#define BOOST_COMPUTE_ALGORITHM_FIND_IF_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/detail/find_if_with_atomics.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns an iterator pointing to the first element in the range
+/// [\p first, \p last) for which \p predicate returns \c true.
+template<class InputIterator, class UnaryPredicate>
+inline InputIterator find_if(InputIterator first,
+ InputIterator last,
+ UnaryPredicate predicate,
+ command_queue &queue = system::default_queue())
+{
+ return detail::find_if_with_atomics(first, last, predicate, queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_FIND_IF_HPP
diff --git a/boost/compute/algorithm/find_if_not.hpp b/boost/compute/algorithm/find_if_not.hpp
new file mode 100644
index 0000000000..61de050d31
--- /dev/null
+++ b/boost/compute/algorithm/find_if_not.hpp
@@ -0,0 +1,43 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_FIND_IF_NOT_HPP
+#define BOOST_COMPUTE_ALGORITHM_FIND_IF_NOT_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/find_if.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns an iterator pointing to the first element in the range
+/// [\p first, \p last) for which \p predicate returns \c false.
+///
+/// \see find_if()
+template<class InputIterator, class UnaryPredicate>
+inline InputIterator find_if_not(InputIterator first,
+ InputIterator last,
+ UnaryPredicate predicate,
+ command_queue &queue = system::default_queue())
+{
+ return ::boost::compute::find_if(
+ first,
+ last,
+ not1(predicate),
+ queue
+ );
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_FIND_IF_NOT_HPP
diff --git a/boost/compute/algorithm/for_each.hpp b/boost/compute/algorithm/for_each.hpp
new file mode 100644
index 0000000000..3ed399e6e9
--- /dev/null
+++ b/boost/compute/algorithm/for_each.hpp
@@ -0,0 +1,65 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_FOR_EACH_HPP
+#define BOOST_COMPUTE_ALGORITHM_FOR_EACH_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator, class Function>
+struct for_each_kernel : public meta_kernel
+{
+ for_each_kernel(InputIterator first, InputIterator last, Function function)
+ : meta_kernel("for_each")
+ {
+ // store range size
+ m_count = detail::iterator_range_size(first, last);
+
+ // setup kernel source
+ *this << function(first[get_global_id(0)]) << ";\n";
+ }
+
+ void exec(command_queue &queue)
+ {
+ exec_1d(queue, 0, m_count);
+ }
+
+ size_t m_count;
+};
+
+} // end detail namespace
+
+/// Calls \p function on each element in the range [\p first, \p last).
+///
+/// \see transform()
+template<class InputIterator, class UnaryFunction>
+inline UnaryFunction for_each(InputIterator first,
+ InputIterator last,
+ UnaryFunction function,
+ command_queue &queue = system::default_queue())
+{
+ detail::for_each_kernel<InputIterator, UnaryFunction> kernel(first, last, function);
+
+ kernel.exec(queue);
+
+ return function;
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_FOR_EACH_HPP
diff --git a/boost/compute/algorithm/for_each_n.hpp b/boost/compute/algorithm/for_each_n.hpp
new file mode 100644
index 0000000000..d0be784bf7
--- /dev/null
+++ b/boost/compute/algorithm/for_each_n.hpp
@@ -0,0 +1,35 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_FOR_EACH_N_HPP
+#define BOOST_COMPUTE_ALGORITHM_FOR_EACH_N_HPP
+
+#include <boost/compute/algorithm/for_each.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Calls \p function on each element in the range [\p first, \p first
+/// \c + \p count).
+///
+/// \see for_each()
+template<class InputIterator, class Size, class UnaryFunction>
+inline UnaryFunction for_each_n(InputIterator first,
+ Size count,
+ UnaryFunction function,
+ command_queue &queue = system::default_queue())
+{
+ return ::boost::compute::for_each(first, first + count, function, queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_FOR_EACH_N_HPP
diff --git a/boost/compute/algorithm/gather.hpp b/boost/compute/algorithm/gather.hpp
new file mode 100644
index 0000000000..b2f725d54e
--- /dev/null
+++ b/boost/compute/algorithm/gather.hpp
@@ -0,0 +1,84 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_GATHER_HPP
+#define BOOST_COMPUTE_ALGORITHM_GATHER_HPP
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/exception.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator, class MapIterator, class OutputIterator>
+class gather_kernel : public meta_kernel
+{
+public:
+ gather_kernel() : meta_kernel("gather")
+ {}
+
+ void set_range(MapIterator first,
+ MapIterator last,
+ InputIterator input,
+ OutputIterator result)
+ {
+ m_count = iterator_range_size(first, last);
+ m_offset = first.get_index();
+
+ *this <<
+ "const uint i = get_global_id(0);\n" <<
+ result[expr<uint_>("i")] << "=" <<
+ input[first[expr<uint_>("i")]] << ";\n";
+ }
+
+ event exec(command_queue &queue)
+ {
+ if(m_count == 0) {
+ return event();
+ }
+
+ return exec_1d(queue, m_offset, m_count);
+ }
+
+private:
+ size_t m_count;
+ size_t m_offset;
+};
+
+} // end detail namespace
+
+/// Copies the elements using the indices from the range [\p first, \p last)
+/// to the range beginning at \p result using the input values from the range
+/// beginning at \p input.
+///
+/// \see scatter()
+template<class InputIterator, class MapIterator, class OutputIterator>
+inline void gather(MapIterator first,
+ MapIterator last,
+ InputIterator input,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
+{
+ detail::gather_kernel<InputIterator, MapIterator, OutputIterator> kernel;
+
+ kernel.set_range(first, last, input, result);
+ kernel.exec(queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_GATHER_HPP
diff --git a/boost/compute/algorithm/generate.hpp b/boost/compute/algorithm/generate.hpp
new file mode 100644
index 0000000000..c70a542683
--- /dev/null
+++ b/boost/compute/algorithm/generate.hpp
@@ -0,0 +1,49 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_GENERATE_HPP
+#define BOOST_COMPUTE_ALGORITHM_GENERATE_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/iterator/function_input_iterator.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Stores the result of \p generator for each element in the range
+/// [\p first, \p last).
+template<class OutputIterator, class Generator>
+inline void generate(OutputIterator first,
+ OutputIterator last,
+ Generator generator,
+ command_queue &queue = system::default_queue())
+{
+ size_t count = detail::iterator_range_size(first, last);
+ if(count == 0){
+ return;
+ }
+
+ ::boost::compute::copy(
+ ::boost::compute::make_function_input_iterator(generator,
+ first.get_index()),
+ ::boost::compute::make_function_input_iterator(generator,
+ last.get_index()),
+ first,
+ queue
+ );
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_GENERATE_HPP
diff --git a/boost/compute/algorithm/generate_n.hpp b/boost/compute/algorithm/generate_n.hpp
new file mode 100644
index 0000000000..6d8e607b64
--- /dev/null
+++ b/boost/compute/algorithm/generate_n.hpp
@@ -0,0 +1,35 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_GENERATE_N_HPP
+#define BOOST_COMPUTE_ALGORITHM_GENERATE_N_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/generate.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Stores the result of \p generator for each element in the range
+/// [\p first, \p first + \p count).
+template<class OutputIterator, class Size, class Generator>
+inline void generate_n(OutputIterator first,
+ Size count,
+ Generator generator,
+ command_queue &queue = system::default_queue())
+{
+ ::boost::compute::generate(first, first + count, generator, queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_GENERATE_N_HPP
diff --git a/boost/compute/algorithm/includes.hpp b/boost/compute/algorithm/includes.hpp
new file mode 100644
index 0000000000..c4e7c793e7
--- /dev/null
+++ b/boost/compute/algorithm/includes.hpp
@@ -0,0 +1,155 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_INCLUDES_HPP
+#define BOOST_COMPUTE_ALGORITHM_INCLUDES_HPP
+
+#include <iterator>
+
+#include <boost/compute/algorithm/detail/balanced_path.hpp>
+#include <boost/compute/algorithm/fill_n.hpp>
+#include <boost/compute/algorithm/find.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/read_write_single_value.hpp>
+#include <boost/compute/system.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+///
+/// \brief Serial includes kernel class
+///
+/// Subclass of meta_kernel to perform includes operation after tiling
+///
+class serial_includes_kernel : meta_kernel
+{
+public:
+
+ serial_includes_kernel() : meta_kernel("includes")
+ {
+
+ }
+
+ template<class InputIterator1, class InputIterator2,
+ class InputIterator3, class InputIterator4,
+ class OutputIterator>
+ void set_range(InputIterator1 first1,
+ InputIterator2 first2,
+ InputIterator3 tile_first1,
+ InputIterator3 tile_last1,
+ InputIterator4 tile_first2,
+ OutputIterator result)
+ {
+ m_count = iterator_range_size(tile_first1, tile_last1) - 1;
+
+ *this <<
+ "uint i = get_global_id(0);\n" <<
+ "uint start1 = " << tile_first1[expr<uint_>("i")] << ";\n" <<
+ "uint end1 = " << tile_first1[expr<uint_>("i+1")] << ";\n" <<
+ "uint start2 = " << tile_first2[expr<uint_>("i")] << ";\n" <<
+ "uint end2 = " << tile_first2[expr<uint_>("i+1")] << ";\n" <<
+ "uint includes = 1;\n" <<
+ "while(start1<end1 && start2<end2)\n" <<
+ "{\n" <<
+ " if(" << first1[expr<uint_>("start1")] << " == " <<
+ first2[expr<uint_>("start2")] << ")\n" <<
+ " {\n" <<
+ " start1++; start2++;\n" <<
+ " }\n" <<
+ " else if(" << first1[expr<uint_>("start1")] << " < " <<
+ first2[expr<uint_>("start2")] << ")\n" <<
+ " start1++;\n" <<
+ " else\n" <<
+ " {\n" <<
+ " includes = 0;\n" <<
+ " break;\n" <<
+ " }\n" <<
+ "}\n" <<
+ "if(start2<end2)\n" <<
+ " includes = 0;\n" <<
+ result[expr<uint_>("i")] << " = includes;\n";
+ }
+
+ event exec(command_queue &queue)
+ {
+ if(m_count == 0) {
+ return event();
+ }
+
+ return exec_1d(queue, 0, m_count);
+ }
+
+private:
+ size_t m_count;
+};
+
+} //end detail namespace
+
+///
+/// \brief Includes algorithm
+///
+/// Finds if the sorted range [first1, last1) includes the sorted
+/// range [first2, last2). In other words, it checks if [first1, last1) is
+/// a superset of [first2, last2).
+///
+/// \return True, if [first1, last1) includes [first2, last2). False otherwise.
+///
+/// \param first1 Iterator pointing to start of first set
+/// \param last1 Iterator pointing to end of first set
+/// \param first2 Iterator pointing to start of second set
+/// \param last2 Iterator pointing to end of second set
+/// \param queue Queue on which to execute
+///
+template<class InputIterator1, class InputIterator2>
+inline bool includes(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ command_queue &queue = system::default_queue())
+{
+ size_t tile_size = 1024;
+
+ size_t count1 = detail::iterator_range_size(first1, last1);
+ size_t count2 = detail::iterator_range_size(first2, last2);
+
+ vector<uint_> tile_a((count1+count2+tile_size-1)/tile_size+1, queue.get_context());
+ vector<uint_> tile_b((count1+count2+tile_size-1)/tile_size+1, queue.get_context());
+
+ // Tile the sets
+ detail::balanced_path_kernel tiling_kernel;
+ tiling_kernel.tile_size = static_cast<unsigned int>(tile_size);
+ tiling_kernel.set_range(first1, last1, first2, last2,
+ tile_a.begin()+1, tile_b.begin()+1);
+ fill_n(tile_a.begin(), 1, uint_(0), queue);
+ fill_n(tile_b.begin(), 1, uint_(0), queue);
+ tiling_kernel.exec(queue);
+
+ fill_n(tile_a.end()-1, 1, static_cast<uint_>(count1), queue);
+ fill_n(tile_b.end()-1, 1, static_cast<uint_>(count2), queue);
+
+ vector<uint_> result((count1+count2+tile_size-1)/tile_size, queue.get_context());
+
+ // Find individually
+ detail::serial_includes_kernel includes_kernel;
+ includes_kernel.set_range(first1, first2, tile_a.begin(), tile_a.end(),
+ tile_b.begin(), result.begin());
+
+ includes_kernel.exec(queue);
+
+ return find(result.begin(), result.end(), 0, queue) == result.end();
+}
+
+} //end compute namespace
+} //end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_SET_UNION_HPP
diff --git a/boost/compute/algorithm/inclusive_scan.hpp b/boost/compute/algorithm/inclusive_scan.hpp
new file mode 100644
index 0000000000..9f98beaf7c
--- /dev/null
+++ b/boost/compute/algorithm/inclusive_scan.hpp
@@ -0,0 +1,81 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_INCLUSIVE_SCAN_HPP
+#define BOOST_COMPUTE_ALGORITHM_INCLUSIVE_SCAN_HPP
+
+#include <boost/compute/functional.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/detail/scan.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Performs an inclusive scan of the elements in the range [\p first, \p last)
+/// and stores the results in the range beginning at \p result.
+///
+/// Each element in the output is assigned to the sum of the current value in
+/// the input with the sum of every previous value in the input.
+///
+/// \param first first element in the range to scan
+/// \param last last element in the range to scan
+/// \param result first element in the result range
+/// \param binary_op associative binary operator
+/// \param queue command queue to perform the operation
+///
+/// \return \c OutputIterator to the end of the result range
+///
+/// The default operation is to add the elements up.
+///
+/// \snippet test/test_scan.cpp inclusive_scan_int
+///
+/// But different associative operation can be specified as \p binary_op
+/// instead (e.g., multiplication, maximum, minimum).
+///
+/// \snippet test/test_scan.cpp inclusive_scan_int_multiplies
+///
+/// \see exclusive_scan()
+template<class InputIterator, class OutputIterator, class BinaryOperator>
+inline OutputIterator
+inclusive_scan(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ BinaryOperator binary_op,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename
+ std::iterator_traits<OutputIterator>::value_type output_type;
+
+ return detail::scan(first, last, result, false,
+ output_type(0), binary_op,
+ queue);
+}
+
+/// \overload
+template<class InputIterator, class OutputIterator>
+inline OutputIterator
+inclusive_scan(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename
+ std::iterator_traits<OutputIterator>::value_type output_type;
+
+ return detail::scan(first, last, result, false,
+ output_type(0), boost::compute::plus<output_type>(),
+ queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_INCLUSIVE_SCAN_HPP
diff --git a/boost/compute/algorithm/inner_product.hpp b/boost/compute/algorithm/inner_product.hpp
new file mode 100644
index 0000000000..614611f91e
--- /dev/null
+++ b/boost/compute/algorithm/inner_product.hpp
@@ -0,0 +1,93 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_INNER_PRODUCT_HPP
+#define BOOST_COMPUTE_ALGORITHM_INNER_PRODUCT_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/accumulate.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/transform_iterator.hpp>
+#include <boost/compute/iterator/zip_iterator.hpp>
+#include <boost/compute/functional/detail/unpack.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns the inner product of the elements in the range
+/// [\p first1, \p last1) with the elements in the range beginning
+/// at \p first2.
+template<class InputIterator1, class InputIterator2, class T>
+inline T inner_product(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ T init,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator1>::value_type input_type;
+
+ ptrdiff_t n = std::distance(first1, last1);
+
+ return ::boost::compute::accumulate(
+ ::boost::compute::make_transform_iterator(
+ ::boost::compute::make_zip_iterator(
+ boost::make_tuple(first1, first2)
+ ),
+ detail::unpack(multiplies<input_type>())
+ ),
+ ::boost::compute::make_transform_iterator(
+ ::boost::compute::make_zip_iterator(
+ boost::make_tuple(last1, first2 + n)
+ ),
+ detail::unpack(multiplies<input_type>())
+ ),
+ init,
+ queue
+ );
+}
+
+/// \overload
+template<class InputIterator1,
+ class InputIterator2,
+ class T,
+ class BinaryAccumulateFunction,
+ class BinaryTransformFunction>
+inline T inner_product(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ T init,
+ BinaryAccumulateFunction accumulate_function,
+ BinaryTransformFunction transform_function,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator1>::value_type value_type;
+
+ size_t count = detail::iterator_range_size(first1, last1);
+ vector<value_type> result(count, queue.get_context());
+ transform(first1,
+ last1,
+ first2,
+ result.begin(),
+ transform_function,
+ queue);
+
+ return ::boost::compute::accumulate(result.begin(),
+ result.end(),
+ init,
+ accumulate_function,
+ queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_INNER_PRODUCT_HPP
diff --git a/boost/compute/algorithm/inplace_merge.hpp b/boost/compute/algorithm/inplace_merge.hpp
new file mode 100644
index 0000000000..3080950df5
--- /dev/null
+++ b/boost/compute/algorithm/inplace_merge.hpp
@@ -0,0 +1,60 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_INPLACE_MERGE_HPP
+#define BOOST_COMPUTE_ALGORITHM_INPLACE_MERGE_HPP
+
+#include <iterator>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/merge.hpp>
+#include <boost/compute/container/vector.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Merges the sorted values in the range [\p first, \p middle) with
+/// the sorted values in the range [\p middle, \p last) in-place.
+template<class Iterator>
+inline void inplace_merge(Iterator first,
+ Iterator middle,
+ Iterator last,
+ command_queue &queue = system::default_queue())
+{
+ BOOST_ASSERT(first < middle && middle < last);
+
+ typedef typename std::iterator_traits<Iterator>::value_type T;
+
+ const context &context = queue.get_context();
+
+ ptrdiff_t left_size = std::distance(first, middle);
+ ptrdiff_t right_size = std::distance(middle, last);
+
+ vector<T> left(left_size, context);
+ vector<T> right(right_size, context);
+
+ copy(first, middle, left.begin(), queue);
+ copy(middle, last, right.begin(), queue);
+
+ ::boost::compute::merge(
+ left.begin(),
+ left.end(),
+ right.begin(),
+ right.end(),
+ first,
+ queue
+ );
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_INPLACE_MERGE_HPP
diff --git a/boost/compute/algorithm/iota.hpp b/boost/compute/algorithm/iota.hpp
new file mode 100644
index 0000000000..084c3d8d97
--- /dev/null
+++ b/boost/compute/algorithm/iota.hpp
@@ -0,0 +1,48 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_IOTA_HPP
+#define BOOST_COMPUTE_ALGORITHM_IOTA_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/iterator/counting_iterator.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Fills the range [\p first, \p last) with sequential values starting at
+/// \p value.
+///
+/// For example, the following code:
+/// \snippet test/test_iota.cpp iota
+///
+/// Will fill \c vec with the values (\c 0, \c 1, \c 2, \c ...).
+template<class BufferIterator, class T>
+inline void iota(BufferIterator first,
+ BufferIterator last,
+ const T &value,
+ command_queue &queue = system::default_queue())
+{
+ T count = static_cast<T>(detail::iterator_range_size(first, last));
+
+ copy(
+ ::boost::compute::make_counting_iterator(value),
+ ::boost::compute::make_counting_iterator(value + count),
+ first,
+ queue
+ );
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_IOTA_HPP
diff --git a/boost/compute/algorithm/is_partitioned.hpp b/boost/compute/algorithm/is_partitioned.hpp
new file mode 100644
index 0000000000..3916825057
--- /dev/null
+++ b/boost/compute/algorithm/is_partitioned.hpp
@@ -0,0 +1,43 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_IS_PARTITIONED_HPP
+#define BOOST_COMPUTE_ALGORITHM_IS_PARTITIONED_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/find_if.hpp>
+#include <boost/compute/algorithm/find_if_not.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns \c true if the values in the range [\p first, \p last)
+/// are partitioned according to \p predicate.
+template<class InputIterator, class UnaryPredicate>
+inline bool is_partitioned(InputIterator first,
+ InputIterator last,
+ UnaryPredicate predicate,
+ command_queue &queue = system::default_queue())
+{
+ return ::boost::compute::find_if(
+ ::boost::compute::find_if_not(first,
+ last,
+ predicate,
+ queue),
+ last,
+ predicate,
+ queue) == last;
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_PARTITION_HPP
diff --git a/boost/compute/algorithm/is_permutation.hpp b/boost/compute/algorithm/is_permutation.hpp
new file mode 100644
index 0000000000..1e502efb37
--- /dev/null
+++ b/boost/compute/algorithm/is_permutation.hpp
@@ -0,0 +1,67 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_IS_PERMUTATION_HPP
+#define BOOST_COMPUTE_ALGORITHM_IS_PERMUTATION_HPP
+
+#include <iterator>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/algorithm/equal.hpp>
+#include <boost/compute/algorithm/sort.hpp>
+
+namespace boost {
+namespace compute {
+
+///
+/// \brief Permutation checking algorithm
+///
+/// Checks if the range [first1, last1) can be permuted into the
+/// range [first2, last2)
+/// \return True, if it can be permuted. False, otherwise.
+///
+/// \param first1 Iterator pointing to start of first range
+/// \param last1 Iterator pointing to end of first range
+/// \param first2 Iterator pointing to start of second range
+/// \param last2 Iterator pointing to end of second range
+/// \param queue Queue on which to execute
+///
+template<class InputIterator1, class InputIterator2>
+inline bool is_permutation(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator1>::value_type value_type1;
+ typedef typename std::iterator_traits<InputIterator2>::value_type value_type2;
+
+ size_t count1 = detail::iterator_range_size(first1, last1);
+ size_t count2 = detail::iterator_range_size(first2, last2);
+
+ if(count1 != count2) return false;
+
+ vector<value_type1> temp1(first1, last1, queue);
+ vector<value_type2> temp2(first2, last2, queue);
+
+ sort(temp1.begin(), temp1.end(), queue);
+ sort(temp2.begin(), temp2.end(), queue);
+
+ return equal(temp1.begin(), temp1.end(),
+ temp2.begin(), queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_IS_PERMUTATION_HPP
diff --git a/boost/compute/algorithm/is_sorted.hpp b/boost/compute/algorithm/is_sorted.hpp
new file mode 100644
index 0000000000..a605159ac3
--- /dev/null
+++ b/boost/compute/algorithm/is_sorted.hpp
@@ -0,0 +1,64 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_IS_SORTED_HPP
+#define BOOST_COMPUTE_ALGORITHM_IS_SORTED_HPP
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/functional/bind.hpp>
+#include <boost/compute/functional/operator.hpp>
+#include <boost/compute/algorithm/adjacent_find.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns \c true if the values in the range [\p first, \p last)
+/// are in sorted order.
+///
+/// \param first first element in the range to check
+/// \param last last element in the range to check
+/// \param compare comparison function (by default \c less)
+/// \param queue command queue to perform the operation
+///
+/// \return \c true if the range [\p first, \p last) is sorted
+///
+/// \see sort()
+template<class InputIterator, class Compare>
+inline bool is_sorted(InputIterator first,
+ InputIterator last,
+ Compare compare,
+ command_queue &queue = system::default_queue())
+{
+ using ::boost::compute::placeholders::_1;
+ using ::boost::compute::placeholders::_2;
+
+ return ::boost::compute::adjacent_find(
+ first, last, ::boost::compute::bind(compare, _2, _1), queue
+ ) == last;
+}
+
+/// \overload
+template<class InputIterator>
+inline bool is_sorted(InputIterator first,
+ InputIterator last,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ return ::boost::compute::is_sorted(
+ first, last, ::boost::compute::less<value_type>(), queue
+ );
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_IS_SORTED_HPP
diff --git a/boost/compute/algorithm/lexicographical_compare.hpp b/boost/compute/algorithm/lexicographical_compare.hpp
new file mode 100644
index 0000000000..c4f7120807
--- /dev/null
+++ b/boost/compute/algorithm/lexicographical_compare.hpp
@@ -0,0 +1,117 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Mageswaran.D <mageswaran1989@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/any_of.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/utility/program_cache.hpp>
+
+namespace boost {
+namespace compute {
+
+namespace detail {
+
+const char lexicographical_compare_source[] =
+"__kernel void lexicographical_compare(const uint size1,\n"
+" const uint size2,\n"
+" __global const T1 *range1,\n"
+" __global const T2 *range2,\n"
+" __global bool *result_buf)\n"
+"{\n"
+" const uint i = get_global_id(0);\n"
+" if((i != size1) && (i != size2)){\n"
+ //Individual elements are compared and results are stored in parallel.
+ //0 is true
+" if(range1[i] < range2[i])\n"
+" result_buf[i] = 0;\n"
+" else\n"
+" result_buf[i] = 1;\n"
+" }\n"
+" else\n"
+" result_buf[i] = !((i == size1) && (i != size2));\n"
+"}\n";
+
+template<class InputIterator1, class InputIterator2>
+inline bool dispatch_lexicographical_compare(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ command_queue &queue)
+{
+ const boost::compute::context &context = queue.get_context();
+
+ boost::shared_ptr<program_cache> cache =
+ program_cache::get_global_cache(context);
+
+ size_t iterator_size1 = iterator_range_size(first1, last1);
+ size_t iterator_size2 = iterator_range_size(first2, last2);
+ size_t max_size = (std::max)(iterator_size1, iterator_size2);
+
+ if(max_size == 0){
+ return false;
+ }
+
+ boost::compute::vector<bool> result_vector(max_size, context);
+
+
+ typedef typename std::iterator_traits<InputIterator1>::value_type value_type1;
+ typedef typename std::iterator_traits<InputIterator2>::value_type value_type2;
+
+ // load (or create) lexicographical compare program
+ std::string cache_key =
+ std::string("__boost_lexicographical_compare")
+ + type_name<value_type1>() + type_name<value_type2>();
+
+ std::stringstream options;
+ options << " -DT1=" << type_name<value_type1>();
+ options << " -DT2=" << type_name<value_type2>();
+
+ program lexicographical_compare_program = cache->get_or_build(
+ cache_key, options.str(), lexicographical_compare_source, context
+ );
+
+ kernel lexicographical_compare_kernel(lexicographical_compare_program,
+ "lexicographical_compare");
+
+ lexicographical_compare_kernel.set_arg<uint_>(0, iterator_size1);
+ lexicographical_compare_kernel.set_arg<uint_>(1, iterator_size2);
+ lexicographical_compare_kernel.set_arg(2, first1.get_buffer());
+ lexicographical_compare_kernel.set_arg(3, first2.get_buffer());
+ lexicographical_compare_kernel.set_arg(4, result_vector.get_buffer());
+
+ queue.enqueue_1d_range_kernel(lexicographical_compare_kernel,
+ 0,
+ max_size,
+ 0);
+
+ return boost::compute::any_of(result_vector.begin(),
+ result_vector.end(),
+ _1 == 0,
+ queue);
+}
+
+} // end detail namespace
+
+/// Checks if the first range [first1, last1) is lexicographically
+/// less than the second range [first2, last2).
+template<class InputIterator1, class InputIterator2>
+inline bool lexicographical_compare(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ command_queue &queue = system::default_queue())
+{
+ return detail::dispatch_lexicographical_compare(first1, last1, first2, last2, queue);
+}
+
+} // end compute namespace
+} // end boost namespac
diff --git a/boost/compute/algorithm/lower_bound.hpp b/boost/compute/algorithm/lower_bound.hpp
new file mode 100644
index 0000000000..b2011c66ef
--- /dev/null
+++ b/boost/compute/algorithm/lower_bound.hpp
@@ -0,0 +1,44 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_LOWER_BOUND_HPP
+#define BOOST_COMPUTE_ALGORITHM_LOWER_BOUND_HPP
+
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/detail/binary_find.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns an iterator pointing to the first element in the sorted
+/// range [\p first, \p last) that is not less than \p value.
+///
+/// \see upper_bound()
+template<class InputIterator, class T>
+inline InputIterator
+lower_bound(InputIterator first,
+ InputIterator last,
+ const T &value,
+ command_queue &queue = system::default_queue())
+{
+ using ::boost::compute::_1;
+
+ InputIterator position =
+ detail::binary_find(first, last, _1 >= value, queue);
+
+ return position;
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_LOWER_BOUND_HPP
diff --git a/boost/compute/algorithm/max_element.hpp b/boost/compute/algorithm/max_element.hpp
new file mode 100644
index 0000000000..55f2f7ffbf
--- /dev/null
+++ b/boost/compute/algorithm/max_element.hpp
@@ -0,0 +1,74 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_MAX_ELEMENT_HPP
+#define BOOST_COMPUTE_ALGORITHM_MAX_ELEMENT_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/algorithm/detail/find_extrema.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns an iterator pointing to the element in the range
+/// [\p first, \p last) with the maximum value.
+///
+/// \param first first element in the input range
+/// \param last last element in the input range
+/// \param compare comparison function object which returns true if the first
+/// argument is less than (i.e. is ordered before) the second.
+/// \param queue command queue to perform the operation
+///
+/// For example, to find \c int2 value with maximum first component in given vector:
+/// \code
+/// // comparison function object
+/// BOOST_COMPUTE_FUNCTION(bool, compare_first, (const int2_ &a, const int2_ &b),
+/// {
+/// return a.x < b.x;
+/// });
+///
+/// // create vector
+/// boost::compute::vector<uint2_> data = ...
+///
+/// boost::compute::vector<uint2_>::iterator max =
+/// boost::compute::max_element(data.begin(), data.end(), compare_first, queue);
+/// \endcode
+///
+/// \see min_element()
+template<class InputIterator, class Compare>
+inline InputIterator
+max_element(InputIterator first,
+ InputIterator last,
+ Compare compare,
+ command_queue &queue = system::default_queue())
+{
+ return detail::find_extrema(first, last, compare, false, queue);
+}
+
+///\overload
+template<class InputIterator>
+inline InputIterator
+max_element(InputIterator first,
+ InputIterator last,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ return ::boost::compute::max_element(
+ first, last, ::boost::compute::less<value_type>(), queue
+ );
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_MAX_ELEMENT_HPP
diff --git a/boost/compute/algorithm/merge.hpp b/boost/compute/algorithm/merge.hpp
new file mode 100644
index 0000000000..875a283044
--- /dev/null
+++ b/boost/compute/algorithm/merge.hpp
@@ -0,0 +1,105 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_MERGE_HPP
+#define BOOST_COMPUTE_ALGORITHM_MERGE_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/detail/merge_with_merge_path.hpp>
+#include <boost/compute/algorithm/detail/serial_merge.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/parameter_cache.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Merges the sorted values in the range [\p first1, \p last1) with the sorted
+/// values in the range [\p first2, last2) and stores the result in the range
+/// beginning at \p result. Values are compared using the \p comp function. If
+/// no comparision function is given, \c less is used.
+///
+/// \param first1 first element in the first range to merge
+/// \param last1 last element in the first range to merge
+/// \param first2 first element in the second range to merge
+/// \param last2 last element in the second range to merge
+/// \param result first element in the result range
+/// \param comp comparison function (by default \c less)
+/// \param queue command queue to perform the operation
+///
+/// \return \c OutputIterator to the end of the result range
+///
+/// \see inplace_merge()
+template<class InputIterator1,
+ class InputIterator2,
+ class OutputIterator,
+ class Compare>
+inline OutputIterator merge(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator result,
+ Compare comp,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator1>::value_type input1_type;
+ typedef typename std::iterator_traits<InputIterator2>::value_type input2_type;
+ typedef typename std::iterator_traits<OutputIterator>::value_type output_type;
+
+ const device &device = queue.get_device();
+
+ std::string cache_key =
+ std::string("__boost_merge_") + type_name<input1_type>() + "_"
+ + type_name<input2_type>() + "_" + type_name<output_type>();
+ boost::shared_ptr<detail::parameter_cache> parameters =
+ detail::parameter_cache::get_global_cache(device);
+
+ // default serial merge threshold depends on device type
+ size_t default_serial_merge_threshold = 32768;
+ if(device.type() & device::gpu) {
+ default_serial_merge_threshold = 2048;
+ }
+
+ // loading serial merge threshold parameter
+ const size_t serial_merge_threshold =
+ parameters->get(cache_key, "serial_merge_threshold",
+ static_cast<uint_>(default_serial_merge_threshold));
+
+ // choosing merge algorithm
+ const size_t total_count =
+ detail::iterator_range_size(first1, last1)
+ + detail::iterator_range_size(first2, last2);
+ // for small inputs serial merge turns out to outperform
+ // merge with merge path algorithm
+ if(total_count <= serial_merge_threshold){
+ return detail::serial_merge(first1, last1, first2, last2, result, comp, queue);
+ }
+ return detail::merge_with_merge_path(first1, last1, first2, last2, result, comp, queue);
+}
+
+/// \overload
+template<class InputIterator1, class InputIterator2, class OutputIterator>
+inline OutputIterator merge(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator1>::value_type value_type;
+ less<value_type> less_than;
+ return merge(first1, last1, first2, last2, result, less_than, queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_MERGE_HPP
diff --git a/boost/compute/algorithm/min_element.hpp b/boost/compute/algorithm/min_element.hpp
new file mode 100644
index 0000000000..62744efb98
--- /dev/null
+++ b/boost/compute/algorithm/min_element.hpp
@@ -0,0 +1,74 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_MIN_ELEMENT_HPP
+#define BOOST_COMPUTE_ALGORITHM_MIN_ELEMENT_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/algorithm/detail/find_extrema.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns an iterator pointing to the element in range
+/// [\p first, \p last) with the minimum value.
+///
+/// \param first first element in the input range
+/// \param last last element in the input range
+/// \param compare comparison function object which returns true if the first
+/// argument is less than (i.e. is ordered before) the second.
+/// \param queue command queue to perform the operation
+///
+/// For example, to find \c int2 value with minimum first component in given vector:
+/// \code
+/// // comparison function object
+/// BOOST_COMPUTE_FUNCTION(bool, compare_first, (const int2_ &a, const int2_ &b),
+/// {
+/// return a.x < b.x;
+/// });
+///
+/// // create vector
+/// boost::compute::vector<uint2_> data = ...
+///
+/// boost::compute::vector<uint2_>::iterator min =
+/// boost::compute::min_element(data.begin(), data.end(), compare_first, queue);
+/// \endcode
+///
+/// \see max_element()
+template<class InputIterator, class Compare>
+inline InputIterator
+min_element(InputIterator first,
+ InputIterator last,
+ Compare compare,
+ command_queue &queue = system::default_queue())
+{
+ return detail::find_extrema(first, last, compare, true, queue);
+}
+
+///\overload
+template<class InputIterator>
+inline InputIterator
+min_element(InputIterator first,
+ InputIterator last,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ return ::boost::compute::min_element(
+ first, last, ::boost::compute::less<value_type>(), queue
+ );
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_MIN_ELEMENT_HPP
diff --git a/boost/compute/algorithm/minmax_element.hpp b/boost/compute/algorithm/minmax_element.hpp
new file mode 100644
index 0000000000..bf32c3c989
--- /dev/null
+++ b/boost/compute/algorithm/minmax_element.hpp
@@ -0,0 +1,70 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_MINMAX_ELEMENT_HPP
+#define BOOST_COMPUTE_ALGORITHM_MINMAX_ELEMENT_HPP
+
+#include <utility>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/max_element.hpp>
+#include <boost/compute/algorithm/min_element.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns a pair of iterators with the first pointing to the minimum
+/// element and the second pointing to the maximum element in the range
+/// [\p first, \p last).
+///
+/// \param first first element in the input range
+/// \param last last element in the input range
+/// \param compare comparison function object which returns true if the first
+/// argument is less than (i.e. is ordered before) the second.
+/// \param queue command queue to perform the operation
+///
+/// \see max_element(), min_element()
+template<class InputIterator, class Compare>
+inline std::pair<InputIterator, InputIterator>
+minmax_element(InputIterator first,
+ InputIterator last,
+ Compare compare,
+ command_queue &queue = system::default_queue())
+{
+ if(first == last){
+ // empty range
+ return std::make_pair(first, first);
+ }
+
+ return std::make_pair(min_element(first, last, compare, queue),
+ max_element(first, last, compare, queue));
+}
+
+///\overload
+template<class InputIterator, class Compare>
+inline std::pair<InputIterator, InputIterator>
+minmax_element(InputIterator first,
+ InputIterator last,
+ command_queue &queue = system::default_queue())
+{
+ if(first == last){
+ // empty range
+ return std::make_pair(first, first);
+ }
+
+ return std::make_pair(min_element(first, last, queue),
+ max_element(first, last, queue));
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_MINMAX_ELEMENT_HPP
diff --git a/boost/compute/algorithm/mismatch.hpp b/boost/compute/algorithm/mismatch.hpp
new file mode 100644
index 0000000000..e7db883004
--- /dev/null
+++ b/boost/compute/algorithm/mismatch.hpp
@@ -0,0 +1,89 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_MISMATCH_HPP
+#define BOOST_COMPUTE_ALGORITHM_MISMATCH_HPP
+
+#include <iterator>
+#include <utility>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/find.hpp>
+#include <boost/compute/iterator/transform_iterator.hpp>
+#include <boost/compute/iterator/zip_iterator.hpp>
+#include <boost/compute/functional/detail/unpack.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns a pair of iterators pointing to the first position where the
+/// range [\p first1, \p last1) and the range starting at \p first2
+/// differ.
+template<class InputIterator1, class InputIterator2>
+inline std::pair<InputIterator1, InputIterator2>
+mismatch(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator1>::value_type value_type;
+
+ ::boost::compute::equal_to<value_type> op;
+
+ InputIterator2 last2 = first2 + std::distance(first1, last1);
+
+ InputIterator1 iter =
+ boost::get<0>(
+ ::boost::compute::find(
+ ::boost::compute::make_transform_iterator(
+ ::boost::compute::make_zip_iterator(
+ boost::make_tuple(first1, first2)
+ ),
+ detail::unpack(op)
+ ),
+ ::boost::compute::make_transform_iterator(
+ ::boost::compute::make_zip_iterator(
+ boost::make_tuple(last1, last2)
+ ),
+ detail::unpack(op)
+ ),
+ false,
+ queue
+ ).base().get_iterator_tuple()
+ );
+
+ return std::make_pair(iter, first2 + std::distance(first1, iter));
+}
+
+/// \overload
+template<class InputIterator1, class InputIterator2>
+inline std::pair<InputIterator1, InputIterator2>
+mismatch(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ command_queue &queue = system::default_queue())
+{
+ if(std::distance(first1, last1) < std::distance(first2, last2)){
+ return ::boost::compute::mismatch(first1, last1, first2, queue);
+ }
+ else {
+ return ::boost::compute::mismatch(
+ first1, first1 + std::distance(first2, last2), first2, queue
+ );
+ }
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_MISMATCH_HPP
diff --git a/boost/compute/algorithm/next_permutation.hpp b/boost/compute/algorithm/next_permutation.hpp
new file mode 100644
index 0000000000..e81fbd2ee8
--- /dev/null
+++ b/boost/compute/algorithm/next_permutation.hpp
@@ -0,0 +1,170 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_NEXT_PERMUTATION_HPP
+#define BOOST_COMPUTE_ALGORITHM_NEXT_PERMUTATION_HPP
+
+#include <iterator>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/container/detail/scalar.hpp>
+#include <boost/compute/algorithm/reverse.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+///
+/// \brief Helper function for next_permutation
+///
+/// To find rightmost element which is smaller
+/// than its next element
+///
+template<class InputIterator>
+inline InputIterator next_permutation_helper(InputIterator first,
+ InputIterator last,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ size_t count = detail::iterator_range_size(first, last);
+ if(count == 0 || count == 1){
+ return last;
+ }
+ count = count - 1;
+ const context &context = queue.get_context();
+
+ detail::meta_kernel k("next_permutation");
+ size_t index_arg = k.add_arg<int *>(memory_object::global_memory, "index");
+ atomic_max<int_> atomic_max_int;
+
+ k << k.decl<const int_>("i") << " = get_global_id(0);\n"
+ << k.decl<const value_type>("cur_value") << "="
+ << first[k.var<const int_>("i")] << ";\n"
+ << k.decl<const value_type>("next_value") << "="
+ << first[k.expr<const int_>("i+1")] << ";\n"
+ << "if(cur_value < next_value){\n"
+ << " " << atomic_max_int(k.var<int_ *>("index"), k.var<int_>("i")) << ";\n"
+ << "}\n";
+
+ kernel kernel = k.compile(context);
+
+ scalar<int_> index(context);
+ kernel.set_arg(index_arg, index.get_buffer());
+
+ index.write(static_cast<int_>(-1), queue);
+
+ queue.enqueue_1d_range_kernel(kernel, 0, count, 0);
+
+ int result = static_cast<int>(index.read(queue));
+ if(result == -1) return last;
+ else return first + result;
+}
+
+///
+/// \brief Helper function for next_permutation
+///
+/// To find the smallest element to the right of the element found above
+/// that is greater than it
+///
+template<class InputIterator, class ValueType>
+inline InputIterator np_ceiling(InputIterator first,
+ InputIterator last,
+ ValueType value,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ size_t count = detail::iterator_range_size(first, last);
+ if(count == 0){
+ return last;
+ }
+ const context &context = queue.get_context();
+
+ detail::meta_kernel k("np_ceiling");
+ size_t index_arg = k.add_arg<int *>(memory_object::global_memory, "index");
+ size_t value_arg = k.add_arg<value_type>(memory_object::private_memory, "value");
+ atomic_max<int_> atomic_max_int;
+
+ k << k.decl<const int_>("i") << " = get_global_id(0);\n"
+ << k.decl<const value_type>("cur_value") << "="
+ << first[k.var<const int_>("i")] << ";\n"
+ << "if(cur_value <= " << first[k.expr<int_>("*index")]
+ << " && cur_value > value){\n"
+ << " " << atomic_max_int(k.var<int_ *>("index"), k.var<int_>("i")) << ";\n"
+ << "}\n";
+
+ kernel kernel = k.compile(context);
+
+ scalar<int_> index(context);
+ kernel.set_arg(index_arg, index.get_buffer());
+
+ index.write(static_cast<int_>(0), queue);
+
+ kernel.set_arg(value_arg, value);
+
+ queue.enqueue_1d_range_kernel(kernel, 0, count, 0);
+
+ int result = static_cast<int>(index.read(queue));
+ return first + result;
+}
+
+} // end detail namespace
+
+///
+/// \brief Permutation generating algorithm
+///
+/// Transforms the range [first, last) into the next permutation from the
+/// set of all permutations arranged in lexicographic order
+/// \return Boolean value signifying if the last permutation was crossed
+/// and the range was reset
+///
+/// \param first Iterator pointing to start of range
+/// \param last Iterator pointing to end of range
+/// \param queue Queue on which to execute
+///
+template<class InputIterator>
+inline bool next_permutation(InputIterator first,
+ InputIterator last,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ if(first == last) return false;
+
+ InputIterator first_element =
+ detail::next_permutation_helper(first, last, queue);
+
+ if(first_element == last)
+ {
+ reverse(first, last, queue);
+ return false;
+ }
+
+ value_type first_value = first_element.read(queue);
+
+ InputIterator ceiling_element =
+ detail::np_ceiling(first_element + 1, last, first_value, queue);
+
+ value_type ceiling_value = ceiling_element.read(queue);
+
+ first_element.write(ceiling_value, queue);
+ ceiling_element.write(first_value, queue);
+
+ reverse(first_element + 1, last, queue);
+
+ return true;
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_NEXT_PERMUTATION_HPP
diff --git a/boost/compute/algorithm/none_of.hpp b/boost/compute/algorithm/none_of.hpp
new file mode 100644
index 0000000000..c25dd12a87
--- /dev/null
+++ b/boost/compute/algorithm/none_of.hpp
@@ -0,0 +1,36 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_NONE_OF_HPP
+#define BOOST_COMPUTE_ALGORITHM_NONE_OF_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/find_if.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns \c true if \p predicate returns \c true for none of the elements in
+/// the range [\p first, \p last).
+///
+/// \see all_of(), any_of()
+template<class InputIterator, class UnaryPredicate>
+inline bool none_of(InputIterator first,
+ InputIterator last,
+ UnaryPredicate predicate,
+ command_queue &queue = system::default_queue())
+{
+ return ::boost::compute::find_if(first, last, predicate, queue) == last;
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_NONE_OF_HPP
diff --git a/boost/compute/algorithm/nth_element.hpp b/boost/compute/algorithm/nth_element.hpp
new file mode 100644
index 0000000000..68f7a3dbc0
--- /dev/null
+++ b/boost/compute/algorithm/nth_element.hpp
@@ -0,0 +1,87 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_NTH_ELEMENT_HPP
+#define BOOST_COMPUTE_ALGORITHM_NTH_ELEMENT_HPP
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/fill_n.hpp>
+#include <boost/compute/algorithm/find.hpp>
+#include <boost/compute/algorithm/partition.hpp>
+#include <boost/compute/algorithm/sort.hpp>
+#include <boost/compute/functional/bind.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Rearranges the elements in the range [\p first, \p last) such that
+/// the \p nth element would be in that position in a sorted sequence.
+template<class Iterator, class Compare>
+inline void nth_element(Iterator first,
+ Iterator nth,
+ Iterator last,
+ Compare compare,
+ command_queue &queue = system::default_queue())
+{
+ if(nth == last) return;
+
+ typedef typename std::iterator_traits<Iterator>::value_type value_type;
+
+ while(1)
+ {
+ value_type value = nth.read(queue);
+
+ using boost::compute::placeholders::_1;
+ Iterator new_nth = partition(
+ first, last, ::boost::compute::bind(compare, _1, value), queue
+ );
+
+ Iterator old_nth = find(new_nth, last, value, queue);
+
+ value_type new_value = new_nth.read(queue);
+
+ fill_n(new_nth, 1, value, queue);
+ fill_n(old_nth, 1, new_value, queue);
+
+ new_value = nth.read(queue);
+
+ if(value == new_value) break;
+
+ if(std::distance(first, nth) < std::distance(first, new_nth))
+ {
+ last = new_nth;
+ }
+ else
+ {
+ first = new_nth;
+ }
+ }
+}
+
+/// \overload
+template<class Iterator>
+inline void nth_element(Iterator first,
+ Iterator nth,
+ Iterator last,
+ command_queue &queue = system::default_queue())
+{
+ if(nth == last) return;
+
+ typedef typename std::iterator_traits<Iterator>::value_type value_type;
+
+ less<value_type> less_than;
+
+ return nth_element(first, nth, last, less_than, queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_NTH_ELEMENT_HPP
diff --git a/boost/compute/algorithm/partial_sum.hpp b/boost/compute/algorithm/partial_sum.hpp
new file mode 100644
index 0000000000..d440369a5a
--- /dev/null
+++ b/boost/compute/algorithm/partial_sum.hpp
@@ -0,0 +1,37 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_PARTIAL_SUM_HPP
+#define BOOST_COMPUTE_ALGORITHM_PARTIAL_SUM_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/inclusive_scan.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Calculates the cumulative sum of the elements in the range [\p first,
+/// \p last) and writes the resulting values to the range beginning at
+/// \p result.
+template<class InputIterator, class OutputIterator>
+inline OutputIterator
+partial_sum(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
+{
+ return ::boost::compute::inclusive_scan(first, last, result, queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_PARTIAL_SUM_HPP
diff --git a/boost/compute/algorithm/partition.hpp b/boost/compute/algorithm/partition.hpp
new file mode 100644
index 0000000000..7860350e0d
--- /dev/null
+++ b/boost/compute/algorithm/partition.hpp
@@ -0,0 +1,39 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_PARTITION_HPP
+#define BOOST_COMPUTE_ALGORITHM_PARTITION_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/stable_partition.hpp>
+
+namespace boost {
+namespace compute {
+
+///
+/// Partitions the elements in the range [\p first, \p last) according to
+/// \p predicate. Order of the elements need not be preserved.
+///
+/// \see is_partitioned() and stable_partition()
+///
+template<class Iterator, class UnaryPredicate>
+inline Iterator partition(Iterator first,
+ Iterator last,
+ UnaryPredicate predicate,
+ command_queue &queue = system::default_queue())
+{
+ return stable_partition(first, last, predicate, queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_PARTITION_HPP
diff --git a/boost/compute/algorithm/partition_copy.hpp b/boost/compute/algorithm/partition_copy.hpp
new file mode 100644
index 0000000000..80a2c6475f
--- /dev/null
+++ b/boost/compute/algorithm/partition_copy.hpp
@@ -0,0 +1,63 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_PARTITION_COPY_HPP
+#define BOOST_COMPUTE_ALGORITHM_PARTITION_COPY_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy_if.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Copies all of the elements in the range [\p first, \p last) for which
+/// \p predicate returns \c true to the range beginning at \p first_true
+/// and all of the elements for which \p predicate returns \c false to
+/// the range beginning at \p first_false.
+///
+/// \see partition()
+template<class InputIterator,
+ class OutputIterator1,
+ class OutputIterator2,
+ class UnaryPredicate>
+inline std::pair<OutputIterator1, OutputIterator2>
+partition_copy(InputIterator first,
+ InputIterator last,
+ OutputIterator1 first_true,
+ OutputIterator2 first_false,
+ UnaryPredicate predicate,
+ command_queue &queue = system::default_queue())
+{
+ // copy true values
+ OutputIterator1 last_true =
+ ::boost::compute::copy_if(first,
+ last,
+ first_true,
+ predicate,
+ queue);
+
+ // copy false values
+ OutputIterator2 last_false =
+ ::boost::compute::copy_if(first,
+ last,
+ first_false,
+ not1(predicate),
+ queue);
+
+ // return iterators to the end of the true and the false ranges
+ return std::make_pair(last_true, last_false);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_PARTITION_COPY_HPP
diff --git a/boost/compute/algorithm/partition_point.hpp b/boost/compute/algorithm/partition_point.hpp
new file mode 100644
index 0000000000..3cc2bc0ca6
--- /dev/null
+++ b/boost/compute/algorithm/partition_point.hpp
@@ -0,0 +1,46 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_PARTITION_POINT_HPP
+#define BOOST_COMPUTE_ALGORITHM_PARTITION_POINT_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/detail/binary_find.hpp>
+
+namespace boost {
+namespace compute {
+
+///
+/// \brief Partition point algorithm
+///
+/// Finds the end of true values in the partitioned range [first, last)
+/// \return Iterator pointing to end of true values
+///
+/// \param first Iterator pointing to start of range
+/// \param last Iterator pointing to end of range
+/// \param predicate Unary predicate to be applied on each element
+/// \param queue Queue on which to execute
+///
+/// \see partition() and stable_partition()
+///
+template<class InputIterator, class UnaryPredicate>
+inline InputIterator partition_point(InputIterator first,
+ InputIterator last,
+ UnaryPredicate predicate,
+ command_queue &queue = system::default_queue())
+{
+ return detail::binary_find(first, last, not1(predicate), queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_PARTITION_POINT_HPP
diff --git a/boost/compute/algorithm/prev_permutation.hpp b/boost/compute/algorithm/prev_permutation.hpp
new file mode 100644
index 0000000000..03c01bf8f4
--- /dev/null
+++ b/boost/compute/algorithm/prev_permutation.hpp
@@ -0,0 +1,170 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_PREV_PERMUTATION_HPP
+#define BOOST_COMPUTE_ALGORITHM_PREV_PERMUTATION_HPP
+
+#include <iterator>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/container/detail/scalar.hpp>
+#include <boost/compute/algorithm/reverse.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+///
+/// \brief Helper function for prev_permutation
+///
+/// To find rightmost element which is greater
+/// than its next element
+///
+template<class InputIterator>
+inline InputIterator prev_permutation_helper(InputIterator first,
+ InputIterator last,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ size_t count = detail::iterator_range_size(first, last);
+ if(count == 0 || count == 1){
+ return last;
+ }
+ count = count - 1;
+ const context &context = queue.get_context();
+
+ detail::meta_kernel k("prev_permutation");
+ size_t index_arg = k.add_arg<int *>(memory_object::global_memory, "index");
+ atomic_max<int_> atomic_max_int;
+
+ k << k.decl<const int_>("i") << " = get_global_id(0);\n"
+ << k.decl<const value_type>("cur_value") << "="
+ << first[k.var<const int_>("i")] << ";\n"
+ << k.decl<const value_type>("next_value") << "="
+ << first[k.expr<const int_>("i+1")] << ";\n"
+ << "if(cur_value > next_value){\n"
+ << " " << atomic_max_int(k.var<int_ *>("index"), k.var<int_>("i")) << ";\n"
+ << "}\n";
+
+ kernel kernel = k.compile(context);
+
+ scalar<int_> index(context);
+ kernel.set_arg(index_arg, index.get_buffer());
+
+ index.write(static_cast<int_>(-1), queue);
+
+ queue.enqueue_1d_range_kernel(kernel, 0, count, 0);
+
+ int result = static_cast<int>(index.read(queue));
+ if(result == -1) return last;
+ else return first + result;
+}
+
+///
+/// \brief Helper function for prev_permutation
+///
+/// To find the largest element to the right of the element found above
+/// that is smaller than it
+///
+template<class InputIterator, class ValueType>
+inline InputIterator pp_floor(InputIterator first,
+ InputIterator last,
+ ValueType value,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ size_t count = detail::iterator_range_size(first, last);
+ if(count == 0){
+ return last;
+ }
+ const context &context = queue.get_context();
+
+ detail::meta_kernel k("pp_floor");
+ size_t index_arg = k.add_arg<int *>(memory_object::global_memory, "index");
+ size_t value_arg = k.add_arg<value_type>(memory_object::private_memory, "value");
+ atomic_max<int_> atomic_max_int;
+
+ k << k.decl<const int_>("i") << " = get_global_id(0);\n"
+ << k.decl<const value_type>("cur_value") << "="
+ << first[k.var<const int_>("i")] << ";\n"
+ << "if(cur_value >= " << first[k.expr<int_>("*index")]
+ << " && cur_value < value){\n"
+ << " " << atomic_max_int(k.var<int_ *>("index"), k.var<int_>("i")) << ";\n"
+ << "}\n";
+
+ kernel kernel = k.compile(context);
+
+ scalar<int_> index(context);
+ kernel.set_arg(index_arg, index.get_buffer());
+
+ index.write(static_cast<int_>(0), queue);
+
+ kernel.set_arg(value_arg, value);
+
+ queue.enqueue_1d_range_kernel(kernel, 0, count, 0);
+
+ int result = static_cast<int>(index.read(queue));
+ return first + result;
+}
+
+} // end detail namespace
+
+///
+/// \brief Permutation generating algorithm
+///
+/// Transforms the range [first, last) into the previous permutation from
+/// the set of all permutations arranged in lexicographic order
+/// \return Boolean value signifying if the first permutation was crossed
+/// and the range was reset
+///
+/// \param first Iterator pointing to start of range
+/// \param last Iterator pointing to end of range
+/// \param queue Queue on which to execute
+///
+template<class InputIterator>
+inline bool prev_permutation(InputIterator first,
+ InputIterator last,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ if(first == last) return false;
+
+ InputIterator first_element =
+ detail::prev_permutation_helper(first, last, queue);
+
+ if(first_element == last)
+ {
+ reverse(first, last, queue);
+ return false;
+ }
+
+ value_type first_value = first_element.read(queue);
+
+ InputIterator ceiling_element =
+ detail::pp_floor(first_element + 1, last, first_value, queue);
+
+ value_type ceiling_value = ceiling_element.read(queue);
+
+ first_element.write(ceiling_value, queue);
+ ceiling_element.write(first_value, queue);
+
+ reverse(first_element + 1, last, queue);
+
+ return true;
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_PREV_PERMUTATION_HPP
diff --git a/boost/compute/algorithm/random_shuffle.hpp b/boost/compute/algorithm/random_shuffle.hpp
new file mode 100644
index 0000000000..7d2d46a133
--- /dev/null
+++ b/boost/compute/algorithm/random_shuffle.hpp
@@ -0,0 +1,75 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_RANDOM_SHUFFLE_HPP
+#define BOOST_COMPUTE_ALGORITHM_RANDOM_SHUFFLE_HPP
+
+#include <vector>
+#include <algorithm>
+
+#include <boost/range/algorithm_ext/iota.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/algorithm/scatter.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Randomly shuffles the elements in the range [\p first, \p last).
+///
+/// \see scatter()
+template<class Iterator>
+inline void random_shuffle(Iterator first,
+ Iterator last,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<Iterator>::value_type value_type;
+
+ size_t count = detail::iterator_range_size(first, last);
+ if(count == 0){
+ return;
+ }
+
+ // generate shuffled indices on the host
+ std::vector<cl_uint> random_indices(count);
+ boost::iota(random_indices, 0);
+ std::random_shuffle(random_indices.begin(), random_indices.end());
+
+ // copy random indices to the device
+ const context &context = queue.get_context();
+ vector<cl_uint> indices(count, context);
+ ::boost::compute::copy(random_indices.begin(),
+ random_indices.end(),
+ indices.begin(),
+ queue);
+
+ // make a copy of the values on the device
+ vector<value_type> tmp(count, context);
+ ::boost::compute::copy(first,
+ last,
+ tmp.begin(),
+ queue);
+
+ // write values to their new locations
+ ::boost::compute::scatter(tmp.begin(),
+ tmp.end(),
+ indices.begin(),
+ first,
+ queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_RANDOM_SHUFFLE_HPP
diff --git a/boost/compute/algorithm/reduce.hpp b/boost/compute/algorithm/reduce.hpp
new file mode 100644
index 0000000000..79624a0e50
--- /dev/null
+++ b/boost/compute/algorithm/reduce.hpp
@@ -0,0 +1,301 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_REDUCE_HPP
+#define BOOST_COMPUTE_ALGORITHM_REDUCE_HPP
+
+#include <iterator>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/container/array.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/algorithm/detail/inplace_reduce.hpp>
+#include <boost/compute/algorithm/detail/reduce_on_gpu.hpp>
+#include <boost/compute/algorithm/detail/serial_reduce.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/memory/local_buffer.hpp>
+#include <boost/compute/type_traits/result_of.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator, class OutputIterator, class BinaryFunction>
+size_t reduce(InputIterator first,
+ size_t count,
+ OutputIterator result,
+ size_t block_size,
+ BinaryFunction function,
+ command_queue &queue)
+{
+ typedef typename
+ std::iterator_traits<InputIterator>::value_type
+ input_type;
+ typedef typename
+ boost::compute::result_of<BinaryFunction(input_type, input_type)>::type
+ result_type;
+
+ const context &context = queue.get_context();
+ size_t block_count = count / 2 / block_size;
+ size_t total_block_count =
+ static_cast<size_t>(std::ceil(float(count) / 2.f / float(block_size)));
+
+ if(block_count != 0){
+ meta_kernel k("block_reduce");
+ size_t output_arg = k.add_arg<result_type *>(memory_object::global_memory, "output");
+ size_t block_arg = k.add_arg<input_type *>(memory_object::local_memory, "block");
+
+ k <<
+ "const uint gid = get_global_id(0);\n" <<
+ "const uint lid = get_local_id(0);\n" <<
+
+ // copy values to local memory
+ "block[lid] = " <<
+ function(first[k.make_var<uint_>("gid*2+0")],
+ first[k.make_var<uint_>("gid*2+1")]) << ";\n" <<
+
+ // perform reduction
+ "for(uint i = 1; i < " << uint_(block_size) << "; i <<= 1){\n" <<
+ " barrier(CLK_LOCAL_MEM_FENCE);\n" <<
+ " uint mask = (i << 1) - 1;\n" <<
+ " if((lid & mask) == 0){\n" <<
+ " block[lid] = " <<
+ function(k.expr<input_type>("block[lid]"),
+ k.expr<input_type>("block[lid+i]")) << ";\n" <<
+ " }\n" <<
+ "}\n" <<
+
+ // write block result to global output
+ "if(lid == 0)\n" <<
+ " output[get_group_id(0)] = block[0];\n";
+
+ kernel kernel = k.compile(context);
+ kernel.set_arg(output_arg, result.get_buffer());
+ kernel.set_arg(block_arg, local_buffer<input_type>(block_size));
+
+ queue.enqueue_1d_range_kernel(kernel,
+ 0,
+ block_count * block_size,
+ block_size);
+ }
+
+ // serially reduce any leftovers
+ if(block_count * block_size * 2 < count){
+ size_t last_block_start = block_count * block_size * 2;
+
+ meta_kernel k("extra_serial_reduce");
+ size_t count_arg = k.add_arg<uint_>("count");
+ size_t offset_arg = k.add_arg<uint_>("offset");
+ size_t output_arg = k.add_arg<result_type *>(memory_object::global_memory, "output");
+ size_t output_offset_arg = k.add_arg<uint_>("output_offset");
+
+ k <<
+ k.decl<result_type>("result") << " = \n" <<
+ first[k.expr<uint_>("offset")] << ";\n" <<
+ "for(uint i = offset + 1; i < count; i++)\n" <<
+ " result = " <<
+ function(k.var<result_type>("result"),
+ first[k.var<uint_>("i")]) << ";\n" <<
+ "output[output_offset] = result;\n";
+
+ kernel kernel = k.compile(context);
+ kernel.set_arg(count_arg, static_cast<uint_>(count));
+ kernel.set_arg(offset_arg, static_cast<uint_>(last_block_start));
+ kernel.set_arg(output_arg, result.get_buffer());
+ kernel.set_arg(output_offset_arg, static_cast<uint_>(block_count));
+
+ queue.enqueue_task(kernel);
+ }
+
+ return total_block_count;
+}
+
+template<class InputIterator, class BinaryFunction>
+inline vector<
+ typename boost::compute::result_of<
+ BinaryFunction(
+ typename std::iterator_traits<InputIterator>::value_type,
+ typename std::iterator_traits<InputIterator>::value_type
+ )
+ >::type
+>
+block_reduce(InputIterator first,
+ size_t count,
+ size_t block_size,
+ BinaryFunction function,
+ command_queue &queue)
+{
+ typedef typename
+ std::iterator_traits<InputIterator>::value_type
+ input_type;
+ typedef typename
+ boost::compute::result_of<BinaryFunction(input_type, input_type)>::type
+ result_type;
+
+ const context &context = queue.get_context();
+ size_t total_block_count =
+ static_cast<size_t>(std::ceil(float(count) / 2.f / float(block_size)));
+ vector<result_type> result_vector(total_block_count, context);
+
+ reduce(first, count, result_vector.begin(), block_size, function, queue);
+
+ return result_vector;
+}
+
+template<class InputIterator, class OutputIterator, class BinaryFunction>
+inline void generic_reduce(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ BinaryFunction function,
+ command_queue &queue)
+{
+ typedef typename
+ std::iterator_traits<InputIterator>::value_type
+ input_type;
+ typedef typename
+ boost::compute::result_of<BinaryFunction(input_type, input_type)>::type
+ result_type;
+
+ const device &device = queue.get_device();
+ const context &context = queue.get_context();
+
+ size_t count = detail::iterator_range_size(first, last);
+
+ if(device.type() & device::cpu){
+ boost::compute::vector<result_type> value(1, context);
+ detail::serial_reduce(first, last, value.begin(), function, queue);
+ boost::compute::copy_n(value.begin(), 1, result, queue);
+ }
+ else {
+ size_t block_size = 256;
+
+ // first pass
+ vector<result_type> results = detail::block_reduce(first,
+ count,
+ block_size,
+ function,
+ queue);
+
+ if(results.size() > 1){
+ detail::inplace_reduce(results.begin(),
+ results.end(),
+ function,
+ queue);
+ }
+
+ boost::compute::copy_n(results.begin(), 1, result, queue);
+ }
+}
+
+template<class InputIterator, class OutputIterator, class T>
+inline void dispatch_reduce(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ const plus<T> &function,
+ command_queue &queue)
+{
+ const context &context = queue.get_context();
+ const device &device = queue.get_device();
+
+ // reduce to temporary buffer on device
+ array<T, 1> tmp(context);
+ if(device.type() & device::cpu){
+ detail::serial_reduce(first, last, tmp.begin(), function, queue);
+ }
+ else {
+ reduce_on_gpu(first, last, tmp.begin(), function, queue);
+ }
+
+ // copy to result iterator
+ copy_n(tmp.begin(), 1, result, queue);
+}
+
+template<class InputIterator, class OutputIterator, class BinaryFunction>
+inline void dispatch_reduce(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ BinaryFunction function,
+ command_queue &queue)
+{
+ generic_reduce(first, last, result, function, queue);
+}
+
+} // end detail namespace
+
+/// Returns the result of applying \p function to the elements in the
+/// range [\p first, \p last).
+///
+/// If no function is specified, \c plus will be used.
+///
+/// \param first first element in the input range
+/// \param last last element in the input range
+/// \param result iterator pointing to the output
+/// \param function binary reduction function
+/// \param queue command queue to perform the operation
+///
+/// The \c reduce() algorithm assumes that the binary reduction function is
+/// associative. When used with non-associative functions the result may
+/// be non-deterministic and vary in precision. Notably this affects the
+/// \c plus<float>() function as floating-point addition is not associative
+/// and may produce slightly different results than a serial algorithm.
+///
+/// This algorithm supports both host and device iterators for the
+/// result argument. This allows for values to be reduced and copied
+/// to the host all with a single function call.
+///
+/// For example, to calculate the sum of the values in a device vector and
+/// copy the result to a value on the host:
+///
+/// \snippet test/test_reduce.cpp sum_int
+///
+/// Note that while the the \c reduce() algorithm is conceptually identical to
+/// the \c accumulate() algorithm, its implementation is substantially more
+/// efficient on parallel hardware. For more information, see the documentation
+/// on the \c accumulate() algorithm.
+///
+/// \see accumulate()
+template<class InputIterator, class OutputIterator, class BinaryFunction>
+inline void reduce(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ BinaryFunction function,
+ command_queue &queue = system::default_queue())
+{
+ if(first == last){
+ return;
+ }
+
+ detail::dispatch_reduce(first, last, result, function, queue);
+}
+
+/// \overload
+template<class InputIterator, class OutputIterator>
+inline void reduce(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type T;
+
+ if(first == last){
+ return;
+ }
+
+ detail::dispatch_reduce(first, last, result, plus<T>(), queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_REDUCE_HPP
diff --git a/boost/compute/algorithm/reduce_by_key.hpp b/boost/compute/algorithm/reduce_by_key.hpp
new file mode 100644
index 0000000000..87c73e887f
--- /dev/null
+++ b/boost/compute/algorithm/reduce_by_key.hpp
@@ -0,0 +1,118 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2015 Jakub Szuppe <j.szuppe@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_REDUCE_BY_KEY_HPP
+#define BOOST_COMPUTE_ALGORITHM_REDUCE_BY_KEY_HPP
+
+#include <iterator>
+#include <utility>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/device.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/detail/reduce_by_key.hpp>
+
+namespace boost {
+namespace compute {
+
+/// The \c reduce_by_key() algorithm performs reduction for each contiguous
+/// subsequence of values determinate by equivalent keys.
+///
+/// Returns a pair of iterators at the end of the ranges [\p keys_result, keys_result_last)
+/// and [\p values_result, \p values_result_last).
+///
+/// If no function is specified, \c plus will be used.
+/// If no predicate is specified, \c equal_to will be used.
+///
+/// \param keys_first the first key
+/// \param keys_last the last key
+/// \param values_first the first input value
+/// \param keys_result iterator pointing to the key output
+/// \param values_result iterator pointing to the reduced value output
+/// \param function binary reduction function
+/// \param predicate binary predicate which returns true only if two keys are equal
+/// \param queue command queue to perform the operation
+///
+/// The \c reduce_by_key() algorithm assumes that the binary reduction function
+/// is associative. When used with non-associative functions the result may
+/// be non-deterministic and vary in precision. Notably this affects the
+/// \c plus<float>() function as floating-point addition is not associative
+/// and may produce slightly different results than a serial algorithm.
+///
+/// For example, to calculate the sum of the values for each key:
+///
+/// \snippet test/test_reduce_by_key.cpp reduce_by_key_int
+///
+/// \see reduce()
+template<class InputKeyIterator, class InputValueIterator,
+ class OutputKeyIterator, class OutputValueIterator,
+ class BinaryFunction, class BinaryPredicate>
+inline std::pair<OutputKeyIterator, OutputValueIterator>
+reduce_by_key(InputKeyIterator keys_first,
+ InputKeyIterator keys_last,
+ InputValueIterator values_first,
+ OutputKeyIterator keys_result,
+ OutputValueIterator values_result,
+ BinaryFunction function,
+ BinaryPredicate predicate,
+ command_queue &queue = system::default_queue())
+{
+ return detail::dispatch_reduce_by_key(keys_first, keys_last, values_first,
+ keys_result, values_result,
+ function, predicate,
+ queue);
+}
+
+/// \overload
+template<class InputKeyIterator, class InputValueIterator,
+ class OutputKeyIterator, class OutputValueIterator,
+ class BinaryFunction>
+inline std::pair<OutputKeyIterator, OutputValueIterator>
+reduce_by_key(InputKeyIterator keys_first,
+ InputKeyIterator keys_last,
+ InputValueIterator values_first,
+ OutputKeyIterator keys_result,
+ OutputValueIterator values_result,
+ BinaryFunction function,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputKeyIterator>::value_type key_type;
+
+ return reduce_by_key(keys_first, keys_last, values_first,
+ keys_result, values_result,
+ function, equal_to<key_type>(),
+ queue);
+}
+
+/// \overload
+template<class InputKeyIterator, class InputValueIterator,
+ class OutputKeyIterator, class OutputValueIterator>
+inline std::pair<OutputKeyIterator, OutputValueIterator>
+reduce_by_key(InputKeyIterator keys_first,
+ InputKeyIterator keys_last,
+ InputValueIterator values_first,
+ OutputKeyIterator keys_result,
+ OutputValueIterator values_result,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputKeyIterator>::value_type key_type;
+ typedef typename std::iterator_traits<InputValueIterator>::value_type value_type;
+
+ return reduce_by_key(keys_first, keys_last, values_first,
+ keys_result, values_result,
+ plus<value_type>(), equal_to<key_type>(),
+ queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_REDUCE_BY_KEY_HPP
diff --git a/boost/compute/algorithm/remove.hpp b/boost/compute/algorithm/remove.hpp
new file mode 100644
index 0000000000..98feb1f9d8
--- /dev/null
+++ b/boost/compute/algorithm/remove.hpp
@@ -0,0 +1,54 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_REMOVE_HPP
+#define BOOST_COMPUTE_ALGORITHM_REMOVE_HPP
+
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/remove_if.hpp>
+#include <boost/compute/type_traits/vector_size.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Removes each element equal to \p value in the range [\p first,
+/// \p last).
+///
+/// \see remove_if()
+template<class Iterator, class T>
+inline Iterator remove(Iterator first,
+ Iterator last,
+ const T &value,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<Iterator>::value_type value_type;
+
+ using ::boost::compute::_1;
+ using ::boost::compute::lambda::all;
+
+ if(vector_size<value_type>::value == 1){
+ return ::boost::compute::remove_if(first,
+ last,
+ _1 == value,
+ queue);
+ }
+ else {
+ return ::boost::compute::remove_if(first,
+ last,
+ all(_1 == value),
+ queue);
+ }
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_REMOVE_HPP
diff --git a/boost/compute/algorithm/remove_if.hpp b/boost/compute/algorithm/remove_if.hpp
new file mode 100644
index 0000000000..5e416bef88
--- /dev/null
+++ b/boost/compute/algorithm/remove_if.hpp
@@ -0,0 +1,47 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_REMOVE_IF_HPP
+#define BOOST_COMPUTE_ALGORITHM_REMOVE_IF_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy_if.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/functional/logical.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Removes each element for which \p predicate returns \c true in the
+/// range [\p first, \p last).
+///
+/// \see remove()
+template<class Iterator, class Predicate>
+inline Iterator remove_if(Iterator first,
+ Iterator last,
+ Predicate predicate,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<Iterator>::value_type value_type;
+
+ // temporary storage for the input data
+ ::boost::compute::vector<value_type> tmp(first, last, queue);
+
+ return ::boost::compute::copy_if(tmp.begin(),
+ tmp.end(),
+ first,
+ not1(predicate),
+ queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_REMOVE_IF_HPP
diff --git a/boost/compute/algorithm/replace.hpp b/boost/compute/algorithm/replace.hpp
new file mode 100644
index 0000000000..fd649a2fad
--- /dev/null
+++ b/boost/compute/algorithm/replace.hpp
@@ -0,0 +1,90 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_REPLACE_HPP
+#define BOOST_COMPUTE_ALGORITHM_REPLACE_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class Iterator, class T>
+class replace_kernel : public meta_kernel
+{
+public:
+ replace_kernel()
+ : meta_kernel("replace")
+ {
+ m_count = 0;
+ }
+
+ void set_range(Iterator first, Iterator last)
+ {
+ m_count = detail::iterator_range_size(first, last);
+
+ *this <<
+ "const uint i = get_global_id(0);\n" <<
+ "if(" << first[var<cl_uint>("i")] << " == " << var<T>("old_value") << ")\n" <<
+ " " << first[var<cl_uint>("i")] << '=' << var<T>("new_value") << ";\n";
+ }
+
+ void set_old_value(const T &old_value)
+ {
+ add_set_arg<T>("old_value", old_value);
+ }
+
+ void set_new_value(const T &new_value)
+ {
+ add_set_arg<T>("new_value", new_value);
+ }
+
+ void exec(command_queue &queue)
+ {
+ if(m_count == 0){
+ // nothing to do
+ return;
+ }
+
+ exec_1d(queue, 0, m_count);
+ }
+
+private:
+ size_t m_count;
+};
+
+} // end detail namespace
+
+/// Replaces each instance of \p old_value in the range [\p first,
+/// \p last) with \p new_value.
+template<class Iterator, class T>
+inline void replace(Iterator first,
+ Iterator last,
+ const T &old_value,
+ const T &new_value,
+ command_queue &queue = system::default_queue())
+{
+ detail::replace_kernel<Iterator, T> kernel;
+
+ kernel.set_range(first, last);
+ kernel.set_old_value(old_value);
+ kernel.set_new_value(new_value);
+
+ kernel.exec(queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_REPLACE_HPP
diff --git a/boost/compute/algorithm/replace_copy.hpp b/boost/compute/algorithm/replace_copy.hpp
new file mode 100644
index 0000000000..7224bd3ae6
--- /dev/null
+++ b/boost/compute/algorithm/replace_copy.hpp
@@ -0,0 +1,62 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_REPLACE_COPY_HPP
+#define BOOST_COMPUTE_ALGORITHM_REPLACE_COPY_HPP
+
+#include <iterator>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/replace.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Copies the value in the range [\p first, \p last) to the range
+/// beginning at \p result while replacing each instance of \p old_value
+/// with \p new_value.
+///
+/// \see replace()
+template<class InputIterator, class OutputIterator, class T>
+inline OutputIterator
+replace_copy(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ const T &old_value,
+ const T &new_value,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<OutputIterator>::difference_type difference_type;
+
+ difference_type count = std::distance(first, last);
+ if(count == 0){
+ return result;
+ }
+
+ // copy data to result
+ ::boost::compute::copy(first, last, result, queue);
+
+ // replace in result
+ ::boost::compute::replace(result,
+ result + count,
+ old_value,
+ new_value,
+ queue);
+
+ // return iterator to the end of result
+ return result + count;
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_REPLACE_COPY_HPP
diff --git a/boost/compute/algorithm/reverse.hpp b/boost/compute/algorithm/reverse.hpp
new file mode 100644
index 0000000000..b6a9e8098c
--- /dev/null
+++ b/boost/compute/algorithm/reverse.hpp
@@ -0,0 +1,74 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_REVERSE_HPP
+#define BOOST_COMPUTE_ALGORITHM_REVERSE_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class Iterator>
+struct reverse_kernel : public meta_kernel
+{
+ reverse_kernel(Iterator first, Iterator last)
+ : meta_kernel("reverse")
+ {
+ typedef typename std::iterator_traits<Iterator>::value_type value_type;
+
+ // store size of the range
+ m_size = detail::iterator_range_size(first, last);
+ add_set_arg<const cl_uint>("size", static_cast<const cl_uint>(m_size));
+
+ *this <<
+ decl<cl_uint>("i") << " = get_global_id(0);\n" <<
+ decl<cl_uint>("j") << " = size - get_global_id(0) - 1;\n" <<
+ decl<value_type>("tmp") << "=" << first[var<cl_uint>("i")] << ";\n" <<
+ first[var<cl_uint>("i")] << "=" << first[var<cl_uint>("j")] << ";\n" <<
+ first[var<cl_uint>("j")] << "= tmp;\n";
+ }
+
+ void exec(command_queue &queue)
+ {
+ exec_1d(queue, 0, m_size / 2);
+ }
+
+ size_t m_size;
+};
+
+} // end detail namespace
+
+/// Reverses the elements in the range [\p first, \p last).
+///
+/// \see reverse_copy()
+template<class Iterator>
+inline void reverse(Iterator first,
+ Iterator last,
+ command_queue &queue = system::default_queue())
+{
+ size_t count = detail::iterator_range_size(first, last);
+ if(count < 2){
+ return;
+ }
+
+ detail::reverse_kernel<Iterator> kernel(first, last);
+
+ kernel.exec(queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_REVERSE_HPP
diff --git a/boost/compute/algorithm/reverse_copy.hpp b/boost/compute/algorithm/reverse_copy.hpp
new file mode 100644
index 0000000000..c839f44651
--- /dev/null
+++ b/boost/compute/algorithm/reverse_copy.hpp
@@ -0,0 +1,79 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_REVERSE_COPY_HPP
+#define BOOST_COMPUTE_ALGORITHM_REVERSE_COPY_HPP
+
+#include <iterator>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/reverse.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class Iterator, class OutputIterator>
+struct reverse_copy_kernel : public meta_kernel
+{
+ reverse_copy_kernel(Iterator first, Iterator last, OutputIterator result)
+ : meta_kernel("reverse_copy")
+ {
+ // store size of the range
+ m_size = detail::iterator_range_size(first, last);
+ add_set_arg<const cl_uint>("size", static_cast<const cl_uint>(m_size));
+
+ *this <<
+ decl<cl_uint>("i") << " = get_global_id(0);\n" <<
+ decl<cl_uint>("j") << " = size - get_global_id(0) - 1;\n" <<
+ result[var<cl_uint>("j")] << "=" << first[var<cl_uint>("i")] << ";\n";
+ }
+
+ void exec(command_queue &queue)
+ {
+ exec_1d(queue, 0, m_size);
+ }
+
+ size_t m_size;
+};
+
+} // end detail namespace
+
+/// Copies the elements in the range [\p first, \p last) in reversed
+/// order to the range beginning at \p result.
+///
+/// \see reverse()
+template<class InputIterator, class OutputIterator>
+inline OutputIterator
+reverse_copy(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<OutputIterator>::difference_type difference_type;
+
+ difference_type count = std::distance(first, last);
+
+ detail::reverse_copy_kernel<InputIterator, OutputIterator>
+ kernel(first, last, result);
+
+ // run kernel
+ kernel.exec(queue);
+
+ // return iterator to the end of result
+ return result + count;
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_REVERSE_COPY_HPP
diff --git a/boost/compute/algorithm/rotate.hpp b/boost/compute/algorithm/rotate.hpp
new file mode 100644
index 0000000000..54cb073cc2
--- /dev/null
+++ b/boost/compute/algorithm/rotate.hpp
@@ -0,0 +1,54 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_ROTATE_HPP
+#define BOOST_COMPUTE_ALGORITHM_ROTATE_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/container/vector.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Performs left rotation such that element at \p n_first comes to the
+/// beginning.
+///
+/// \see rotate_copy()
+template<class InputIterator>
+inline void rotate(InputIterator first,
+ InputIterator n_first,
+ InputIterator last,
+ command_queue &queue = system::default_queue())
+{
+ //Handle trivial cases
+ if (n_first==first || n_first==last)
+ {
+ return;
+ }
+
+ //Handle others
+ typedef typename std::iterator_traits<InputIterator>::value_type T;
+
+ size_t count = detail::iterator_range_size(first, n_first);
+ size_t count2 = detail::iterator_range_size(first, last);
+
+ const context &context = queue.get_context();
+ vector<T> temp(count2, context);
+ ::boost::compute::copy(first, last, temp.begin(), queue);
+
+ ::boost::compute::copy(temp.begin()+count, temp.end(), first, queue);
+ ::boost::compute::copy(temp.begin(), temp.begin()+count, last-count, queue);
+}
+
+} //end compute namespace
+} //end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_ROTATE_HPP
diff --git a/boost/compute/algorithm/rotate_copy.hpp b/boost/compute/algorithm/rotate_copy.hpp
new file mode 100644
index 0000000000..fa1b44c5e5
--- /dev/null
+++ b/boost/compute/algorithm/rotate_copy.hpp
@@ -0,0 +1,41 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_ROTATE_COPY_HPP
+#define BOOST_COMPUTE_ALGORITHM_ROTATE_COPY_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Performs left rotation such that element at n_first comes to the
+/// beginning and the output is stored in range starting at result.
+///
+/// \see rotate()
+template<class InputIterator, class OutputIterator>
+inline void rotate_copy(InputIterator first,
+ InputIterator n_first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
+{
+ size_t count = detail::iterator_range_size(first, n_first);
+ size_t count2 = detail::iterator_range_size(n_first, last);
+
+ ::boost::compute::copy(first+count, last, result, queue);
+ ::boost::compute::copy(first, first+count, result+count2, queue);
+}
+
+} //end compute namespace
+} //end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_ROTATE_COPY_HPP
diff --git a/boost/compute/algorithm/scatter.hpp b/boost/compute/algorithm/scatter.hpp
new file mode 100644
index 0000000000..bea4201628
--- /dev/null
+++ b/boost/compute/algorithm/scatter.hpp
@@ -0,0 +1,99 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_SCATTER_HPP
+#define BOOST_COMPUTE_ALGORITHM_SCATTER_HPP
+
+#include <boost/algorithm/string/replace.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/exception.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator, class MapIterator, class OutputIterator>
+class scatter_kernel : meta_kernel
+{
+public:
+ scatter_kernel() : meta_kernel("scatter")
+ {}
+
+ void set_range(InputIterator first,
+ InputIterator last,
+ MapIterator map,
+ OutputIterator result)
+ {
+ m_count = iterator_range_size(first, last);
+ m_input_offset = first.get_index();
+ m_output_offset = result.get_index();
+
+ m_input_offset_arg = add_arg<uint_>("input_offset");
+ m_output_offset_arg = add_arg<uint_>("output_offset");
+
+ *this <<
+ "const uint i = get_global_id(0);\n" <<
+ "uint i1 = " << map[expr<uint_>("i")] <<
+ " + output_offset;\n" <<
+ "uint i2 = i + input_offset;\n" <<
+ result[expr<uint_>("i1")] << "=" <<
+ first[expr<uint_>("i2")] << ";\n";
+ }
+
+ event exec(command_queue &queue)
+ {
+ if(m_count == 0) {
+ return event();
+ }
+
+ set_arg(m_input_offset_arg, uint_(m_input_offset));
+ set_arg(m_output_offset_arg, uint_(m_output_offset));
+
+ return exec_1d(queue, 0, m_count);
+ }
+
+private:
+ size_t m_count;
+ size_t m_input_offset;
+ size_t m_input_offset_arg;
+ size_t m_output_offset;
+ size_t m_output_offset_arg;
+};
+
+} // end detail namespace
+
+/// Copies the elements from the range [\p first, \p last) to the range
+/// beginning at \p result using the output indices from the range beginning
+/// at \p map.
+///
+/// \see gather()
+template<class InputIterator, class MapIterator, class OutputIterator>
+inline void scatter(InputIterator first,
+ InputIterator last,
+ MapIterator map,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
+{
+ detail::scatter_kernel<InputIterator, MapIterator, OutputIterator> kernel;
+
+ kernel.set_range(first, last, map, result);
+ kernel.exec(queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_SCATTER_HPP
diff --git a/boost/compute/algorithm/scatter_if.hpp b/boost/compute/algorithm/scatter_if.hpp
new file mode 100644
index 0000000000..159edd8c86
--- /dev/null
+++ b/boost/compute/algorithm/scatter_if.hpp
@@ -0,0 +1,119 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2015 Jakub Pola <jakub.pola@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_SCATTER_IF_HPP
+#define BOOST_COMPUTE_ALGORITHM_SCATTER_IF_HPP
+
+#include <boost/algorithm/string/replace.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/exception.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator, class MapIterator, class StencilIterator, class OutputIterator, class Predicate>
+class scatter_if_kernel : meta_kernel
+{
+public:
+ scatter_if_kernel() : meta_kernel("scatter_if")
+ {}
+
+ void set_range(InputIterator first,
+ InputIterator last,
+ MapIterator map,
+ StencilIterator stencil,
+ OutputIterator result,
+ Predicate predicate)
+ {
+ m_count = iterator_range_size(first, last);
+ m_input_offset = first.get_index();
+ m_output_offset = result.get_index();
+
+ m_input_offset_arg = add_arg<uint_>("input_offset");
+ m_output_offset_arg = add_arg<uint_>("output_offset");
+
+ *this <<
+ "const uint i = get_global_id(0);\n" <<
+ "uint i1 = " << map[expr<uint_>("i")] <<
+ " + output_offset;\n" <<
+ "uint i2 = i + input_offset;\n" <<
+ if_(predicate(stencil[expr<uint_>("i")])) << "\n" <<
+ result[expr<uint_>("i1")] << "=" <<
+ first[expr<uint_>("i2")] << ";\n";
+ }
+
+ event exec(command_queue &queue)
+ {
+ if(m_count == 0) {
+ return event();
+ }
+
+ set_arg(m_input_offset_arg, uint_(m_input_offset));
+ set_arg(m_output_offset_arg, uint_(m_output_offset));
+
+ return exec_1d(queue, 0, m_count);
+ }
+
+private:
+ size_t m_count;
+ size_t m_input_offset;
+ size_t m_input_offset_arg;
+ size_t m_output_offset;
+ size_t m_output_offset_arg;
+};
+
+} // end detail namespace
+
+/// Copies the elements from the range [\p first, \p last) to the range
+/// beginning at \p result using the output indices from the range beginning
+/// at \p map if stencil is resolved to true. By default the predicate is
+/// an identity
+///
+///
+template<class InputIterator, class MapIterator, class StencilIterator, class OutputIterator,
+ class Predicate>
+inline void scatter_if(InputIterator first,
+ InputIterator last,
+ MapIterator map,
+ StencilIterator stencil,
+ OutputIterator result,
+ Predicate predicate,
+ command_queue &queue = system::default_queue())
+{
+ detail::scatter_if_kernel<InputIterator, MapIterator, StencilIterator, OutputIterator, Predicate> kernel;
+
+ kernel.set_range(first, last, map, stencil, result, predicate);
+ kernel.exec(queue);
+}
+
+template<class InputIterator, class MapIterator, class StencilIterator, class OutputIterator>
+inline void scatter_if(InputIterator first,
+ InputIterator last,
+ MapIterator map,
+ StencilIterator stencil,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<StencilIterator>::value_type T;
+
+ scatter_if(first, last, map, stencil, result, identity<T>(), queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_SCATTER_IF_HPP
diff --git a/boost/compute/algorithm/search.hpp b/boost/compute/algorithm/search.hpp
new file mode 100644
index 0000000000..3d3d035b3c
--- /dev/null
+++ b/boost/compute/algorithm/search.hpp
@@ -0,0 +1,73 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_SEARCH_HPP
+#define BOOST_COMPUTE_ALGORITHM_SEARCH_HPP
+
+#include <boost/compute/algorithm/detail/search_all.hpp>
+#include <boost/compute/algorithm/find.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/system.hpp>
+
+namespace boost {
+namespace compute {
+
+///
+/// \brief Substring matching algorithm
+///
+/// Searches for the first match of the pattern [p_first, p_last)
+/// in text [t_first, t_last).
+/// \return Iterator pointing to beginning of first occurrence
+///
+/// \param t_first Iterator pointing to start of text
+/// \param t_last Iterator pointing to end of text
+/// \param p_first Iterator pointing to start of pattern
+/// \param p_last Iterator pointing to end of pattern
+/// \param queue Queue on which to execute
+///
+template<class TextIterator, class PatternIterator>
+inline TextIterator search(TextIterator t_first,
+ TextIterator t_last,
+ PatternIterator p_first,
+ PatternIterator p_last,
+ command_queue &queue = system::default_queue())
+{
+ // there is no need to check if pattern starts at last n - 1 indices
+ vector<uint_> matching_indices(
+ detail::iterator_range_size(t_first, t_last)
+ - detail::iterator_range_size(p_first, p_last) + 1,
+ queue.get_context()
+ );
+
+ // search_kernel puts value 1 at every index in vector where pattern starts at
+ detail::search_kernel<PatternIterator,
+ TextIterator,
+ vector<uint_>::iterator> kernel;
+
+ kernel.set_range(p_first, p_last, t_first, t_last, matching_indices.begin());
+ kernel.exec(queue);
+
+ vector<uint_>::iterator index = ::boost::compute::find(
+ matching_indices.begin(), matching_indices.end(), uint_(1), queue
+ );
+
+ // pattern was not found
+ if(index == matching_indices.end())
+ return t_last;
+
+ return t_first + detail::iterator_range_size(matching_indices.begin(), index);
+}
+
+} //end compute namespace
+} //end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_SEARCH_HPP
diff --git a/boost/compute/algorithm/search_n.hpp b/boost/compute/algorithm/search_n.hpp
new file mode 100644
index 0000000000..9e03111bb0
--- /dev/null
+++ b/boost/compute/algorithm/search_n.hpp
@@ -0,0 +1,140 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_SEARCH_N_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_SEARCH_N_HPP
+
+#include <iterator>
+
+#include <boost/compute/algorithm/find.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/system.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+///
+/// \brief Search kernel class
+///
+/// Subclass of meta_kernel which is capable of performing search_n
+///
+template<class TextIterator, class OutputIterator>
+class search_n_kernel : public meta_kernel
+{
+public:
+ typedef typename std::iterator_traits<TextIterator>::value_type value_type;
+
+ search_n_kernel() : meta_kernel("search_n")
+ {}
+
+ void set_range(TextIterator t_first,
+ TextIterator t_last,
+ value_type value,
+ size_t n,
+ OutputIterator result)
+ {
+ m_n = n;
+ m_n_arg = add_arg<uint_>("n");
+
+ m_value = value;
+ m_value_arg = add_arg<value_type>("value");
+
+ m_count = iterator_range_size(t_first, t_last);
+ m_count = m_count + 1 - m_n;
+
+ *this <<
+ "uint i = get_global_id(0);\n" <<
+ "uint i1 = i;\n" <<
+ "uint j;\n" <<
+ "for(j = 0; j<n; j++,i++)\n" <<
+ "{\n" <<
+ " if(value != " << t_first[expr<uint_>("i")] << ")\n" <<
+ " j = n + 1;\n" <<
+ "}\n" <<
+ "if(j == n)\n" <<
+ result[expr<uint_>("i1")] << " = 1;\n" <<
+ "else\n" <<
+ result[expr<uint_>("i1")] << " = 0;\n";
+ }
+
+ event exec(command_queue &queue)
+ {
+ if(m_count == 0) {
+ return event();
+ }
+
+ set_arg(m_n_arg, uint_(m_n));
+ set_arg(m_value_arg, m_value);
+
+ return exec_1d(queue, 0, m_count);
+ }
+
+private:
+ size_t m_n;
+ size_t m_n_arg;
+ size_t m_count;
+ value_type m_value;
+ size_t m_value_arg;
+};
+
+} //end detail namespace
+
+///
+/// \brief Substring matching algorithm
+///
+/// Searches for the first occurrence of n consecutive occurrences of
+/// value in text [t_first, t_last).
+/// \return Iterator pointing to beginning of first occurrence
+///
+/// \param t_first Iterator pointing to start of text
+/// \param t_last Iterator pointing to end of text
+/// \param n Number of times value repeats
+/// \param value Value which repeats
+/// \param queue Queue on which to execute
+///
+template<class TextIterator, class ValueType>
+inline TextIterator search_n(TextIterator t_first,
+ TextIterator t_last,
+ size_t n,
+ ValueType value,
+ command_queue &queue = system::default_queue())
+{
+ // there is no need to check if pattern starts at last n - 1 indices
+ vector<uint_> matching_indices(
+ detail::iterator_range_size(t_first, t_last) + 1 - n,
+ queue.get_context()
+ );
+
+ // search_n_kernel puts value 1 at every index in vector where pattern
+ // of n values starts at
+ detail::search_n_kernel<TextIterator,
+ vector<uint_>::iterator> kernel;
+
+ kernel.set_range(t_first, t_last, value, n, matching_indices.begin());
+ kernel.exec(queue);
+
+ vector<uint_>::iterator index = ::boost::compute::find(
+ matching_indices.begin(), matching_indices.end(), uint_(1), queue
+ );
+
+ // pattern was not found
+ if(index == matching_indices.end())
+ return t_last;
+
+ return t_first + detail::iterator_range_size(matching_indices.begin(), index);
+}
+
+} //end compute namespace
+} //end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_SEARCH_N_HPP
diff --git a/boost/compute/algorithm/set_difference.hpp b/boost/compute/algorithm/set_difference.hpp
new file mode 100644
index 0000000000..17ce7bd3f6
--- /dev/null
+++ b/boost/compute/algorithm/set_difference.hpp
@@ -0,0 +1,182 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_SET_DIFFERENCE_HPP
+#define BOOST_COMPUTE_ALGORITHM_SET_DIFFERENCE_HPP
+
+#include <iterator>
+
+#include <boost/compute/algorithm/detail/compact.hpp>
+#include <boost/compute/algorithm/detail/balanced_path.hpp>
+#include <boost/compute/algorithm/exclusive_scan.hpp>
+#include <boost/compute/algorithm/fill_n.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/system.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+///
+/// \brief Serial set difference kernel class
+///
+/// Subclass of meta_kernel to perform serial set difference after tiling
+///
+class serial_set_difference_kernel : meta_kernel
+{
+public:
+ unsigned int tile_size;
+
+ serial_set_difference_kernel() : meta_kernel("set_difference")
+ {
+ tile_size = 4;
+ }
+
+ template<class InputIterator1, class InputIterator2,
+ class InputIterator3, class InputIterator4,
+ class OutputIterator1, class OutputIterator2>
+ void set_range(InputIterator1 first1,
+ InputIterator2 first2,
+ InputIterator3 tile_first1,
+ InputIterator3 tile_last1,
+ InputIterator4 tile_first2,
+ OutputIterator1 result,
+ OutputIterator2 counts)
+ {
+ m_count = iterator_range_size(tile_first1, tile_last1) - 1;
+
+ *this <<
+ "uint i = get_global_id(0);\n" <<
+ "uint start1 = " << tile_first1[expr<uint_>("i")] << ";\n" <<
+ "uint end1 = " << tile_first1[expr<uint_>("i+1")] << ";\n" <<
+ "uint start2 = " << tile_first2[expr<uint_>("i")] << ";\n" <<
+ "uint end2 = " << tile_first2[expr<uint_>("i+1")] << ";\n" <<
+ "uint index = i*" << tile_size << ";\n" <<
+ "uint count = 0;\n" <<
+ "while(start1<end1 && start2<end2)\n" <<
+ "{\n" <<
+ " if(" << first1[expr<uint_>("start1")] << " == " <<
+ first2[expr<uint_>("start2")] << ")\n" <<
+ " {\n" <<
+ " start1++; start2++;\n" <<
+ " }\n" <<
+ " else if(" << first1[expr<uint_>("start1")] << " < " <<
+ first2[expr<uint_>("start2")] << ")\n" <<
+ " {\n" <<
+ result[expr<uint_>("index")] <<
+ " = " << first1[expr<uint_>("start1")] << ";\n" <<
+ " index++; count++;\n" <<
+ " start1++;\n" <<
+ " }\n" <<
+ " else\n" <<
+ " {\n" <<
+ " start2++;\n" <<
+ " }\n" <<
+ "}\n" <<
+ "while(start1<end1)\n" <<
+ "{\n" <<
+ result[expr<uint_>("index")] <<
+ " = " << first1[expr<uint_>("start1")] << ";\n" <<
+ " index++; count++;\n" <<
+ " start1++;\n" <<
+ "}\n" <<
+ counts[expr<uint_>("i")] << " = count;\n";
+ }
+
+ event exec(command_queue &queue)
+ {
+ if(m_count == 0) {
+ return event();
+ }
+
+ return exec_1d(queue, 0, m_count);
+ }
+
+private:
+ size_t m_count;
+};
+
+} //end detail namespace
+
+///
+/// \brief Set difference algorithm
+///
+/// Finds the difference of the sorted range [first2, last2) from the sorted
+/// range [first1, last1) and stores it in range starting at result
+/// \return Iterator pointing to end of difference
+///
+/// \param first1 Iterator pointing to start of first set
+/// \param last1 Iterator pointing to end of first set
+/// \param first2 Iterator pointing to start of second set
+/// \param last2 Iterator pointing to end of second set
+/// \param result Iterator pointing to start of range in which the difference
+/// will be stored
+/// \param queue Queue on which to execute
+///
+template<class InputIterator1, class InputIterator2, class OutputIterator>
+inline OutputIterator set_difference(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator1>::value_type value_type;
+
+ int tile_size = 1024;
+
+ int count1 = detail::iterator_range_size(first1, last1);
+ int count2 = detail::iterator_range_size(first2, last2);
+
+ vector<uint_> tile_a((count1+count2+tile_size-1)/tile_size+1, queue.get_context());
+ vector<uint_> tile_b((count1+count2+tile_size-1)/tile_size+1, queue.get_context());
+
+ // Tile the sets
+ detail::balanced_path_kernel tiling_kernel;
+ tiling_kernel.tile_size = tile_size;
+ tiling_kernel.set_range(first1, last1, first2, last2,
+ tile_a.begin()+1, tile_b.begin()+1);
+ fill_n(tile_a.begin(), 1, 0, queue);
+ fill_n(tile_b.begin(), 1, 0, queue);
+ tiling_kernel.exec(queue);
+
+ fill_n(tile_a.end()-1, 1, count1, queue);
+ fill_n(tile_b.end()-1, 1, count2, queue);
+
+ vector<value_type> temp_result(count1+count2, queue.get_context());
+ vector<uint_> counts((count1+count2+tile_size-1)/tile_size + 1, queue.get_context());
+ fill_n(counts.end()-1, 1, 0, queue);
+
+ // Find individual differences
+ detail::serial_set_difference_kernel difference_kernel;
+ difference_kernel.tile_size = tile_size;
+ difference_kernel.set_range(first1, first2, tile_a.begin(), tile_a.end(),
+ tile_b.begin(), temp_result.begin(), counts.begin());
+
+ difference_kernel.exec(queue);
+
+ exclusive_scan(counts.begin(), counts.end(), counts.begin(), queue);
+
+ // Compact the results
+ detail::compact_kernel compact_kernel;
+ compact_kernel.tile_size = tile_size;
+ compact_kernel.set_range(temp_result.begin(), counts.begin(), counts.end(), result);
+
+ compact_kernel.exec(queue);
+
+ return result + (counts.end() - 1).read(queue);
+}
+
+} //end compute namespace
+} //end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_SET_DIFFERENCE_HPP
diff --git a/boost/compute/algorithm/set_intersection.hpp b/boost/compute/algorithm/set_intersection.hpp
new file mode 100644
index 0000000000..50f291e84a
--- /dev/null
+++ b/boost/compute/algorithm/set_intersection.hpp
@@ -0,0 +1,170 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_SET_INTERSECTION_HPP
+#define BOOST_COMPUTE_ALGORITHM_SET_INTERSECTION_HPP
+
+#include <iterator>
+
+#include <boost/compute/algorithm/detail/compact.hpp>
+#include <boost/compute/algorithm/detail/balanced_path.hpp>
+#include <boost/compute/algorithm/exclusive_scan.hpp>
+#include <boost/compute/algorithm/fill_n.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/system.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+///
+/// \brief Serial set intersection kernel class
+///
+/// Subclass of meta_kernel to perform serial set intersection after tiling
+///
+class serial_set_intersection_kernel : meta_kernel
+{
+public:
+ unsigned int tile_size;
+
+ serial_set_intersection_kernel() : meta_kernel("set_intersection")
+ {
+ tile_size = 4;
+ }
+
+ template<class InputIterator1, class InputIterator2,
+ class InputIterator3, class InputIterator4,
+ class OutputIterator1, class OutputIterator2>
+ void set_range(InputIterator1 first1,
+ InputIterator2 first2,
+ InputIterator3 tile_first1,
+ InputIterator3 tile_last1,
+ InputIterator4 tile_first2,
+ OutputIterator1 result,
+ OutputIterator2 counts)
+ {
+ m_count = iterator_range_size(tile_first1, tile_last1) - 1;
+
+ *this <<
+ "uint i = get_global_id(0);\n" <<
+ "uint start1 = " << tile_first1[expr<uint_>("i")] << ";\n" <<
+ "uint end1 = " << tile_first1[expr<uint_>("i+1")] << ";\n" <<
+ "uint start2 = " << tile_first2[expr<uint_>("i")] << ";\n" <<
+ "uint end2 = " << tile_first2[expr<uint_>("i+1")] << ";\n" <<
+ "uint index = i*" << tile_size << ";\n" <<
+ "uint count = 0;\n" <<
+ "while(start1<end1 && start2<end2)\n" <<
+ "{\n" <<
+ " if(" << first1[expr<uint_>("start1")] << " == " <<
+ first2[expr<uint_>("start2")] << ")\n" <<
+ " {\n" <<
+ result[expr<uint_>("index")] <<
+ " = " << first1[expr<uint_>("start1")] << ";\n" <<
+ " index++; count++;\n" <<
+ " start1++; start2++;\n" <<
+ " }\n" <<
+ " else if(" << first1[expr<uint_>("start1")] << " < " <<
+ first2[expr<uint_>("start2")] << ")\n" <<
+ " start1++;\n" <<
+ " else start2++;\n" <<
+ "}\n" <<
+ counts[expr<uint_>("i")] << " = count;\n";
+ }
+
+ event exec(command_queue &queue)
+ {
+ if(m_count == 0) {
+ return event();
+ }
+
+ return exec_1d(queue, 0, m_count);
+ }
+
+private:
+ size_t m_count;
+};
+
+} //end detail namespace
+
+///
+/// \brief Set intersection algorithm
+///
+/// Finds the intersection of the sorted range [first1, last1) with the sorted
+/// range [first2, last2) and stores it in range starting at result
+/// \return Iterator pointing to end of intersection
+///
+/// \param first1 Iterator pointing to start of first set
+/// \param last1 Iterator pointing to end of first set
+/// \param first2 Iterator pointing to start of second set
+/// \param last2 Iterator pointing to end of second set
+/// \param result Iterator pointing to start of range in which the intersection
+/// will be stored
+/// \param queue Queue on which to execute
+///
+template<class InputIterator1, class InputIterator2, class OutputIterator>
+inline OutputIterator set_intersection(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator1>::value_type value_type;
+
+ int tile_size = 1024;
+
+ int count1 = detail::iterator_range_size(first1, last1);
+ int count2 = detail::iterator_range_size(first2, last2);
+
+ vector<uint_> tile_a((count1+count2+tile_size-1)/tile_size+1, queue.get_context());
+ vector<uint_> tile_b((count1+count2+tile_size-1)/tile_size+1, queue.get_context());
+
+ // Tile the sets
+ detail::balanced_path_kernel tiling_kernel;
+ tiling_kernel.tile_size = tile_size;
+ tiling_kernel.set_range(first1, last1, first2, last2,
+ tile_a.begin()+1, tile_b.begin()+1);
+ fill_n(tile_a.begin(), 1, 0, queue);
+ fill_n(tile_b.begin(), 1, 0, queue);
+ tiling_kernel.exec(queue);
+
+ fill_n(tile_a.end()-1, 1, count1, queue);
+ fill_n(tile_b.end()-1, 1, count2, queue);
+
+ vector<value_type> temp_result(count1+count2, queue.get_context());
+ vector<uint_> counts((count1+count2+tile_size-1)/tile_size + 1, queue.get_context());
+ fill_n(counts.end()-1, 1, 0, queue);
+
+ // Find individual intersections
+ detail::serial_set_intersection_kernel intersection_kernel;
+ intersection_kernel.tile_size = tile_size;
+ intersection_kernel.set_range(first1, first2, tile_a.begin(), tile_a.end(),
+ tile_b.begin(), temp_result.begin(), counts.begin());
+
+ intersection_kernel.exec(queue);
+
+ exclusive_scan(counts.begin(), counts.end(), counts.begin(), queue);
+
+ // Compact the results
+ detail::compact_kernel compact_kernel;
+ compact_kernel.tile_size = tile_size;
+ compact_kernel.set_range(temp_result.begin(), counts.begin(), counts.end(), result);
+
+ compact_kernel.exec(queue);
+
+ return result + (counts.end() - 1).read(queue);
+}
+
+} //end compute namespace
+} //end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_SET_INTERSECTION_HPP
diff --git a/boost/compute/algorithm/set_symmetric_difference.hpp b/boost/compute/algorithm/set_symmetric_difference.hpp
new file mode 100644
index 0000000000..6e60b38511
--- /dev/null
+++ b/boost/compute/algorithm/set_symmetric_difference.hpp
@@ -0,0 +1,194 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_SET_SYMMETRIC_DIFFERENCE_HPP
+#define BOOST_COMPUTE_ALGORITHM_SET_SYMMETRIC_DIFFERENCE_HPP
+
+#include <iterator>
+
+#include <boost/compute/algorithm/detail/compact.hpp>
+#include <boost/compute/algorithm/detail/balanced_path.hpp>
+#include <boost/compute/algorithm/exclusive_scan.hpp>
+#include <boost/compute/algorithm/fill_n.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/system.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+///
+/// \brief Serial set symmetric difference kernel class
+///
+/// Subclass of meta_kernel to perform serial set symmetric
+/// difference after tiling
+///
+class serial_set_symmetric_difference_kernel : meta_kernel
+{
+public:
+ unsigned int tile_size;
+
+ serial_set_symmetric_difference_kernel() : meta_kernel("set_symmetric_difference")
+ {
+ tile_size = 4;
+ }
+
+ template<class InputIterator1, class InputIterator2,
+ class InputIterator3, class InputIterator4,
+ class OutputIterator1, class OutputIterator2>
+ void set_range(InputIterator1 first1,
+ InputIterator2 first2,
+ InputIterator3 tile_first1,
+ InputIterator3 tile_last1,
+ InputIterator4 tile_first2,
+ OutputIterator1 result,
+ OutputIterator2 counts)
+ {
+ m_count = iterator_range_size(tile_first1, tile_last1) - 1;
+
+ *this <<
+ "uint i = get_global_id(0);\n" <<
+ "uint start1 = " << tile_first1[expr<uint_>("i")] << ";\n" <<
+ "uint end1 = " << tile_first1[expr<uint_>("i+1")] << ";\n" <<
+ "uint start2 = " << tile_first2[expr<uint_>("i")] << ";\n" <<
+ "uint end2 = " << tile_first2[expr<uint_>("i+1")] << ";\n" <<
+ "uint index = i*" << tile_size << ";\n" <<
+ "uint count = 0;\n" <<
+ "while(start1<end1 && start2<end2)\n" <<
+ "{\n" <<
+ " if(" << first1[expr<uint_>("start1")] << " == " <<
+ first2[expr<uint_>("start2")] << ")\n" <<
+ " {\n" <<
+ " start1++; start2++;\n" <<
+ " }\n" <<
+ " else if(" << first1[expr<uint_>("start1")] << " < " <<
+ first2[expr<uint_>("start2")] << ")\n" <<
+ " {\n" <<
+ result[expr<uint_>("index")] <<
+ " = " << first1[expr<uint_>("start1")] << ";\n" <<
+ " index++; count++;\n" <<
+ " start1++;\n" <<
+ " }\n" <<
+ " else\n" <<
+ " {\n" <<
+ result[expr<uint_>("index")] <<
+ " = " << first2[expr<uint_>("start2")] << ";\n" <<
+ " index++; count++;\n" <<
+ " start2++;\n" <<
+ " }\n" <<
+ "}\n" <<
+ "while(start1<end1)\n" <<
+ "{\n" <<
+ result[expr<uint_>("index")] <<
+ " = " << first1[expr<uint_>("start1")] << ";\n" <<
+ " index++; count++;\n" <<
+ " start1++;\n" <<
+ "}\n" <<
+ "while(start2<end2)\n" <<
+ "{\n" <<
+ result[expr<uint_>("index")] <<
+ " = " << first2[expr<uint_>("start2")] << ";\n" <<
+ " index++; count++;\n" <<
+ " start2++;\n" <<
+ "}\n" <<
+ counts[expr<uint_>("i")] << " = count;\n";
+ }
+
+ event exec(command_queue &queue)
+ {
+ if(m_count == 0) {
+ return event();
+ }
+
+ return exec_1d(queue, 0, m_count);
+ }
+
+private:
+ size_t m_count;
+};
+
+} //end detail namespace
+
+///
+/// \brief Set symmetric difference algorithm
+///
+/// Finds the symmetric difference of the sorted range [first2, last2) from
+/// the sorted range [first1, last1) and stores it in range starting at result
+/// \return Iterator pointing to end of symmetric difference
+///
+/// \param first1 Iterator pointing to start of first set
+/// \param last1 Iterator pointing to end of first set
+/// \param first2 Iterator pointing to start of second set
+/// \param last2 Iterator pointing to end of second set
+/// \param result Iterator pointing to start of range in which the symmetric
+/// difference will be stored
+/// \param queue Queue on which to execute
+///
+template<class InputIterator1, class InputIterator2, class OutputIterator>
+inline OutputIterator set_symmetric_difference(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator1>::value_type value_type;
+
+ int tile_size = 1024;
+
+ int count1 = detail::iterator_range_size(first1, last1);
+ int count2 = detail::iterator_range_size(first2, last2);
+
+ vector<uint_> tile_a((count1+count2+tile_size-1)/tile_size+1, queue.get_context());
+ vector<uint_> tile_b((count1+count2+tile_size-1)/tile_size+1, queue.get_context());
+
+ // Tile the sets
+ detail::balanced_path_kernel tiling_kernel;
+ tiling_kernel.tile_size = tile_size;
+ tiling_kernel.set_range(first1, last1, first2, last2,
+ tile_a.begin()+1, tile_b.begin()+1);
+ fill_n(tile_a.begin(), 1, 0, queue);
+ fill_n(tile_b.begin(), 1, 0, queue);
+ tiling_kernel.exec(queue);
+
+ fill_n(tile_a.end()-1, 1, count1, queue);
+ fill_n(tile_b.end()-1, 1, count2, queue);
+
+ vector<value_type> temp_result(count1+count2, queue.get_context());
+ vector<uint_> counts((count1+count2+tile_size-1)/tile_size + 1, queue.get_context());
+ fill_n(counts.end()-1, 1, 0, queue);
+
+ // Find individual symmetric differences
+ detail::serial_set_symmetric_difference_kernel symmetric_difference_kernel;
+ symmetric_difference_kernel.tile_size = tile_size;
+ symmetric_difference_kernel.set_range(first1, first2, tile_a.begin(),
+ tile_a.end(), tile_b.begin(),
+ temp_result.begin(), counts.begin());
+
+ symmetric_difference_kernel.exec(queue);
+
+ exclusive_scan(counts.begin(), counts.end(), counts.begin(), queue);
+
+ // Compact the results
+ detail::compact_kernel compact_kernel;
+ compact_kernel.tile_size = tile_size;
+ compact_kernel.set_range(temp_result.begin(), counts.begin(), counts.end(), result);
+
+ compact_kernel.exec(queue);
+
+ return result + (counts.end() - 1).read(queue);
+}
+
+} //end compute namespace
+} //end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_SET_SYMMETRIC_DIFFERENCE_HPP
diff --git a/boost/compute/algorithm/set_union.hpp b/boost/compute/algorithm/set_union.hpp
new file mode 100644
index 0000000000..c61f7b29b3
--- /dev/null
+++ b/boost/compute/algorithm/set_union.hpp
@@ -0,0 +1,195 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_SET_UNION_HPP
+#define BOOST_COMPUTE_ALGORITHM_SET_UNION_HPP
+
+#include <iterator>
+
+#include <boost/compute/algorithm/detail/balanced_path.hpp>
+#include <boost/compute/algorithm/detail/compact.hpp>
+#include <boost/compute/algorithm/exclusive_scan.hpp>
+#include <boost/compute/algorithm/fill_n.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/system.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+///
+/// \brief Serial set union kernel class
+///
+/// Subclass of meta_kernel to perform serial set union after tiling
+///
+class serial_set_union_kernel : meta_kernel
+{
+public:
+ unsigned int tile_size;
+
+ serial_set_union_kernel() : meta_kernel("set_union")
+ {
+ tile_size = 4;
+ }
+
+ template<class InputIterator1, class InputIterator2,
+ class InputIterator3, class InputIterator4,
+ class OutputIterator1, class OutputIterator2>
+ void set_range(InputIterator1 first1,
+ InputIterator2 first2,
+ InputIterator3 tile_first1,
+ InputIterator3 tile_last1,
+ InputIterator4 tile_first2,
+ OutputIterator1 result,
+ OutputIterator2 counts)
+ {
+ m_count = iterator_range_size(tile_first1, tile_last1) - 1;
+
+ *this <<
+ "uint i = get_global_id(0);\n" <<
+ "uint start1 = " << tile_first1[expr<uint_>("i")] << ";\n" <<
+ "uint end1 = " << tile_first1[expr<uint_>("i+1")] << ";\n" <<
+ "uint start2 = " << tile_first2[expr<uint_>("i")] << ";\n" <<
+ "uint end2 = " << tile_first2[expr<uint_>("i+1")] << ";\n" <<
+ "uint index = i*" << tile_size << ";\n" <<
+ "uint count = 0;\n" <<
+ "while(start1<end1 && start2<end2)\n" <<
+ "{\n" <<
+ " if(" << first1[expr<uint_>("start1")] << " == " <<
+ first2[expr<uint_>("start2")] << ")\n" <<
+ " {\n" <<
+ result[expr<uint_>("index")] <<
+ " = " << first1[expr<uint_>("start1")] << ";\n" <<
+ " index++; count++;\n" <<
+ " start1++; start2++;\n" <<
+ " }\n" <<
+ " else if(" << first1[expr<uint_>("start1")] << " < " <<
+ first2[expr<uint_>("start2")] << ")\n" <<
+ " {\n" <<
+ result[expr<uint_>("index")] <<
+ " = " << first1[expr<uint_>("start1")] << ";\n" <<
+ " index++; count++;\n" <<
+ " start1++;\n" <<
+ " }\n" <<
+ " else\n" <<
+ " {\n" <<
+ result[expr<uint_>("index")] <<
+ " = " << first2[expr<uint_>("start2")] << ";\n" <<
+ " index++; count++;\n" <<
+ " start2++;\n" <<
+ " }\n" <<
+ "}\n" <<
+ "while(start1<end1)\n" <<
+ "{\n" <<
+ result[expr<uint_>("index")] <<
+ " = " << first1[expr<uint_>("start1")] << ";\n" <<
+ " index++; count++;\n" <<
+ " start1++;\n" <<
+ "}\n" <<
+ "while(start2<end2)\n" <<
+ "{\n" <<
+ result[expr<uint_>("index")] <<
+ " = " << first2[expr<uint_>("start2")] << ";\n" <<
+ " index++; count++;\n" <<
+ " start2++;\n" <<
+ "}\n" <<
+ counts[expr<uint_>("i")] << " = count;\n";
+ }
+
+ event exec(command_queue &queue)
+ {
+ if(m_count == 0) {
+ return event();
+ }
+
+ return exec_1d(queue, 0, m_count);
+ }
+
+private:
+ size_t m_count;
+};
+
+} //end detail namespace
+
+///
+/// \brief Set union algorithm
+///
+/// Finds the union of the sorted range [first1, last1) with the sorted
+/// range [first2, last2) and stores it in range starting at result
+/// \return Iterator pointing to end of union
+///
+/// \param first1 Iterator pointing to start of first set
+/// \param last1 Iterator pointing to end of first set
+/// \param first2 Iterator pointing to start of second set
+/// \param last2 Iterator pointing to end of second set
+/// \param result Iterator pointing to start of range in which the union
+/// will be stored
+/// \param queue Queue on which to execute
+///
+template<class InputIterator1, class InputIterator2, class OutputIterator>
+inline OutputIterator set_union(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator1>::value_type value_type;
+
+ int tile_size = 1024;
+
+ int count1 = detail::iterator_range_size(first1, last1);
+ int count2 = detail::iterator_range_size(first2, last2);
+
+ vector<uint_> tile_a((count1+count2+tile_size-1)/tile_size+1, queue.get_context());
+ vector<uint_> tile_b((count1+count2+tile_size-1)/tile_size+1, queue.get_context());
+
+ // Tile the sets
+ detail::balanced_path_kernel tiling_kernel;
+ tiling_kernel.tile_size = tile_size;
+ tiling_kernel.set_range(first1, last1, first2, last2,
+ tile_a.begin()+1, tile_b.begin()+1);
+ fill_n(tile_a.begin(), 1, 0, queue);
+ fill_n(tile_b.begin(), 1, 0, queue);
+ tiling_kernel.exec(queue);
+
+ fill_n(tile_a.end()-1, 1, count1, queue);
+ fill_n(tile_b.end()-1, 1, count2, queue);
+
+ vector<value_type> temp_result(count1+count2, queue.get_context());
+ vector<uint_> counts((count1+count2+tile_size-1)/tile_size + 1, queue.get_context());
+ fill_n(counts.end()-1, 1, 0, queue);
+
+ // Find individual unions
+ detail::serial_set_union_kernel union_kernel;
+ union_kernel.tile_size = tile_size;
+ union_kernel.set_range(first1, first2, tile_a.begin(), tile_a.end(),
+ tile_b.begin(), temp_result.begin(), counts.begin());
+
+ union_kernel.exec(queue);
+
+ exclusive_scan(counts.begin(), counts.end(), counts.begin(), queue);
+
+ // Compact the results
+ detail::compact_kernel compact_kernel;
+ compact_kernel.tile_size = tile_size;
+ compact_kernel.set_range(temp_result.begin(), counts.begin(), counts.end(), result);
+
+ compact_kernel.exec(queue);
+
+ return result + (counts.end() - 1).read(queue);
+}
+
+} //end compute namespace
+} //end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_SET_UNION_HPP
diff --git a/boost/compute/algorithm/sort.hpp b/boost/compute/algorithm/sort.hpp
new file mode 100644
index 0000000000..b2730b3e2b
--- /dev/null
+++ b/boost/compute/algorithm/sort.hpp
@@ -0,0 +1,194 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_SORT_HPP
+#define BOOST_COMPUTE_ALGORITHM_SORT_HPP
+
+#include <iterator>
+
+#include <boost/utility/enable_if.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/detail/merge_sort_on_cpu.hpp>
+#include <boost/compute/algorithm/detail/radix_sort.hpp>
+#include <boost/compute/algorithm/detail/insertion_sort.hpp>
+#include <boost/compute/algorithm/reverse.hpp>
+#include <boost/compute/container/mapped_view.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+#include <boost/compute/type_traits/is_device_iterator.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class T>
+inline void dispatch_gpu_sort(buffer_iterator<T> first,
+ buffer_iterator<T> last,
+ less<T>,
+ command_queue &queue,
+ typename boost::enable_if_c<
+ is_radix_sortable<T>::value
+ >::type* = 0)
+{
+ size_t count = detail::iterator_range_size(first, last);
+
+ if(count < 2){
+ // nothing to do
+ return;
+ }
+ else if(count <= 32){
+ ::boost::compute::detail::serial_insertion_sort(first, last, queue);
+ }
+ else {
+ ::boost::compute::detail::radix_sort(first, last, queue);
+ }
+}
+
+template<class T>
+inline void dispatch_gpu_sort(buffer_iterator<T> first,
+ buffer_iterator<T> last,
+ greater<T> compare,
+ command_queue &queue,
+ typename boost::enable_if_c<
+ is_radix_sortable<T>::value
+ >::type* = 0)
+{
+ size_t count = detail::iterator_range_size(first, last);
+
+ if(count < 2){
+ // nothing to do
+ return;
+ }
+ else if(count <= 32){
+ ::boost::compute::detail::serial_insertion_sort(
+ first, last, compare, queue
+ );
+ }
+ else {
+ // radix sort in ascending order
+ ::boost::compute::detail::radix_sort(first, last, queue);
+
+ // reverse range to descending order
+ ::boost::compute::reverse(first, last, queue);
+ }
+}
+
+template<class Iterator, class Compare>
+inline void dispatch_gpu_sort(Iterator first,
+ Iterator last,
+ Compare compare,
+ command_queue &queue)
+{
+ ::boost::compute::detail::serial_insertion_sort(
+ first, last, compare, queue
+ );
+}
+
+// sort() for device iterators
+template<class Iterator, class Compare>
+inline void dispatch_sort(Iterator first,
+ Iterator last,
+ Compare compare,
+ command_queue &queue,
+ typename boost::enable_if<
+ is_device_iterator<Iterator>
+ >::type* = 0)
+{
+ if(queue.get_device().type() & device::gpu) {
+ dispatch_gpu_sort(first, last, compare, queue);
+ return;
+ }
+ ::boost::compute::detail::merge_sort_on_cpu(first, last, compare, queue);
+}
+
+// sort() for host iterators
+template<class Iterator, class Compare>
+inline void dispatch_sort(Iterator first,
+ Iterator last,
+ Compare compare,
+ command_queue &queue,
+ typename boost::disable_if<
+ is_device_iterator<Iterator>
+ >::type* = 0)
+{
+ typedef typename std::iterator_traits<Iterator>::value_type T;
+
+ size_t size = static_cast<size_t>(std::distance(first, last));
+
+ // create mapped buffer
+ mapped_view<T> view(
+ boost::addressof(*first), size, queue.get_context()
+ );
+
+ // sort mapped buffer
+ dispatch_sort(view.begin(), view.end(), compare, queue);
+
+ // return results to host
+ view.map(queue);
+}
+
+} // end detail namespace
+
+/// Sorts the values in the range [\p first, \p last) according to
+/// \p compare.
+///
+/// \param first first element in the range to sort
+/// \param last last element in the range to sort
+/// \param compare comparison function (by default \c less)
+/// \param queue command queue to perform the operation
+///
+/// For example, to sort a vector on the device:
+/// \code
+/// // create vector on the device with data
+/// float data[] = { 2.f, 4.f, 1.f, 3.f };
+/// boost::compute::vector<float> vec(data, data + 4, queue);
+///
+/// // sort the vector on the device
+/// boost::compute::sort(vec.begin(), vec.end(), queue);
+/// \endcode
+///
+/// The sort() algorithm can also be directly used with host iterators. This
+/// example will automatically transfer the data to the device, sort it, and
+/// then transfer the data back to the host:
+/// \code
+/// std::vector<int> data = { 9, 3, 2, 5, 1, 4, 6, 7 };
+///
+/// boost::compute::sort(data.begin(), data.end(), queue);
+/// \endcode
+///
+/// \see is_sorted()
+template<class Iterator, class Compare>
+inline void sort(Iterator first,
+ Iterator last,
+ Compare compare,
+ command_queue &queue = system::default_queue())
+{
+ ::boost::compute::detail::dispatch_sort(first, last, compare, queue);
+}
+
+/// \overload
+template<class Iterator>
+inline void sort(Iterator first,
+ Iterator last,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<Iterator>::value_type value_type;
+
+ ::boost::compute::sort(
+ first, last, ::boost::compute::less<value_type>(), queue
+ );
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_SORT_HPP
diff --git a/boost/compute/algorithm/sort_by_key.hpp b/boost/compute/algorithm/sort_by_key.hpp
new file mode 100644
index 0000000000..0e3dba81eb
--- /dev/null
+++ b/boost/compute/algorithm/sort_by_key.hpp
@@ -0,0 +1,156 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_SORT_BY_KEY_HPP
+#define BOOST_COMPUTE_ALGORITHM_SORT_BY_KEY_HPP
+
+#include <iterator>
+
+#include <boost/utility/enable_if.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/detail/merge_sort_on_cpu.hpp>
+#include <boost/compute/algorithm/detail/insertion_sort.hpp>
+#include <boost/compute/algorithm/detail/radix_sort.hpp>
+#include <boost/compute/algorithm/reverse.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+
+namespace boost {
+namespace compute {
+
+namespace detail {
+
+template<class KeyIterator, class ValueIterator>
+inline void
+dispatch_gpu_sort_by_key(KeyIterator keys_first,
+ KeyIterator keys_last,
+ ValueIterator values_first,
+ less<typename std::iterator_traits<KeyIterator>::value_type> compare,
+ command_queue &queue,
+ typename boost::enable_if_c<
+ is_radix_sortable<
+ typename std::iterator_traits<KeyIterator>::value_type
+ >::value
+ >::type* = 0)
+{
+ size_t count = detail::iterator_range_size(keys_first, keys_last);
+
+ if(count < 32){
+ detail::serial_insertion_sort_by_key(
+ keys_first, keys_last, values_first, compare, queue
+ );
+ }
+ else {
+ detail::radix_sort_by_key(
+ keys_first, keys_last, values_first, queue
+ );
+ }
+}
+
+template<class KeyIterator, class ValueIterator>
+inline void
+dispatch_gpu_sort_by_key(KeyIterator keys_first,
+ KeyIterator keys_last,
+ ValueIterator values_first,
+ greater<typename std::iterator_traits<KeyIterator>::value_type> compare,
+ command_queue &queue,
+ typename boost::enable_if_c<
+ is_radix_sortable<
+ typename std::iterator_traits<KeyIterator>::value_type
+ >::value
+ >::type* = 0)
+{
+ size_t count = detail::iterator_range_size(keys_first, keys_last);
+
+ if(count < 32){
+ detail::serial_insertion_sort_by_key(
+ keys_first, keys_last, values_first, compare, queue
+ );
+ }
+ else {
+ // radix sorts in ascending order
+ detail::radix_sort_by_key(
+ keys_first, keys_last, values_first, queue
+ );
+
+ // Reverse keys, values for descending order
+ ::boost::compute::reverse(keys_first, keys_last, queue);
+ ::boost::compute::reverse(values_first, values_first + count, queue);
+ }
+}
+
+template<class KeyIterator, class ValueIterator, class Compare>
+inline void dispatch_gpu_sort_by_key(KeyIterator keys_first,
+ KeyIterator keys_last,
+ ValueIterator values_first,
+ Compare compare,
+ command_queue &queue)
+{
+ detail::serial_insertion_sort_by_key(
+ keys_first, keys_last, values_first, compare, queue
+ );
+}
+
+template<class KeyIterator, class ValueIterator, class Compare>
+inline void dispatch_sort_by_key(KeyIterator keys_first,
+ KeyIterator keys_last,
+ ValueIterator values_first,
+ Compare compare,
+ command_queue &queue)
+{
+ if(queue.get_device().type() & device::gpu) {
+ dispatch_gpu_sort_by_key(keys_first, keys_last, values_first, compare, queue);
+ return;
+ }
+ ::boost::compute::detail::merge_sort_by_key_on_cpu(
+ keys_first, keys_last, values_first, compare, queue
+ );
+}
+
+} // end detail namespace
+
+/// Performs a key-value sort using the keys in the range [\p keys_first,
+/// \p keys_last) on the values in the range [\p values_first,
+/// \p values_first \c + (\p keys_last \c - \p keys_first)) using \p compare.
+///
+/// If no compare function is specified, \c less is used.
+///
+/// \see sort()
+template<class KeyIterator, class ValueIterator, class Compare>
+inline void sort_by_key(KeyIterator keys_first,
+ KeyIterator keys_last,
+ ValueIterator values_first,
+ Compare compare,
+ command_queue &queue = system::default_queue())
+{
+ ::boost::compute::detail::dispatch_sort_by_key(
+ keys_first, keys_last, values_first, compare, queue
+ );
+}
+
+/// \overload
+template<class KeyIterator, class ValueIterator>
+inline void sort_by_key(KeyIterator keys_first,
+ KeyIterator keys_last,
+ ValueIterator values_first,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<KeyIterator>::value_type key_type;
+
+ ::boost::compute::sort_by_key(
+ keys_first, keys_last, values_first, less<key_type>(), queue
+ );
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_SORT_BY_KEY_HPP
diff --git a/boost/compute/algorithm/stable_partition.hpp b/boost/compute/algorithm/stable_partition.hpp
new file mode 100644
index 0000000000..283b068283
--- /dev/null
+++ b/boost/compute/algorithm/stable_partition.hpp
@@ -0,0 +1,72 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_STABLE_PARTITION_HPP
+#define BOOST_COMPUTE_ALGORITHM_STABLE_PARTITION_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy_if.hpp>
+#include <boost/compute/container/vector.hpp>
+
+namespace boost {
+namespace compute {
+
+///
+/// \brief Partitioning algorithm
+///
+/// Partitions the elements in the range [\p first, \p last) according to
+/// \p predicate. The order of the elements is preserved.
+/// \return Iterator pointing to end of true values
+///
+/// \param first Iterator pointing to start of range
+/// \param last Iterator pointing to end of range
+/// \param predicate Unary predicate to be applied on each element
+/// \param queue Queue on which to execute
+///
+/// \see is_partitioned() and partition()
+///
+template<class Iterator, class UnaryPredicate>
+inline Iterator stable_partition(Iterator first,
+ Iterator last,
+ UnaryPredicate predicate,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<Iterator>::value_type value_type;
+
+ // make temporary copy of the input
+ ::boost::compute::vector<value_type> tmp(first, last, queue);
+
+ // copy true values
+ Iterator last_true =
+ ::boost::compute::copy_if(tmp.begin(),
+ tmp.end(),
+ first,
+ predicate,
+ queue);
+
+ // copy false values
+ Iterator last_false =
+ ::boost::compute::copy_if(tmp.begin(),
+ tmp.end(),
+ last_true,
+ not1(predicate),
+ queue);
+
+ // return iterator pointing to the last true value
+ return last_true;
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_STABLE_PARTITION_HPP
diff --git a/boost/compute/algorithm/stable_sort.hpp b/boost/compute/algorithm/stable_sort.hpp
new file mode 100644
index 0000000000..cd82a0a606
--- /dev/null
+++ b/boost/compute/algorithm/stable_sort.hpp
@@ -0,0 +1,99 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_STABLE_SORT_HPP
+#define BOOST_COMPUTE_ALGORITHM_STABLE_SORT_HPP
+
+#include <iterator>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/detail/merge_sort_on_cpu.hpp>
+#include <boost/compute/algorithm/detail/radix_sort.hpp>
+#include <boost/compute/algorithm/detail/insertion_sort.hpp>
+#include <boost/compute/algorithm/reverse.hpp>
+#include <boost/compute/functional/operator.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class Iterator, class Compare>
+inline void dispatch_gpu_stable_sort(Iterator first,
+ Iterator last,
+ Compare compare,
+ command_queue &queue)
+{
+ ::boost::compute::detail::serial_insertion_sort(
+ first, last, compare, queue
+ );
+}
+
+template<class T>
+inline typename boost::enable_if_c<is_radix_sortable<T>::value>::type
+dispatch_gpu_stable_sort(buffer_iterator<T> first,
+ buffer_iterator<T> last,
+ less<T>,
+ command_queue &queue)
+{
+ ::boost::compute::detail::radix_sort(first, last, queue);
+}
+
+template<class T>
+inline typename boost::enable_if_c<is_radix_sortable<T>::value>::type
+dispatch_gpu_stable_sort(buffer_iterator<T> first,
+ buffer_iterator<T> last,
+ greater<T>,
+ command_queue &queue)
+{
+ // radix sort in ascending order
+ ::boost::compute::detail::radix_sort(first, last, queue);
+
+ // reverse range to descending order
+ ::boost::compute::reverse(first, last, queue);
+}
+
+} // end detail namespace
+
+/// Sorts the values in the range [\p first, \p last) according to
+/// \p compare. The relative order of identical values is preserved.
+///
+/// \see sort(), is_sorted()
+template<class Iterator, class Compare>
+inline void stable_sort(Iterator first,
+ Iterator last,
+ Compare compare,
+ command_queue &queue = system::default_queue())
+{
+ if(queue.get_device().type() & device::gpu) {
+ ::boost::compute::detail::dispatch_gpu_stable_sort(
+ first, last, compare, queue
+ );
+ }
+ ::boost::compute::detail::merge_sort_on_cpu(first, last, compare, queue);
+}
+
+/// \overload
+template<class Iterator>
+inline void stable_sort(Iterator first,
+ Iterator last,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<Iterator>::value_type value_type;
+
+ ::boost::compute::less<value_type> less;
+
+ ::boost::compute::stable_sort(first, last, less, queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_STABLE_SORT_HPP
diff --git a/boost/compute/algorithm/stable_sort_by_key.hpp b/boost/compute/algorithm/stable_sort_by_key.hpp
new file mode 100644
index 0000000000..8a51372ede
--- /dev/null
+++ b/boost/compute/algorithm/stable_sort_by_key.hpp
@@ -0,0 +1,61 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2016 Jakub Szuppe <j.szuppe@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_STABLE_SORT_BY_KEY_HPP
+#define BOOST_COMPUTE_ALGORITHM_STABLE_SORT_BY_KEY_HPP
+
+#include <iterator>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/sort_by_key.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Performs a key-value stable sort using the keys in the range [\p keys_first,
+/// \p keys_last) on the values in the range [\p values_first,
+/// \p values_first \c + (\p keys_last \c - \p keys_first)) using \p compare.
+///
+/// If no compare function is specified, \c less is used.
+///
+/// \see sort()
+template<class KeyIterator, class ValueIterator, class Compare>
+inline void stable_sort_by_key(KeyIterator keys_first,
+ KeyIterator keys_last,
+ ValueIterator values_first,
+ Compare compare,
+ command_queue &queue = system::default_queue())
+{
+ // sort_by_key is stable
+ ::boost::compute::sort_by_key(
+ keys_first, keys_last, values_first, compare, queue
+ );
+}
+
+/// \overload
+template<class KeyIterator, class ValueIterator>
+inline void stable_sort_by_key(KeyIterator keys_first,
+ KeyIterator keys_last,
+ ValueIterator values_first,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<KeyIterator>::value_type key_type;
+
+ ::boost::compute::stable_sort_by_key(
+ keys_first, keys_last, values_first, less<key_type>(), queue
+ );
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_STABLE_SORT_BY_KEY_HPP
diff --git a/boost/compute/algorithm/swap_ranges.hpp b/boost/compute/algorithm/swap_ranges.hpp
new file mode 100644
index 0000000000..6ff3e14f6a
--- /dev/null
+++ b/boost/compute/algorithm/swap_ranges.hpp
@@ -0,0 +1,44 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_SWAP_RANGES_HPP
+#define BOOST_COMPUTE_ALGORITHM_SWAP_RANGES_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/container/vector.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Swaps the elements in the range [\p first1, \p last1) with the
+/// elements in the range beginning at \p first2.
+template<class Iterator1, class Iterator2>
+inline Iterator2 swap_ranges(Iterator1 first1,
+ Iterator1 last1,
+ Iterator2 first2,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<Iterator1>::value_type value_type;
+
+ Iterator2 last2 = first2 + std::distance(first1, last1);
+
+ ::boost::compute::vector<value_type> tmp(first1, last1, queue);
+ ::boost::compute::copy(first2, last2, first1, queue);
+ ::boost::compute::copy(tmp.begin(), tmp.end(), first2, queue);
+
+ return last2;
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_SWAP_RANGES_HPP
diff --git a/boost/compute/algorithm/transform.hpp b/boost/compute/algorithm/transform.hpp
new file mode 100644
index 0000000000..022a4988bd
--- /dev/null
+++ b/boost/compute/algorithm/transform.hpp
@@ -0,0 +1,76 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_TRANSFORM_HPP
+#define BOOST_COMPUTE_ALGORITHM_TRANSFORM_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/iterator/transform_iterator.hpp>
+#include <boost/compute/iterator/zip_iterator.hpp>
+#include <boost/compute/functional/detail/unpack.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Transforms the elements in the range [\p first, \p last) using
+/// \p transform and stores the results in the range beginning at
+/// \p result.
+///
+/// For example, to calculate the absolute value for each element in a vector:
+///
+/// \snippet test/test_transform.cpp transform_abs
+///
+/// \see copy()
+template<class InputIterator, class OutputIterator, class UnaryOperator>
+inline OutputIterator transform(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ UnaryOperator op,
+ command_queue &queue = system::default_queue())
+{
+ return copy(
+ ::boost::compute::make_transform_iterator(first, op),
+ ::boost::compute::make_transform_iterator(last, op),
+ result,
+ queue
+ );
+}
+
+/// \overload
+template<class InputIterator1,
+ class InputIterator2,
+ class OutputIterator,
+ class BinaryOperator>
+inline OutputIterator transform(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ OutputIterator result,
+ BinaryOperator op,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator1>::difference_type difference_type;
+
+ difference_type n = std::distance(first1, last1);
+
+ return transform(
+ make_zip_iterator(boost::make_tuple(first1, first2)),
+ make_zip_iterator(boost::make_tuple(last1, first2 + n)),
+ result,
+ detail::unpack(op),
+ queue
+ );
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_TRANSFORM_HPP
diff --git a/boost/compute/algorithm/transform_if.hpp b/boost/compute/algorithm/transform_if.hpp
new file mode 100644
index 0000000000..0eb0fd434e
--- /dev/null
+++ b/boost/compute/algorithm/transform_if.hpp
@@ -0,0 +1,117 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_TRANSFORM_IF_HPP
+#define BOOST_COMPUTE_ALGORITHM_TRANSFORM_IF_HPP
+
+#include <boost/compute/cl.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/count.hpp>
+#include <boost/compute/algorithm/count_if.hpp>
+#include <boost/compute/algorithm/exclusive_scan.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/iterator/discard_iterator.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator, class OutputIterator, class UnaryFunction, class Predicate>
+inline OutputIterator transform_if_impl(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ UnaryFunction function,
+ Predicate predicate,
+ bool copyIndex,
+ command_queue &queue)
+{
+ typedef typename std::iterator_traits<OutputIterator>::difference_type difference_type;
+
+ size_t count = detail::iterator_range_size(first, last);
+ if(count == 0){
+ return result;
+ }
+
+ const context &context = queue.get_context();
+
+ // storage for destination indices
+ ::boost::compute::vector<cl_uint> indices(count, context);
+
+ // write counts
+ ::boost::compute::detail::meta_kernel k1("transform_if_write_counts");
+ k1 << indices.begin()[k1.get_global_id(0)] << " = "
+ << predicate(first[k1.get_global_id(0)]) << " ? 1 : 0;\n";
+ k1.exec_1d(queue, 0, count);
+
+ // count number of elements to be copied
+ size_t copied_element_count =
+ ::boost::compute::count(indices.begin(), indices.end(), 1, queue);
+
+ // scan indices
+ ::boost::compute::exclusive_scan(
+ indices.begin(), indices.end(), indices.begin(), queue
+ );
+
+ // copy values
+ ::boost::compute::detail::meta_kernel k2("transform_if_do_copy");
+ k2 << "if(" << predicate(first[k2.get_global_id(0)]) << ")" <<
+ " " << result[indices.begin()[k2.get_global_id(0)]] << "=";
+
+ if(copyIndex){
+ k2 << k2.get_global_id(0) << ";\n";
+ }
+ else {
+ k2 << function(first[k2.get_global_id(0)]) << ";\n";
+ }
+
+ k2.exec_1d(queue, 0, count);
+
+ return result + static_cast<difference_type>(copied_element_count);
+}
+
+template<class InputIterator, class UnaryFunction, class Predicate>
+inline discard_iterator transform_if_impl(InputIterator first,
+ InputIterator last,
+ discard_iterator result,
+ UnaryFunction function,
+ Predicate predicate,
+ bool copyIndex,
+ command_queue &queue)
+{
+ (void) function;
+ (void) copyIndex;
+
+ return result + count_if(first, last, predicate, queue);
+}
+
+} // end detail namespace
+
+/// Copies each element in the range [\p first, \p last) for which
+/// \p predicate returns \c true to the range beginning at \p result.
+template<class InputIterator, class OutputIterator, class UnaryFunction, class Predicate>
+inline OutputIterator transform_if(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ UnaryFunction function,
+ Predicate predicate,
+ command_queue &queue = system::default_queue())
+{
+ return detail::transform_if_impl(
+ first, last, result, function, predicate, false, queue
+ );
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_TRANSFORM_IF_HPP
diff --git a/boost/compute/algorithm/transform_reduce.hpp b/boost/compute/algorithm/transform_reduce.hpp
new file mode 100644
index 0000000000..fbeee5a691
--- /dev/null
+++ b/boost/compute/algorithm/transform_reduce.hpp
@@ -0,0 +1,89 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_TRANSFORM_REDUCE_HPP
+#define BOOST_COMPUTE_ALGORITHM_TRANSFORM_REDUCE_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/reduce.hpp>
+#include <boost/compute/iterator/transform_iterator.hpp>
+#include <boost/compute/iterator/zip_iterator.hpp>
+#include <boost/compute/functional/detail/unpack.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Transforms each value in the range [\p first, \p last) with the unary
+/// \p transform_function and then reduces each transformed value with
+/// \p reduce_function.
+///
+/// For example, to calculate the sum of the absolute values of a vector
+/// of integers:
+///
+/// \snippet test/test_transform_reduce.cpp sum_abs_int
+///
+/// \see reduce(), inner_product()
+template<class InputIterator,
+ class OutputIterator,
+ class UnaryTransformFunction,
+ class BinaryReduceFunction>
+inline void transform_reduce(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ UnaryTransformFunction transform_function,
+ BinaryReduceFunction reduce_function,
+ command_queue &queue = system::default_queue())
+{
+ ::boost::compute::reduce(
+ ::boost::compute::make_transform_iterator(first, transform_function),
+ ::boost::compute::make_transform_iterator(last, transform_function),
+ result,
+ reduce_function,
+ queue
+ );
+}
+
+/// \overload
+template<class InputIterator1,
+ class InputIterator2,
+ class OutputIterator,
+ class BinaryTransformFunction,
+ class BinaryReduceFunction>
+inline void transform_reduce(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ OutputIterator result,
+ BinaryTransformFunction transform_function,
+ BinaryReduceFunction reduce_function,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator1>::difference_type difference_type;
+
+ difference_type n = std::distance(first1, last1);
+
+ ::boost::compute::transform_reduce(
+ ::boost::compute::make_zip_iterator(
+ boost::make_tuple(first1, first2)
+ ),
+ ::boost::compute::make_zip_iterator(
+ boost::make_tuple(last1, first2 + n)
+ ),
+ result,
+ detail::unpack(transform_function),
+ reduce_function,
+ queue
+ );
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_TRANSFORM_REDUCE_HPP
diff --git a/boost/compute/algorithm/unique.hpp b/boost/compute/algorithm/unique.hpp
new file mode 100644
index 0000000000..faa36bad9d
--- /dev/null
+++ b/boost/compute/algorithm/unique.hpp
@@ -0,0 +1,66 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_UNIQUE_HPP
+#define BOOST_COMPUTE_ALGORITHM_UNIQUE_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/unique_copy.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/functional/operator.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Removes all consecutive duplicate elements (determined by \p op) from the
+/// range [first, last). If \p op is not provided, the equality operator is
+/// used.
+///
+/// \param first first element in the input range
+/// \param last last element in the input range
+/// \param op binary operator used to check for uniqueness
+/// \param queue command queue to perform the operation
+///
+/// \return \c InputIterator to the new logical end of the range
+///
+/// \see unique_copy()
+template<class InputIterator, class BinaryPredicate>
+inline InputIterator unique(InputIterator first,
+ InputIterator last,
+ BinaryPredicate op,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ vector<value_type> temp(first, last, queue);
+
+ return ::boost::compute::unique_copy(
+ temp.begin(), temp.end(), first, op, queue
+ );
+}
+
+/// \overload
+template<class InputIterator>
+inline InputIterator unique(InputIterator first,
+ InputIterator last,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ return ::boost::compute::unique(
+ first, last, ::boost::compute::equal_to<value_type>(), queue
+ );
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_UNIQUE_HPP
diff --git a/boost/compute/algorithm/unique_copy.hpp b/boost/compute/algorithm/unique_copy.hpp
new file mode 100644
index 0000000000..2ce60a9359
--- /dev/null
+++ b/boost/compute/algorithm/unique_copy.hpp
@@ -0,0 +1,164 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_UNIQUE_COPY_HPP
+#define BOOST_COMPUTE_ALGORITHM_UNIQUE_COPY_HPP
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy_if.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/algorithm/gather.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/functional/operator.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator, class OutputIterator, class BinaryPredicate>
+inline OutputIterator serial_unique_copy(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ BinaryPredicate op,
+ command_queue &queue)
+{
+ if(first == last){
+ return result;
+ }
+
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ const context &context = queue.get_context();
+
+ size_t count = detail::iterator_range_size(first, last);
+
+ detail::meta_kernel k("serial_unique_copy");
+
+ vector<uint_> unique_count_vector(1, context);
+
+ size_t size_arg = k.add_arg<const uint_>("size");
+ size_t unique_count_arg = k.add_arg<uint_ *>(memory_object::global_memory, "unique_count");
+
+ k << k.decl<uint_>("index") << " = 0;\n"
+ << k.decl<value_type>("current") << " = " << first[k.var<uint_>("0")] << ";\n"
+ << result[k.var<uint_>("0")] << " = current;\n"
+ << "for(uint i = 1; i < size; i++){\n"
+ << " " << k.decl<value_type>("next") << " = " << first[k.var<uint_>("i")] << ";\n"
+ << " if(!" << op(k.var<value_type>("current"), k.var<value_type>("next")) << "){\n"
+ << " " << result[k.var<uint_>("++index")] << " = next;\n"
+ << " " << "current = next;\n"
+ << " }\n"
+ << "}\n"
+ << "*unique_count = index + 1;\n";
+
+ k.set_arg<const uint_>(size_arg, count);
+ k.set_arg(unique_count_arg, unique_count_vector.get_buffer());
+
+ k.exec_1d(queue, 0, 1, 1);
+
+ uint_ unique_count;
+ copy_n(unique_count_vector.begin(), 1, &unique_count, queue);
+
+ return result + unique_count;
+}
+
+template<class InputIterator, class OutputIterator, class BinaryPredicate>
+inline OutputIterator unique_copy(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ BinaryPredicate op,
+ command_queue &queue)
+{
+ if(first == last){
+ return result;
+ }
+
+ const context &context = queue.get_context();
+ size_t count = detail::iterator_range_size(first, last);
+
+ // flags marking unique elements
+ vector<uint_> flags(count, context);
+
+ // find each unique element and mark it with a one
+ transform(
+ first, last - 1, first + 1, flags.begin() + 1, not2(op), queue
+ );
+
+ // first element is always unique
+ fill_n(flags.begin(), 1, 1, queue);
+
+ // storage for desination indices
+ vector<uint_> indices(count, context);
+
+ // copy indices for each unique element
+ vector<uint_>::iterator last_index = detail::copy_index_if(
+ flags.begin(), flags.end(), indices.begin(), lambda::_1 == 1, queue
+ );
+
+ // copy unique values from input to output using the computed indices
+ gather(indices.begin(), last_index, first, result, queue);
+
+ // return an iterator to the end of the unique output range
+ return result + std::distance(indices.begin(), last_index);
+}
+
+} // end detail namespace
+
+/// Makes a copy of the range [first, last) and removes all consecutive
+/// duplicate elements (determined by \p op) from the copy. If \p op is not
+/// provided, the equality operator is used.
+///
+/// \param first first element in the input range
+/// \param last last element in the input range
+/// \param result first element in the result range
+/// \param op binary operator used to check for uniqueness
+/// \param queue command queue to perform the operation
+///
+/// \return \c OutputIterator to the end of the result range
+///
+/// \see unique()
+template<class InputIterator, class OutputIterator, class BinaryPredicate>
+inline OutputIterator unique_copy(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ BinaryPredicate op,
+ command_queue &queue = system::default_queue())
+{
+ size_t count = detail::iterator_range_size(first, last);
+ if(count < 32){
+ return detail::serial_unique_copy(first, last, result, op, queue);
+ }
+ else {
+ return detail::unique_copy(first, last, result, op, queue);
+ }
+}
+
+/// \overload
+template<class InputIterator, class OutputIterator>
+inline OutputIterator unique_copy(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ return ::boost::compute::unique_copy(
+ first, last, result, ::boost::compute::equal_to<value_type>(), queue
+ );
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_UNIQUE_COPY_HPP
diff --git a/boost/compute/algorithm/upper_bound.hpp b/boost/compute/algorithm/upper_bound.hpp
new file mode 100644
index 0000000000..a5a82d301c
--- /dev/null
+++ b/boost/compute/algorithm/upper_bound.hpp
@@ -0,0 +1,43 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_UPPER_BOUND_HPP
+#define BOOST_COMPUTE_ALGORITHM_UPPER_BOUND_HPP
+
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/detail/binary_find.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns an iterator pointing to the first element in the sorted
+/// range [\p first, \p last) that is not less than or equal to
+/// \p value.
+template<class InputIterator, class T>
+inline InputIterator
+upper_bound(InputIterator first,
+ InputIterator last,
+ const T &value,
+ command_queue &queue = system::default_queue())
+{
+ using ::boost::compute::_1;
+
+ InputIterator position =
+ detail::binary_find(first, last, _1 > value, queue);
+
+ return position;
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_UPPER_BOUND_HPP
diff --git a/boost/compute/allocator.hpp b/boost/compute/allocator.hpp
new file mode 100644
index 0000000000..e3db491b42
--- /dev/null
+++ b/boost/compute/allocator.hpp
@@ -0,0 +1,21 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALLOCATOR_HPP
+#define BOOST_COMPUTE_ALLOCATOR_HPP
+
+/// \file
+///
+/// Meta-header to include all Boost.Compute allocator headers.
+
+#include <boost/compute/allocator/buffer_allocator.hpp>
+#include <boost/compute/allocator/pinned_allocator.hpp>
+
+#endif // BOOST_COMPUTE_ALLOCATOR_HPP
diff --git a/boost/compute/allocator/buffer_allocator.hpp b/boost/compute/allocator/buffer_allocator.hpp
new file mode 100644
index 0000000000..2139a97896
--- /dev/null
+++ b/boost/compute/allocator/buffer_allocator.hpp
@@ -0,0 +1,118 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALLOCATOR_BUFFER_ALLOCATOR_HPP
+#define BOOST_COMPUTE_ALLOCATOR_BUFFER_ALLOCATOR_HPP
+
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/config.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/detail/device_ptr.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class buffer_allocator
+/// \brief The buffer_allocator class allocates memory with \ref buffer objects
+///
+/// \see buffer
+template<class T>
+class buffer_allocator
+{
+public:
+ typedef T value_type;
+ typedef detail::device_ptr<T> pointer;
+ typedef const detail::device_ptr<T> const_pointer;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ explicit buffer_allocator(const context &context)
+ : m_context(context),
+ m_mem_flags(buffer::read_write)
+ {
+ }
+
+ buffer_allocator(const buffer_allocator<T> &other)
+ : m_context(other.m_context),
+ m_mem_flags(other.m_mem_flags)
+ {
+ }
+
+ buffer_allocator<T>& operator=(const buffer_allocator<T> &other)
+ {
+ if(this != &other){
+ m_context = other.m_context;
+ m_mem_flags = other.m_mem_flags;
+ }
+
+ return *this;
+ }
+
+ #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+ buffer_allocator(buffer_allocator<T>&& other) BOOST_NOEXCEPT
+ : m_context(std::move(other.m_context)),
+ m_mem_flags(other.m_mem_flags)
+ {
+ }
+
+ buffer_allocator<T>& operator=(buffer_allocator<T>&& other) BOOST_NOEXCEPT
+ {
+ m_context = std::move(other.m_context);
+ m_mem_flags = other.m_mem_flags;
+
+ return *this;
+ }
+ #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+ ~buffer_allocator()
+ {
+ }
+
+ pointer allocate(size_type n)
+ {
+ buffer buf(m_context, n * sizeof(T), m_mem_flags);
+ clRetainMemObject(buf.get());
+ return detail::device_ptr<T>(buf);
+ }
+
+ void deallocate(pointer p, size_type n)
+ {
+ BOOST_ASSERT(p.get_buffer().get_context() == m_context);
+
+ (void) n;
+
+ clReleaseMemObject(p.get_buffer().get());
+ }
+
+ size_type max_size() const
+ {
+ return m_context.get_device().max_memory_alloc_size() / sizeof(T);
+ }
+
+ context get_context() const
+ {
+ return m_context;
+ }
+
+protected:
+ void set_mem_flags(cl_mem_flags flags)
+ {
+ m_mem_flags = flags;
+ }
+
+private:
+ context m_context;
+ cl_mem_flags m_mem_flags;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALLOCATOR_BUFFER_ALLOCATOR_HPP
diff --git a/boost/compute/allocator/pinned_allocator.hpp b/boost/compute/allocator/pinned_allocator.hpp
new file mode 100644
index 0000000000..9c85d93e79
--- /dev/null
+++ b/boost/compute/allocator/pinned_allocator.hpp
@@ -0,0 +1,53 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALLOCATOR_PINNED_ALLOCATOR_HPP
+#define BOOST_COMPUTE_ALLOCATOR_PINNED_ALLOCATOR_HPP
+
+#include <boost/compute/allocator/buffer_allocator.hpp>
+
+namespace boost {
+namespace compute {
+
+template<class T>
+class pinned_allocator : public buffer_allocator<T>
+{
+public:
+ explicit pinned_allocator(const context &context)
+ : buffer_allocator<T>(context)
+ {
+ buffer_allocator<T>::set_mem_flags(
+ buffer::read_write | buffer::alloc_host_ptr
+ );
+ }
+
+ pinned_allocator(const pinned_allocator<T> &other)
+ : buffer_allocator<T>(other)
+ {
+ }
+
+ pinned_allocator<T>& operator=(const pinned_allocator<T> &other)
+ {
+ if(this != &other){
+ buffer_allocator<T>::operator=(other);
+ }
+
+ return *this;
+ }
+
+ ~pinned_allocator()
+ {
+ }
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALLOCATOR_PINNED_ALLOCATOR_HPP
diff --git a/boost/compute/async.hpp b/boost/compute/async.hpp
new file mode 100644
index 0000000000..415dedda7d
--- /dev/null
+++ b/boost/compute/async.hpp
@@ -0,0 +1,21 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ASYNC_HPP
+#define BOOST_COMPUTE_ASYNC_HPP
+
+/// \file
+///
+/// Meta-header to include all Boost.Compute async headers.
+
+#include <boost/compute/async/future.hpp>
+#include <boost/compute/async/wait_guard.hpp>
+
+#endif // BOOST_COMPUTE_ASYNC_HPP
diff --git a/boost/compute/async/future.hpp b/boost/compute/async/future.hpp
new file mode 100644
index 0000000000..f7f7780deb
--- /dev/null
+++ b/boost/compute/async/future.hpp
@@ -0,0 +1,166 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ASYNC_FUTURE_HPP
+#define BOOST_COMPUTE_ASYNC_FUTURE_HPP
+
+#include <boost/compute/event.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class future
+/// \brief Holds the result of an asynchronous computation.
+///
+/// \see event, wait_list
+template<class T>
+class future
+{
+public:
+ future()
+ : m_event(0)
+ {
+ }
+
+ future(const T &result, const event &event)
+ : m_result(result),
+ m_event(event)
+ {
+ }
+
+ future(const future<T> &other)
+ : m_result(other.m_result),
+ m_event(other.m_event)
+ {
+ }
+
+ future& operator=(const future<T> &other)
+ {
+ if(this != &other){
+ m_result = other.m_result;
+ m_event = other.m_event;
+ }
+
+ return *this;
+ }
+
+ ~future()
+ {
+ }
+
+ /// Returns the result of the computation. This will block until
+ /// the result is ready.
+ T get()
+ {
+ wait();
+
+ return m_result;
+ }
+
+ /// Returns \c true if the future is valid.
+ bool valid() const
+ {
+ return m_event != 0;
+ }
+
+ /// Blocks until the computation is complete.
+ void wait() const
+ {
+ m_event.wait();
+ }
+
+ /// Returns the underlying event object.
+ event get_event() const
+ {
+ return m_event;
+ }
+
+private:
+ T m_result;
+ event m_event;
+};
+
+/// \internal_
+template<>
+class future<void>
+{
+public:
+ future()
+ : m_event(0)
+ {
+ }
+
+ template<class T>
+ future(const future<T> &other)
+ : m_event(other.get_event())
+ {
+ }
+
+ explicit future(const event &event)
+ : m_event(event)
+ {
+ }
+
+ template<class T>
+ future<void> &operator=(const future<T> &other)
+ {
+ m_event = other.get_event();
+
+ return *this;
+ }
+
+ future<void> &operator=(const future<void> &other)
+ {
+ if(this != &other){
+ m_event = other.m_event;
+ }
+
+ return *this;
+ }
+
+ ~future()
+ {
+ }
+
+ void get()
+ {
+ wait();
+ }
+
+ bool valid() const
+ {
+ return m_event != 0;
+ }
+
+ void wait() const
+ {
+ m_event.wait();
+ }
+
+ event get_event() const
+ {
+ return m_event;
+ }
+
+private:
+ event m_event;
+};
+
+/// \internal_
+template<class Result>
+inline future<Result> make_future(const Result &result, const event &event)
+{
+ return future<Result>(result, event);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ASYNC_FUTURE_HPP
diff --git a/boost/compute/async/wait.hpp b/boost/compute/async/wait.hpp
new file mode 100644
index 0000000000..dacf0feb0c
--- /dev/null
+++ b/boost/compute/async/wait.hpp
@@ -0,0 +1,56 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ASYNC_WAIT_HPP
+#define BOOST_COMPUTE_ASYNC_WAIT_HPP
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/utility/wait_list.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+#ifndef BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
+template<class Event>
+inline void insert_events_variadic(wait_list &l, Event&& event)
+{
+ l.insert(std::forward<Event>(event));
+}
+
+template<class Event, class... Rest>
+inline void insert_events_variadic(wait_list &l, Event&& event, Rest&&... rest)
+{
+ l.insert(std::forward<Event>(event));
+
+ insert_events_variadic(l, std::forward<Rest>(rest)...);
+}
+#endif // BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
+
+} // end detail namespace
+
+#ifndef BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
+/// Blocks until all events have completed. Events can either be \ref event
+/// objects or \ref future "future<T>" objects.
+///
+/// \see event, wait_list
+template<class... Events>
+inline void wait_for_all(Events&&... events)
+{
+ wait_list l;
+ detail::insert_events_variadic(l, std::forward<Events>(events)...);
+ l.wait();
+}
+#endif // BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ASYNC_WAIT_HPP
diff --git a/boost/compute/async/wait_guard.hpp b/boost/compute/async/wait_guard.hpp
new file mode 100644
index 0000000000..46018fa35a
--- /dev/null
+++ b/boost/compute/async/wait_guard.hpp
@@ -0,0 +1,63 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ASYNC_WAIT_GUARD_HPP
+#define BOOST_COMPUTE_ASYNC_WAIT_GUARD_HPP
+
+#include <boost/noncopyable.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class wait_guard
+/// \brief A guard object for synchronizing an operation on the device
+///
+/// The wait_guard class stores a waitable object representing an operation
+/// on a compute device (e.g. \ref event, \ref future "future<T>") and calls
+/// its \c wait() method when the guard object goes out of scope.
+///
+/// This is useful for ensuring that an OpenCL operation completes before
+/// leaving the current scope and cleaning up any resources.
+///
+/// For example:
+/// \code
+/// // enqueue a compute kernel for execution
+/// event e = queue.enqueue_nd_range_kernel(...);
+///
+/// // call e.wait() upon exiting the current scope
+/// wait_guard<event> guard(e);
+/// \endcode
+///
+/// \ref wait_list, wait_for_all()
+template<class Waitable>
+class wait_guard : boost::noncopyable
+{
+public:
+ /// Creates a new wait_guard object for \p waitable.
+ wait_guard(const Waitable &waitable)
+ : m_waitable(waitable)
+ {
+ }
+
+ /// Destroys the wait_guard object. The default implementation will call
+ /// \c wait() on the stored waitable object.
+ ~wait_guard()
+ {
+ m_waitable.wait();
+ }
+
+private:
+ Waitable m_waitable;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ASYNC_WAIT_GUARD_HPP
diff --git a/boost/compute/buffer.hpp b/boost/compute/buffer.hpp
new file mode 100644
index 0000000000..b5a48806d5
--- /dev/null
+++ b/boost/compute/buffer.hpp
@@ -0,0 +1,227 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_BUFFER_HPP
+#define BOOST_COMPUTE_BUFFER_HPP
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/exception.hpp>
+#include <boost/compute/memory_object.hpp>
+#include <boost/compute/detail/get_object_info.hpp>
+
+namespace boost {
+namespace compute {
+
+// forward declarations
+class command_queue;
+
+/// \class buffer
+/// \brief A memory buffer on a compute device.
+///
+/// The buffer class represents a memory buffer on a compute device.
+///
+/// Buffers are allocated within a compute context. For example, to allocate
+/// a memory buffer for 32 float's:
+///
+/// \snippet test/test_buffer.cpp constructor
+///
+/// Once created, data can be copied to and from the buffer using the
+/// \c enqueue_*_buffer() methods in the command_queue class. For example, to
+/// copy a set of \c int values from the host to the device:
+/// \code
+/// int data[] = { 1, 2, 3, 4 };
+///
+/// queue.enqueue_write_buffer(buf, 0, 4 * sizeof(int), data);
+/// \endcode
+///
+/// Also see the copy() algorithm for a higher-level interface to copying data
+/// between the host and the device. For a higher-level, dynamically-resizable,
+/// type-safe container for data on a compute device, use the vector<T> class.
+///
+/// Buffer objects have reference semantics. Creating a copy of a buffer
+/// object simply creates another reference to the underlying OpenCL memory
+/// object. To create an actual copy use the buffer::clone() method.
+///
+/// \see context, command_queue
+class buffer : public memory_object
+{
+public:
+ /// Creates a null buffer object.
+ buffer()
+ : memory_object()
+ {
+ }
+
+ /// Creates a buffer object for \p mem. If \p retain is \c true, the
+ /// reference count for \p mem will be incremented.
+ explicit buffer(cl_mem mem, bool retain = true)
+ : memory_object(mem, retain)
+ {
+ }
+
+ /// Create a new memory buffer in of \p size with \p flags in
+ /// \p context.
+ ///
+ /// \see_opencl_ref{clCreateBuffer}
+ buffer(const context &context,
+ size_t size,
+ cl_mem_flags flags = read_write,
+ void *host_ptr = 0)
+ {
+ cl_int error = 0;
+ m_mem = clCreateBuffer(context,
+ flags,
+ (std::max)(size, size_t(1)),
+ host_ptr,
+ &error);
+ if(!m_mem){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+ }
+
+ /// Creates a new buffer object as a copy of \p other.
+ buffer(const buffer &other)
+ : memory_object(other)
+ {
+ }
+
+ /// Copies the buffer object from \p other to \c *this.
+ buffer& operator=(const buffer &other)
+ {
+ if(this != &other){
+ memory_object::operator=(other);
+ }
+
+ return *this;
+ }
+
+ #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+ /// Move-constructs a new buffer object from \p other.
+ buffer(buffer&& other) BOOST_NOEXCEPT
+ : memory_object(std::move(other))
+ {
+ }
+
+ /// Move-assigns the buffer from \p other to \c *this.
+ buffer& operator=(buffer&& other) BOOST_NOEXCEPT
+ {
+ memory_object::operator=(std::move(other));
+
+ return *this;
+ }
+ #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+ /// Destroys the buffer object.
+ ~buffer()
+ {
+ }
+
+ /// Returns the size of the buffer in bytes.
+ size_t size() const
+ {
+ return get_memory_size();
+ }
+
+ /// \internal_
+ size_t max_size() const
+ {
+ return get_context().get_device().max_memory_alloc_size();
+ }
+
+ /// Returns information about the buffer.
+ ///
+ /// \see_opencl_ref{clGetMemObjectInfo}
+ template<class T>
+ T get_info(cl_mem_info info) const
+ {
+ return get_memory_info<T>(info);
+ }
+
+ /// \overload
+ template<int Enum>
+ typename detail::get_object_info_type<buffer, Enum>::type
+ get_info() const;
+
+ /// Creates a new buffer with a copy of the data in \c *this. Uses
+ /// \p queue to perform the copy.
+ buffer clone(command_queue &queue) const;
+
+ #if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ /// Creates a new buffer out of this buffer.
+ /// The new buffer is a sub region of this buffer.
+ /// \p flags The mem_flags which should be used to create the new buffer
+ /// \p origin The start index in this buffer
+ /// \p size The size of the new sub buffer
+ ///
+ /// \see_opencl_ref{clCreateSubBuffer}
+ ///
+ /// \opencl_version_warning{1,1}
+ buffer create_subbuffer(cl_mem_flags flags, size_t origin,
+ size_t size)
+ {
+ BOOST_ASSERT(origin + size <= this->size());
+ BOOST_ASSERT(origin % (get_context().
+ get_device().
+ get_info<CL_DEVICE_MEM_BASE_ADDR_ALIGN>() / 8) == 0);
+ cl_int error = 0;
+
+ cl_buffer_region region = { origin, size };
+
+ cl_mem mem = clCreateSubBuffer(m_mem,
+ flags,
+ CL_BUFFER_CREATE_TYPE_REGION,
+ &region,
+ &error);
+
+ if(!mem){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+
+ return buffer(mem, false);
+ }
+ #endif // CL_VERSION_1_1
+};
+
+/// \internal_ define get_info() specializations for buffer
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(buffer,
+ ((cl_mem_object_type, CL_MEM_TYPE))
+ ((cl_mem_flags, CL_MEM_FLAGS))
+ ((size_t, CL_MEM_SIZE))
+ ((void *, CL_MEM_HOST_PTR))
+ ((cl_uint, CL_MEM_MAP_COUNT))
+ ((cl_uint, CL_MEM_REFERENCE_COUNT))
+ ((cl_context, CL_MEM_CONTEXT))
+)
+
+#ifdef CL_VERSION_1_1
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(buffer,
+ ((cl_mem, CL_MEM_ASSOCIATED_MEMOBJECT))
+ ((size_t, CL_MEM_OFFSET))
+)
+#endif // CL_VERSION_1_1
+
+namespace detail {
+
+// set_kernel_arg specialization for buffer
+template<>
+struct set_kernel_arg<buffer>
+{
+ void operator()(kernel &kernel_, size_t index, const buffer &buffer_)
+ {
+ kernel_.set_arg(index, buffer_.get());
+ }
+};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_BUFFER_HPP
diff --git a/boost/compute/cl.hpp b/boost/compute/cl.hpp
new file mode 100644
index 0000000000..c439d8dfdc
--- /dev/null
+++ b/boost/compute/cl.hpp
@@ -0,0 +1,20 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_CL_HPP
+#define BOOST_COMPUTE_CL_HPP
+
+#if defined(__APPLE__)
+#include <OpenCL/cl.h>
+#else
+#include <CL/cl.h>
+#endif
+
+#endif // BOOST_COMPUTE_CL_HPP
diff --git a/boost/compute/cl_ext.hpp b/boost/compute/cl_ext.hpp
new file mode 100644
index 0000000000..0b21a12fd7
--- /dev/null
+++ b/boost/compute/cl_ext.hpp
@@ -0,0 +1,20 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_CL_EXT_HPP
+#define BOOST_COMPUTE_CL_EXT_HPP
+
+#if defined(__APPLE__)
+#include <OpenCL/cl_ext.h>
+#else
+#include <CL/cl_ext.h>
+#endif
+
+#endif // BOOST_COMPUTE_CL_EXT_HPP
diff --git a/boost/compute/closure.hpp b/boost/compute/closure.hpp
new file mode 100644
index 0000000000..6e3cbe702b
--- /dev/null
+++ b/boost/compute/closure.hpp
@@ -0,0 +1,347 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_CLOSURE_HPP
+#define BOOST_COMPUTE_CLOSURE_HPP
+
+#include <string>
+#include <sstream>
+
+#include <boost/config.hpp>
+#include <boost/fusion/adapted/boost_tuple.hpp>
+#include <boost/fusion/algorithm/iteration/for_each.hpp>
+#include <boost/mpl/for_each.hpp>
+#include <boost/mpl/transform.hpp>
+#include <boost/typeof/typeof.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/type_traits/function_traits.hpp>
+
+#include <boost/compute/cl.hpp>
+#include <boost/compute/function.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/type_traits/detail/capture_traits.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class ResultType, class ArgTuple, class CaptureTuple>
+class invoked_closure
+{
+public:
+ typedef ResultType result_type;
+
+ BOOST_STATIC_CONSTANT(
+ size_t, arity = boost::tuples::length<ArgTuple>::value
+ );
+
+ invoked_closure(const std::string &name,
+ const std::string &source,
+ const std::map<std::string, std::string> &definitions,
+ const ArgTuple &args,
+ const CaptureTuple &capture)
+ : m_name(name),
+ m_source(source),
+ m_definitions(definitions),
+ m_args(args),
+ m_capture(capture)
+ {
+ }
+
+ std::string name() const
+ {
+ return m_name;
+ }
+
+ std::string source() const
+ {
+ return m_source;
+ }
+
+ const std::map<std::string, std::string>& definitions() const
+ {
+ return m_definitions;
+ }
+
+ const ArgTuple& args() const
+ {
+ return m_args;
+ }
+
+ const CaptureTuple& capture() const
+ {
+ return m_capture;
+ }
+
+private:
+ std::string m_name;
+ std::string m_source;
+ std::map<std::string, std::string> m_definitions;
+ ArgTuple m_args;
+ CaptureTuple m_capture;
+};
+
+} // end detail namespace
+
+/// \internal_
+template<class Signature, class CaptureTuple>
+class closure
+{
+public:
+ typedef typename
+ boost::function_traits<Signature>::result_type result_type;
+
+ BOOST_STATIC_CONSTANT(
+ size_t, arity = boost::function_traits<Signature>::arity
+ );
+
+ closure(const std::string &name,
+ const CaptureTuple &capture,
+ const std::string &source)
+ : m_name(name),
+ m_source(source),
+ m_capture(capture)
+ {
+ }
+
+ ~closure()
+ {
+ }
+
+ std::string name() const
+ {
+ return m_name;
+ }
+
+ /// \internal_
+ std::string source() const
+ {
+ return m_source;
+ }
+
+ /// \internal_
+ void define(std::string name, std::string value = std::string())
+ {
+ m_definitions[name] = value;
+ }
+
+ /// \internal_
+ detail::invoked_closure<result_type, boost::tuple<>, CaptureTuple>
+ operator()() const
+ {
+ BOOST_STATIC_ASSERT_MSG(
+ arity == 0,
+ "Non-nullary closure function invoked with zero arguments"
+ );
+
+ return detail::invoked_closure<result_type, boost::tuple<>, CaptureTuple>(
+ m_name, m_source, m_definitions, boost::make_tuple(), m_capture
+ );
+ }
+
+ /// \internal_
+ template<class Arg1>
+ detail::invoked_closure<result_type, boost::tuple<Arg1>, CaptureTuple>
+ operator()(const Arg1 &arg1) const
+ {
+ BOOST_STATIC_ASSERT_MSG(
+ arity == 1,
+ "Non-unary closure function invoked with one argument"
+ );
+
+ return detail::invoked_closure<result_type, boost::tuple<Arg1>, CaptureTuple>(
+ m_name, m_source, m_definitions, boost::make_tuple(arg1), m_capture
+ );
+ }
+
+ /// \internal_
+ template<class Arg1, class Arg2>
+ detail::invoked_closure<result_type, boost::tuple<Arg1, Arg2>, CaptureTuple>
+ operator()(const Arg1 &arg1, const Arg2 &arg2) const
+ {
+ BOOST_STATIC_ASSERT_MSG(
+ arity == 2,
+ "Non-binary closure function invoked with two arguments"
+ );
+
+ return detail::invoked_closure<result_type, boost::tuple<Arg1, Arg2>, CaptureTuple>(
+ m_name, m_source, m_definitions, boost::make_tuple(arg1, arg2), m_capture
+ );
+ }
+
+ /// \internal_
+ template<class Arg1, class Arg2, class Arg3>
+ detail::invoked_closure<result_type, boost::tuple<Arg1, Arg2, Arg3>, CaptureTuple>
+ operator()(const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) const
+ {
+ BOOST_STATIC_ASSERT_MSG(
+ arity == 3,
+ "Non-ternary closure function invoked with three arguments"
+ );
+
+ return detail::invoked_closure<result_type, boost::tuple<Arg1, Arg2, Arg3>, CaptureTuple>(
+ m_name, m_source, m_definitions, boost::make_tuple(arg1, arg2, arg3), m_capture
+ );
+ }
+
+private:
+ std::string m_name;
+ std::string m_source;
+ std::map<std::string, std::string> m_definitions;
+ CaptureTuple m_capture;
+};
+
+namespace detail {
+
+struct closure_signature_argument_inserter
+{
+ closure_signature_argument_inserter(std::stringstream &s_,
+ const char *capture_string,
+ size_t last)
+ : s(s_)
+ {
+ n = 0;
+ m_last = last;
+
+ size_t capture_string_length = std::strlen(capture_string);
+ BOOST_ASSERT(capture_string[0] == '(' &&
+ capture_string[capture_string_length-1] == ')');
+ std::string capture_string_(capture_string + 1, capture_string_length - 2);
+ boost::split(m_capture_names, capture_string_ , boost::is_any_of(","));
+ }
+
+ template<class T>
+ void operator()(const T&) const
+ {
+ BOOST_ASSERT(n < m_capture_names.size());
+
+ // get captured variable name
+ std::string variable_name = m_capture_names[n];
+
+ // remove leading and trailing whitespace from variable name
+ boost::trim(variable_name);
+
+ s << capture_traits<T>::type_name() << " " << variable_name;
+ if(n+1 < m_last){
+ s << ", ";
+ }
+ n++;
+ }
+
+ mutable size_t n;
+ size_t m_last;
+ std::vector<std::string> m_capture_names;
+ std::stringstream &s;
+};
+
+template<class Signature, class CaptureTuple>
+inline std::string
+make_closure_declaration(const char *name,
+ const char *arguments,
+ const CaptureTuple &capture_tuple,
+ const char *capture_string)
+{
+ typedef typename
+ boost::function_traits<Signature>::result_type result_type;
+ typedef typename
+ boost::function_types::parameter_types<Signature>::type parameter_types;
+ typedef typename
+ mpl::size<parameter_types>::type arity_type;
+
+ std::stringstream s;
+ s << "inline " << type_name<result_type>() << " " << name;
+ s << "(";
+
+ // insert function arguments
+ signature_argument_inserter i(s, arguments, arity_type::value);
+ mpl::for_each<
+ typename mpl::transform<parameter_types, boost::add_pointer<mpl::_1>
+ >::type>(i);
+ s << ", ";
+
+ // insert capture arguments
+ closure_signature_argument_inserter j(
+ s, capture_string, boost::tuples::length<CaptureTuple>::value
+ );
+ fusion::for_each(capture_tuple, j);
+
+ s << ")";
+ return s.str();
+}
+
+// used by the BOOST_COMPUTE_CLOSURE() macro to create a closure
+// function with the given signature, name, capture, and source.
+template<class Signature, class CaptureTuple>
+inline closure<Signature, CaptureTuple>
+make_closure_impl(const char *name,
+ const char *arguments,
+ const CaptureTuple &capture,
+ const char *capture_string,
+ const std::string &source)
+{
+ std::stringstream s;
+ s << make_closure_declaration<Signature>(name, arguments, capture, capture_string);
+ s << source;
+
+ return closure<Signature, CaptureTuple>(name, capture, s.str());
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+/// Creates a closure function object with \p name and \p source.
+///
+/// \param return_type The return type for the function.
+/// \param name The name of the function.
+/// \param arguments A list of arguments for the function.
+/// \param capture A list of variables to capture.
+/// \param source The OpenCL C source code for the function.
+///
+/// For example, to create a function which checks if a 2D point is
+/// contained in a circle of a given radius:
+/// \code
+/// // radius variable declared in C++
+/// float radius = 1.5f;
+///
+/// // create a closure function which returns true if the 2D point
+/// // argument is contained within a circle of the given radius
+/// BOOST_COMPUTE_CLOSURE(bool, is_in_circle, (const float2_ p), (radius),
+/// {
+/// return sqrt(p.x*p.x + p.y*p.y) < radius;
+/// });
+///
+/// // vector of 2D points
+/// boost::compute::vector<float2_> points = ...
+///
+/// // count number of points in the circle
+/// size_t count = boost::compute::count_if(
+/// points.begin(), points.end(), is_in_circle, queue
+/// );
+/// \endcode
+///
+/// \see BOOST_COMPUTE_FUNCTION()
+#ifdef BOOST_COMPUTE_DOXYGEN_INVOKED
+#define BOOST_COMPUTE_CLOSURE(return_type, name, arguments, capture, source)
+#else
+#define BOOST_COMPUTE_CLOSURE(return_type, name, arguments, capture, ...) \
+ ::boost::compute::closure< \
+ return_type arguments, BOOST_TYPEOF(boost::tie capture) \
+ > name = \
+ ::boost::compute::detail::make_closure_impl< \
+ return_type arguments \
+ >( \
+ #name, #arguments, boost::tie capture, #capture, #__VA_ARGS__ \
+ )
+#endif
+
+#endif // BOOST_COMPUTE_CLOSURE_HPP
diff --git a/boost/compute/command_queue.hpp b/boost/compute/command_queue.hpp
new file mode 100644
index 0000000000..2a1328a959
--- /dev/null
+++ b/boost/compute/command_queue.hpp
@@ -0,0 +1,1881 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_COMMAND_QUEUE_HPP
+#define BOOST_COMPUTE_COMMAND_QUEUE_HPP
+
+#include <cstddef>
+#include <algorithm>
+
+#include <boost/assert.hpp>
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/event.hpp>
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/device.hpp>
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/exception.hpp>
+#include <boost/compute/image/image1d.hpp>
+#include <boost/compute/image/image2d.hpp>
+#include <boost/compute/image/image3d.hpp>
+#include <boost/compute/image/image_object.hpp>
+#include <boost/compute/utility/wait_list.hpp>
+#include <boost/compute/detail/get_object_info.hpp>
+#include <boost/compute/detail/assert_cl_success.hpp>
+#include <boost/compute/detail/diagnostic.hpp>
+#include <boost/compute/utility/extents.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+inline void BOOST_COMPUTE_CL_CALLBACK
+nullary_native_kernel_trampoline(void *user_func_ptr)
+{
+ void (*user_func)();
+ std::memcpy(&user_func, user_func_ptr, sizeof(user_func));
+ user_func();
+}
+
+} // end detail namespace
+
+/// \class command_queue
+/// \brief A command queue.
+///
+/// Command queues provide the interface for interacting with compute
+/// devices. The command_queue class provides methods to copy data to
+/// and from a compute device as well as execute compute kernels.
+///
+/// Command queues are created for a compute device within a compute
+/// context.
+///
+/// For example, to create a context and command queue for the default device
+/// on the system (this is the normal set up code used by almost all OpenCL
+/// programs):
+/// \code
+/// #include <boost/compute/core.hpp>
+///
+/// // get the default compute device
+/// boost::compute::device device = boost::compute::system::default_device();
+///
+/// // set up a compute context and command queue
+/// boost::compute::context context(device);
+/// boost::compute::command_queue queue(context, device);
+/// \endcode
+///
+/// The default command queue for the system can be obtained with the
+/// system::default_queue() method.
+///
+/// \see buffer, context, kernel
+class command_queue
+{
+public:
+ enum properties {
+ enable_profiling = CL_QUEUE_PROFILING_ENABLE,
+ enable_out_of_order_execution = CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE
+ };
+
+ enum map_flags {
+ map_read = CL_MAP_READ,
+ map_write = CL_MAP_WRITE
+ #ifdef CL_VERSION_1_2
+ ,
+ map_write_invalidate_region = CL_MAP_WRITE_INVALIDATE_REGION
+ #endif
+ };
+
+ /// Creates a null command queue.
+ command_queue()
+ : m_queue(0)
+ {
+ }
+
+ explicit command_queue(cl_command_queue queue, bool retain = true)
+ : m_queue(queue)
+ {
+ if(m_queue && retain){
+ clRetainCommandQueue(m_queue);
+ }
+ }
+
+ /// Creates a command queue in \p context for \p device with
+ /// \p properties.
+ ///
+ /// \see_opencl_ref{clCreateCommandQueue}
+ command_queue(const context &context,
+ const device &device,
+ cl_command_queue_properties properties = 0)
+ {
+ BOOST_ASSERT(device.id() != 0);
+
+ cl_int error = 0;
+
+ #ifdef CL_VERSION_2_0
+ if (device.check_version(2, 0)){
+ std::vector<cl_queue_properties> queue_properties;
+ if(properties){
+ queue_properties.push_back(CL_QUEUE_PROPERTIES);
+ queue_properties.push_back(cl_queue_properties(properties));
+ queue_properties.push_back(cl_queue_properties(0));
+ }
+
+ const cl_queue_properties *queue_properties_ptr =
+ queue_properties.empty() ? 0 : &queue_properties[0];
+
+ m_queue = clCreateCommandQueueWithProperties(
+ context, device.id(), queue_properties_ptr, &error
+ );
+ } else
+ #endif
+ {
+ // Suppress deprecated declarations warning
+ BOOST_COMPUTE_DISABLE_DEPRECATED_DECLARATIONS();
+ m_queue = clCreateCommandQueue(
+ context, device.id(), properties, &error
+ );
+ BOOST_COMPUTE_ENABLE_DEPRECATED_DECLARATIONS();
+ }
+
+ if(!m_queue){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+ }
+
+ /// Creates a new command queue object as a copy of \p other.
+ command_queue(const command_queue &other)
+ : m_queue(other.m_queue)
+ {
+ if(m_queue){
+ clRetainCommandQueue(m_queue);
+ }
+ }
+
+ /// Copies the command queue object from \p other to \c *this.
+ command_queue& operator=(const command_queue &other)
+ {
+ if(this != &other){
+ if(m_queue){
+ clReleaseCommandQueue(m_queue);
+ }
+
+ m_queue = other.m_queue;
+
+ if(m_queue){
+ clRetainCommandQueue(m_queue);
+ }
+ }
+
+ return *this;
+ }
+
+ #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+ /// Move-constructs a new command queue object from \p other.
+ command_queue(command_queue&& other) BOOST_NOEXCEPT
+ : m_queue(other.m_queue)
+ {
+ other.m_queue = 0;
+ }
+
+ /// Move-assigns the command queue from \p other to \c *this.
+ command_queue& operator=(command_queue&& other) BOOST_NOEXCEPT
+ {
+ if(m_queue){
+ clReleaseCommandQueue(m_queue);
+ }
+
+ m_queue = other.m_queue;
+ other.m_queue = 0;
+
+ return *this;
+ }
+ #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+ /// Destroys the command queue.
+ ///
+ /// \see_opencl_ref{clReleaseCommandQueue}
+ ~command_queue()
+ {
+ if(m_queue){
+ BOOST_COMPUTE_ASSERT_CL_SUCCESS(
+ clReleaseCommandQueue(m_queue)
+ );
+ }
+ }
+
+ /// Returns the underlying OpenCL command queue.
+ cl_command_queue& get() const
+ {
+ return const_cast<cl_command_queue &>(m_queue);
+ }
+
+ /// Returns the device that the command queue issues commands to.
+ device get_device() const
+ {
+ return device(get_info<cl_device_id>(CL_QUEUE_DEVICE));
+ }
+
+ /// Returns the context for the command queue.
+ context get_context() const
+ {
+ return context(get_info<cl_context>(CL_QUEUE_CONTEXT));
+ }
+
+ /// Returns information about the command queue.
+ ///
+ /// \see_opencl_ref{clGetCommandQueueInfo}
+ template<class T>
+ T get_info(cl_command_queue_info info) const
+ {
+ return detail::get_object_info<T>(clGetCommandQueueInfo, m_queue, info);
+ }
+
+ /// \overload
+ template<int Enum>
+ typename detail::get_object_info_type<command_queue, Enum>::type
+ get_info() const;
+
+ /// Returns the properties for the command queue.
+ cl_command_queue_properties get_properties() const
+ {
+ return get_info<cl_command_queue_properties>(CL_QUEUE_PROPERTIES);
+ }
+
+ /// Enqueues a command to read data from \p buffer to host memory.
+ ///
+ /// \see_opencl_ref{clEnqueueReadBuffer}
+ ///
+ /// \see copy()
+ event enqueue_read_buffer(const buffer &buffer,
+ size_t offset,
+ size_t size,
+ void *host_ptr,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+ BOOST_ASSERT(size <= buffer.size());
+ BOOST_ASSERT(buffer.get_context() == this->get_context());
+ BOOST_ASSERT(host_ptr != 0);
+
+ event event_;
+
+ cl_int ret = clEnqueueReadBuffer(
+ m_queue,
+ buffer.get(),
+ CL_TRUE,
+ offset,
+ size,
+ host_ptr,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ /// Enqueues a command to read data from \p buffer to host memory. The
+ /// copy will be performed asynchronously.
+ ///
+ /// \see_opencl_ref{clEnqueueReadBuffer}
+ ///
+ /// \see copy_async()
+ event enqueue_read_buffer_async(const buffer &buffer,
+ size_t offset,
+ size_t size,
+ void *host_ptr,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+ BOOST_ASSERT(size <= buffer.size());
+ BOOST_ASSERT(buffer.get_context() == this->get_context());
+ BOOST_ASSERT(host_ptr != 0);
+
+ event event_;
+
+ cl_int ret = clEnqueueReadBuffer(
+ m_queue,
+ buffer.get(),
+ CL_FALSE,
+ offset,
+ size,
+ host_ptr,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ #if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ /// Enqueues a command to read a rectangular region from \p buffer to
+ /// host memory.
+ ///
+ /// \see_opencl_ref{clEnqueueReadBufferRect}
+ ///
+ /// \opencl_version_warning{1,1}
+ event enqueue_read_buffer_rect(const buffer &buffer,
+ const size_t buffer_origin[3],
+ const size_t host_origin[3],
+ const size_t region[3],
+ size_t buffer_row_pitch,
+ size_t buffer_slice_pitch,
+ size_t host_row_pitch,
+ size_t host_slice_pitch,
+ void *host_ptr,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+ BOOST_ASSERT(buffer.get_context() == this->get_context());
+ BOOST_ASSERT(host_ptr != 0);
+
+ event event_;
+
+ cl_int ret = clEnqueueReadBufferRect(
+ m_queue,
+ buffer.get(),
+ CL_TRUE,
+ buffer_origin,
+ host_origin,
+ region,
+ buffer_row_pitch,
+ buffer_slice_pitch,
+ host_row_pitch,
+ host_slice_pitch,
+ host_ptr,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ /// Enqueues a command to read a rectangular region from \p buffer to
+ /// host memory. The copy will be performed asynchronously.
+ ///
+ /// \see_opencl_ref{clEnqueueReadBufferRect}
+ ///
+ /// \opencl_version_warning{1,1}
+ event enqueue_read_buffer_rect_async(const buffer &buffer,
+ const size_t buffer_origin[3],
+ const size_t host_origin[3],
+ const size_t region[3],
+ size_t buffer_row_pitch,
+ size_t buffer_slice_pitch,
+ size_t host_row_pitch,
+ size_t host_slice_pitch,
+ void *host_ptr,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+ BOOST_ASSERT(buffer.get_context() == this->get_context());
+ BOOST_ASSERT(host_ptr != 0);
+
+ event event_;
+
+ cl_int ret = clEnqueueReadBufferRect(
+ m_queue,
+ buffer.get(),
+ CL_FALSE,
+ buffer_origin,
+ host_origin,
+ region,
+ buffer_row_pitch,
+ buffer_slice_pitch,
+ host_row_pitch,
+ host_slice_pitch,
+ host_ptr,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+ #endif // CL_VERSION_1_1
+
+ /// Enqueues a command to write data from host memory to \p buffer.
+ ///
+ /// \see_opencl_ref{clEnqueueWriteBuffer}
+ ///
+ /// \see copy()
+ event enqueue_write_buffer(const buffer &buffer,
+ size_t offset,
+ size_t size,
+ const void *host_ptr,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+ BOOST_ASSERT(size <= buffer.size());
+ BOOST_ASSERT(buffer.get_context() == this->get_context());
+ BOOST_ASSERT(host_ptr != 0);
+
+ event event_;
+
+ cl_int ret = clEnqueueWriteBuffer(
+ m_queue,
+ buffer.get(),
+ CL_TRUE,
+ offset,
+ size,
+ host_ptr,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ /// Enqueues a command to write data from host memory to \p buffer.
+ /// The copy is performed asynchronously.
+ ///
+ /// \see_opencl_ref{clEnqueueWriteBuffer}
+ ///
+ /// \see copy_async()
+ event enqueue_write_buffer_async(const buffer &buffer,
+ size_t offset,
+ size_t size,
+ const void *host_ptr,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+ BOOST_ASSERT(size <= buffer.size());
+ BOOST_ASSERT(buffer.get_context() == this->get_context());
+ BOOST_ASSERT(host_ptr != 0);
+
+ event event_;
+
+ cl_int ret = clEnqueueWriteBuffer(
+ m_queue,
+ buffer.get(),
+ CL_FALSE,
+ offset,
+ size,
+ host_ptr,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ #if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ /// Enqueues a command to write a rectangular region from host memory
+ /// to \p buffer.
+ ///
+ /// \see_opencl_ref{clEnqueueWriteBufferRect}
+ ///
+ /// \opencl_version_warning{1,1}
+ event enqueue_write_buffer_rect(const buffer &buffer,
+ const size_t buffer_origin[3],
+ const size_t host_origin[3],
+ const size_t region[3],
+ size_t buffer_row_pitch,
+ size_t buffer_slice_pitch,
+ size_t host_row_pitch,
+ size_t host_slice_pitch,
+ void *host_ptr,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+ BOOST_ASSERT(buffer.get_context() == this->get_context());
+ BOOST_ASSERT(host_ptr != 0);
+
+ event event_;
+
+ cl_int ret = clEnqueueWriteBufferRect(
+ m_queue,
+ buffer.get(),
+ CL_TRUE,
+ buffer_origin,
+ host_origin,
+ region,
+ buffer_row_pitch,
+ buffer_slice_pitch,
+ host_row_pitch,
+ host_slice_pitch,
+ host_ptr,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ /// Enqueues a command to write a rectangular region from host memory
+ /// to \p buffer. The copy is performed asynchronously.
+ ///
+ /// \see_opencl_ref{clEnqueueWriteBufferRect}
+ ///
+ /// \opencl_version_warning{1,1}
+ event enqueue_write_buffer_rect_async(const buffer &buffer,
+ const size_t buffer_origin[3],
+ const size_t host_origin[3],
+ const size_t region[3],
+ size_t buffer_row_pitch,
+ size_t buffer_slice_pitch,
+ size_t host_row_pitch,
+ size_t host_slice_pitch,
+ void *host_ptr,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+ BOOST_ASSERT(buffer.get_context() == this->get_context());
+ BOOST_ASSERT(host_ptr != 0);
+
+ event event_;
+
+ cl_int ret = clEnqueueWriteBufferRect(
+ m_queue,
+ buffer.get(),
+ CL_FALSE,
+ buffer_origin,
+ host_origin,
+ region,
+ buffer_row_pitch,
+ buffer_slice_pitch,
+ host_row_pitch,
+ host_slice_pitch,
+ host_ptr,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+ #endif // CL_VERSION_1_1
+
+ /// Enqueues a command to copy data from \p src_buffer to
+ /// \p dst_buffer.
+ ///
+ /// \see_opencl_ref{clEnqueueCopyBuffer}
+ ///
+ /// \see copy()
+ event enqueue_copy_buffer(const buffer &src_buffer,
+ const buffer &dst_buffer,
+ size_t src_offset,
+ size_t dst_offset,
+ size_t size,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+ BOOST_ASSERT(src_offset + size <= src_buffer.size());
+ BOOST_ASSERT(dst_offset + size <= dst_buffer.size());
+ BOOST_ASSERT(src_buffer.get_context() == this->get_context());
+ BOOST_ASSERT(dst_buffer.get_context() == this->get_context());
+
+ event event_;
+
+ cl_int ret = clEnqueueCopyBuffer(
+ m_queue,
+ src_buffer.get(),
+ dst_buffer.get(),
+ src_offset,
+ dst_offset,
+ size,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ #if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ /// Enqueues a command to copy a rectangular region from
+ /// \p src_buffer to \p dst_buffer.
+ ///
+ /// \see_opencl_ref{clEnqueueCopyBufferRect}
+ ///
+ /// \opencl_version_warning{1,1}
+ event enqueue_copy_buffer_rect(const buffer &src_buffer,
+ const buffer &dst_buffer,
+ const size_t src_origin[3],
+ const size_t dst_origin[3],
+ const size_t region[3],
+ size_t buffer_row_pitch,
+ size_t buffer_slice_pitch,
+ size_t host_row_pitch,
+ size_t host_slice_pitch,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+ BOOST_ASSERT(src_buffer.get_context() == this->get_context());
+ BOOST_ASSERT(dst_buffer.get_context() == this->get_context());
+
+ event event_;
+
+ cl_int ret = clEnqueueCopyBufferRect(
+ m_queue,
+ src_buffer.get(),
+ dst_buffer.get(),
+ src_origin,
+ dst_origin,
+ region,
+ buffer_row_pitch,
+ buffer_slice_pitch,
+ host_row_pitch,
+ host_slice_pitch,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+ #endif // CL_VERSION_1_1
+
+ #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ /// Enqueues a command to fill \p buffer with \p pattern.
+ ///
+ /// \see_opencl_ref{clEnqueueFillBuffer}
+ ///
+ /// \opencl_version_warning{1,2}
+ ///
+ /// \see fill()
+ event enqueue_fill_buffer(const buffer &buffer,
+ const void *pattern,
+ size_t pattern_size,
+ size_t offset,
+ size_t size,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+ BOOST_ASSERT(offset + size <= buffer.size());
+ BOOST_ASSERT(buffer.get_context() == this->get_context());
+
+ event event_;
+
+ cl_int ret = clEnqueueFillBuffer(
+ m_queue,
+ buffer.get(),
+ pattern,
+ pattern_size,
+ offset,
+ size,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+ #endif // CL_VERSION_1_2
+
+ /// Enqueues a command to map \p buffer into the host address space.
+ /// Event associated with map operation is returned through
+ /// \p map_buffer_event parameter.
+ ///
+ /// \see_opencl_ref{clEnqueueMapBuffer}
+ void* enqueue_map_buffer(const buffer &buffer,
+ cl_map_flags flags,
+ size_t offset,
+ size_t size,
+ event &map_buffer_event,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+ BOOST_ASSERT(offset + size <= buffer.size());
+ BOOST_ASSERT(buffer.get_context() == this->get_context());
+
+ cl_int ret = 0;
+ void *pointer = clEnqueueMapBuffer(
+ m_queue,
+ buffer.get(),
+ CL_TRUE,
+ flags,
+ offset,
+ size,
+ events.size(),
+ events.get_event_ptr(),
+ &map_buffer_event.get(),
+ &ret
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return pointer;
+ }
+
+ /// \overload
+ void* enqueue_map_buffer(const buffer &buffer,
+ cl_map_flags flags,
+ size_t offset,
+ size_t size,
+ const wait_list &events = wait_list())
+ {
+ event event_;
+ return enqueue_map_buffer(buffer, flags, offset, size, event_, events);
+ }
+
+ /// Enqueues a command to map \p buffer into the host address space.
+ /// Map operation is performed asynchronously. The pointer to the mapped
+ /// region cannot be used until the map operation has completed.
+ ///
+ /// Event associated with map operation is returned through
+ /// \p map_buffer_event parameter.
+ ///
+ /// \see_opencl_ref{clEnqueueMapBuffer}
+ void* enqueue_map_buffer_async(const buffer &buffer,
+ cl_map_flags flags,
+ size_t offset,
+ size_t size,
+ event &map_buffer_event,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+ BOOST_ASSERT(offset + size <= buffer.size());
+ BOOST_ASSERT(buffer.get_context() == this->get_context());
+
+ cl_int ret = 0;
+ void *pointer = clEnqueueMapBuffer(
+ m_queue,
+ buffer.get(),
+ CL_FALSE,
+ flags,
+ offset,
+ size,
+ events.size(),
+ events.get_event_ptr(),
+ &map_buffer_event.get(),
+ &ret
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return pointer;
+ }
+
+ /// Enqueues a command to unmap \p buffer from the host memory space.
+ ///
+ /// \see_opencl_ref{clEnqueueUnmapMemObject}
+ event enqueue_unmap_buffer(const buffer &buffer,
+ void *mapped_ptr,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(buffer.get_context() == this->get_context());
+
+ return enqueue_unmap_mem_object(buffer.get(), mapped_ptr, events);
+ }
+
+ /// Enqueues a command to unmap \p mem from the host memory space.
+ ///
+ /// \see_opencl_ref{clEnqueueUnmapMemObject}
+ event enqueue_unmap_mem_object(cl_mem mem,
+ void *mapped_ptr,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+
+ event event_;
+
+ cl_int ret = clEnqueueUnmapMemObject(
+ m_queue,
+ mem,
+ mapped_ptr,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ /// Enqueues a command to read data from \p image to host memory.
+ ///
+ /// \see_opencl_ref{clEnqueueReadImage}
+ event enqueue_read_image(const image_object& image,
+ const size_t *origin,
+ const size_t *region,
+ size_t row_pitch,
+ size_t slice_pitch,
+ void *host_ptr,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+
+ event event_;
+
+ cl_int ret = clEnqueueReadImage(
+ m_queue,
+ image.get(),
+ CL_TRUE,
+ origin,
+ region,
+ row_pitch,
+ slice_pitch,
+ host_ptr,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ /// \overload
+ template<size_t N>
+ event enqueue_read_image(const image_object& image,
+ const extents<N> origin,
+ const extents<N> region,
+ void *host_ptr,
+ size_t row_pitch = 0,
+ size_t slice_pitch = 0,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(image.get_context() == this->get_context());
+
+ size_t origin3[3] = { 0, 0, 0 };
+ size_t region3[3] = { 1, 1, 1 };
+
+ std::copy(origin.data(), origin.data() + N, origin3);
+ std::copy(region.data(), region.data() + N, region3);
+
+ return enqueue_read_image(
+ image, origin3, region3, row_pitch, slice_pitch, host_ptr, events
+ );
+ }
+
+ /// Enqueues a command to write data from host memory to \p image.
+ ///
+ /// \see_opencl_ref{clEnqueueWriteImage}
+ event enqueue_write_image(image_object& image,
+ const size_t *origin,
+ const size_t *region,
+ const void *host_ptr,
+ size_t input_row_pitch = 0,
+ size_t input_slice_pitch = 0,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+
+ event event_;
+
+ cl_int ret = clEnqueueWriteImage(
+ m_queue,
+ image.get(),
+ CL_TRUE,
+ origin,
+ region,
+ input_row_pitch,
+ input_slice_pitch,
+ host_ptr,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ /// \overload
+ template<size_t N>
+ event enqueue_write_image(image_object& image,
+ const extents<N> origin,
+ const extents<N> region,
+ const void *host_ptr,
+ const size_t input_row_pitch = 0,
+ const size_t input_slice_pitch = 0,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(image.get_context() == this->get_context());
+
+ size_t origin3[3] = { 0, 0, 0 };
+ size_t region3[3] = { 1, 1, 1 };
+
+ std::copy(origin.data(), origin.data() + N, origin3);
+ std::copy(region.data(), region.data() + N, region3);
+
+ return enqueue_write_image(
+ image, origin3, region3, host_ptr, input_row_pitch, input_slice_pitch, events
+ );
+ }
+
+ /// Enqueues a command to map \p image into the host address space.
+ ///
+ /// Event associated with map operation is returned through
+ /// \p map_image_event parameter.
+ ///
+ /// \see_opencl_ref{clEnqueueMapImage}
+ void* enqueue_map_image(const image_object &image,
+ cl_map_flags flags,
+ const size_t *origin,
+ const size_t *region,
+ size_t &output_row_pitch,
+ size_t &output_slice_pitch,
+ event &map_image_event,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+ BOOST_ASSERT(image.get_context() == this->get_context());
+
+ cl_int ret = 0;
+ void *pointer = clEnqueueMapImage(
+ m_queue,
+ image.get(),
+ CL_TRUE,
+ flags,
+ origin,
+ region,
+ &output_row_pitch,
+ &output_slice_pitch,
+ events.size(),
+ events.get_event_ptr(),
+ &map_image_event.get(),
+ &ret
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return pointer;
+ }
+
+ /// \overload
+ void* enqueue_map_image(const image_object &image,
+ cl_map_flags flags,
+ const size_t *origin,
+ const size_t *region,
+ size_t &output_row_pitch,
+ size_t &output_slice_pitch,
+ const wait_list &events = wait_list())
+ {
+ event event_;
+ return enqueue_map_image(
+ image, flags, origin, region,
+ output_row_pitch, output_slice_pitch, event_, events
+ );
+ }
+
+ /// \overload
+ template<size_t N>
+ void* enqueue_map_image(image_object& image,
+ cl_map_flags flags,
+ const extents<N> origin,
+ const extents<N> region,
+ size_t &output_row_pitch,
+ size_t &output_slice_pitch,
+ event &map_image_event,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(image.get_context() == this->get_context());
+
+ size_t origin3[3] = { 0, 0, 0 };
+ size_t region3[3] = { 1, 1, 1 };
+
+ std::copy(origin.data(), origin.data() + N, origin3);
+ std::copy(region.data(), region.data() + N, region3);
+
+ return enqueue_map_image(
+ image, flags, origin3, region3,
+ output_row_pitch, output_slice_pitch, map_image_event, events
+ );
+ }
+
+ /// \overload
+ template<size_t N>
+ void* enqueue_map_image(image_object& image,
+ cl_map_flags flags,
+ const extents<N> origin,
+ const extents<N> region,
+ size_t &output_row_pitch,
+ size_t &output_slice_pitch,
+ const wait_list &events = wait_list())
+ {
+ event event_;
+ return enqueue_map_image(
+ image, flags, origin, region,
+ output_row_pitch, output_slice_pitch, event_, events
+ );
+ }
+
+ /// Enqueues a command to map \p image into the host address space.
+ /// Map operation is performed asynchronously. The pointer to the mapped
+ /// region cannot be used until the map operation has completed.
+ ///
+ /// Event associated with map operation is returned through
+ /// \p map_image_event parameter.
+ ///
+ /// \see_opencl_ref{clEnqueueMapImage}
+ void* enqueue_map_image_async(const image_object &image,
+ cl_map_flags flags,
+ const size_t *origin,
+ const size_t *region,
+ size_t &output_row_pitch,
+ size_t &output_slice_pitch,
+ event &map_image_event,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+ BOOST_ASSERT(image.get_context() == this->get_context());
+
+ cl_int ret = 0;
+ void *pointer = clEnqueueMapImage(
+ m_queue,
+ image.get(),
+ CL_FALSE,
+ flags,
+ origin,
+ region,
+ &output_row_pitch,
+ &output_slice_pitch,
+ events.size(),
+ events.get_event_ptr(),
+ &map_image_event.get(),
+ &ret
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return pointer;
+ }
+
+ /// \overload
+ template<size_t N>
+ void* enqueue_map_image_async(image_object& image,
+ cl_map_flags flags,
+ const extents<N> origin,
+ const extents<N> region,
+ size_t &output_row_pitch,
+ size_t &output_slice_pitch,
+ event &map_image_event,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(image.get_context() == this->get_context());
+
+ size_t origin3[3] = { 0, 0, 0 };
+ size_t region3[3] = { 1, 1, 1 };
+
+ std::copy(origin.data(), origin.data() + N, origin3);
+ std::copy(region.data(), region.data() + N, region3);
+
+ return enqueue_map_image_async(
+ image, flags, origin3, region3,
+ output_row_pitch, output_slice_pitch, map_image_event, events
+ );
+ }
+
+ /// Enqueues a command to unmap \p image from the host memory space.
+ ///
+ /// \see_opencl_ref{clEnqueueUnmapMemObject}
+ event enqueue_unmap_image(const image_object &image,
+ void *mapped_ptr,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(image.get_context() == this->get_context());
+
+ return enqueue_unmap_mem_object(image.get(), mapped_ptr, events);
+ }
+
+ /// Enqueues a command to copy data from \p src_image to \p dst_image.
+ ///
+ /// \see_opencl_ref{clEnqueueCopyImage}
+ event enqueue_copy_image(const image_object& src_image,
+ image_object& dst_image,
+ const size_t *src_origin,
+ const size_t *dst_origin,
+ const size_t *region,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+
+ event event_;
+
+ cl_int ret = clEnqueueCopyImage(
+ m_queue,
+ src_image.get(),
+ dst_image.get(),
+ src_origin,
+ dst_origin,
+ region,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ /// \overload
+ template<size_t N>
+ event enqueue_copy_image(const image_object& src_image,
+ image_object& dst_image,
+ const extents<N> src_origin,
+ const extents<N> dst_origin,
+ const extents<N> region,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(src_image.get_context() == this->get_context());
+ BOOST_ASSERT(dst_image.get_context() == this->get_context());
+ BOOST_ASSERT_MSG(src_image.format() == dst_image.format(),
+ "Source and destination image formats must match.");
+
+ size_t src_origin3[3] = { 0, 0, 0 };
+ size_t dst_origin3[3] = { 0, 0, 0 };
+ size_t region3[3] = { 1, 1, 1 };
+
+ std::copy(src_origin.data(), src_origin.data() + N, src_origin3);
+ std::copy(dst_origin.data(), dst_origin.data() + N, dst_origin3);
+ std::copy(region.data(), region.data() + N, region3);
+
+ return enqueue_copy_image(
+ src_image, dst_image, src_origin3, dst_origin3, region3, events
+ );
+ }
+
+ /// Enqueues a command to copy data from \p src_image to \p dst_buffer.
+ ///
+ /// \see_opencl_ref{clEnqueueCopyImageToBuffer}
+ event enqueue_copy_image_to_buffer(const image_object& src_image,
+ memory_object& dst_buffer,
+ const size_t *src_origin,
+ const size_t *region,
+ size_t dst_offset,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+
+ event event_;
+
+ cl_int ret = clEnqueueCopyImageToBuffer(
+ m_queue,
+ src_image.get(),
+ dst_buffer.get(),
+ src_origin,
+ region,
+ dst_offset,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ /// Enqueues a command to copy data from \p src_buffer to \p dst_image.
+ ///
+ /// \see_opencl_ref{clEnqueueCopyBufferToImage}
+ event enqueue_copy_buffer_to_image(const memory_object& src_buffer,
+ image_object& dst_image,
+ size_t src_offset,
+ const size_t *dst_origin,
+ const size_t *region,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+
+ event event_;
+
+ cl_int ret = clEnqueueCopyBufferToImage(
+ m_queue,
+ src_buffer.get(),
+ dst_image.get(),
+ src_offset,
+ dst_origin,
+ region,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ /// Enqueues a command to fill \p image with \p fill_color.
+ ///
+ /// \see_opencl_ref{clEnqueueFillImage}
+ ///
+ /// \opencl_version_warning{1,2}
+ event enqueue_fill_image(image_object& image,
+ const void *fill_color,
+ const size_t *origin,
+ const size_t *region,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+
+ event event_;
+
+ cl_int ret = clEnqueueFillImage(
+ m_queue,
+ image.get(),
+ fill_color,
+ origin,
+ region,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ /// \overload
+ template<size_t N>
+ event enqueue_fill_image(image_object& image,
+ const void *fill_color,
+ const extents<N> origin,
+ const extents<N> region,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(image.get_context() == this->get_context());
+
+ size_t origin3[3] = { 0, 0, 0 };
+ size_t region3[3] = { 1, 1, 1 };
+
+ std::copy(origin.data(), origin.data() + N, origin3);
+ std::copy(region.data(), region.data() + N, region3);
+
+ return enqueue_fill_image(
+ image, fill_color, origin3, region3, events
+ );
+ }
+
+ /// Enqueues a command to migrate \p mem_objects.
+ ///
+ /// \see_opencl_ref{clEnqueueMigrateMemObjects}
+ ///
+ /// \opencl_version_warning{1,2}
+ event enqueue_migrate_memory_objects(uint_ num_mem_objects,
+ const cl_mem *mem_objects,
+ cl_mem_migration_flags flags,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+
+ event event_;
+
+ cl_int ret = clEnqueueMigrateMemObjects(
+ m_queue,
+ num_mem_objects,
+ mem_objects,
+ flags,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+ #endif // CL_VERSION_1_2
+
+ /// Enqueues a kernel for execution.
+ ///
+ /// \see_opencl_ref{clEnqueueNDRangeKernel}
+ event enqueue_nd_range_kernel(const kernel &kernel,
+ size_t work_dim,
+ const size_t *global_work_offset,
+ const size_t *global_work_size,
+ const size_t *local_work_size,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+ BOOST_ASSERT(kernel.get_context() == this->get_context());
+
+ event event_;
+
+ cl_int ret = clEnqueueNDRangeKernel(
+ m_queue,
+ kernel,
+ static_cast<cl_uint>(work_dim),
+ global_work_offset,
+ global_work_size,
+ local_work_size,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ /// \overload
+ template<size_t N>
+ event enqueue_nd_range_kernel(const kernel &kernel,
+ const extents<N> &global_work_offset,
+ const extents<N> &global_work_size,
+ const extents<N> &local_work_size,
+ const wait_list &events = wait_list())
+ {
+ return enqueue_nd_range_kernel(
+ kernel,
+ N,
+ global_work_offset.data(),
+ global_work_size.data(),
+ local_work_size.data(),
+ events
+ );
+ }
+
+ /// Convenience method which calls enqueue_nd_range_kernel() with a
+ /// one-dimensional range.
+ event enqueue_1d_range_kernel(const kernel &kernel,
+ size_t global_work_offset,
+ size_t global_work_size,
+ size_t local_work_size,
+ const wait_list &events = wait_list())
+ {
+ return enqueue_nd_range_kernel(
+ kernel,
+ 1,
+ &global_work_offset,
+ &global_work_size,
+ local_work_size ? &local_work_size : 0,
+ events
+ );
+ }
+
+ /// Enqueues a kernel to execute using a single work-item.
+ ///
+ /// \see_opencl_ref{clEnqueueTask}
+ event enqueue_task(const kernel &kernel, const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+ BOOST_ASSERT(kernel.get_context() == this->get_context());
+
+ event event_;
+
+ // clEnqueueTask() was deprecated in OpenCL 2.0. In that case we
+ // just forward to the equivalent clEnqueueNDRangeKernel() call.
+ #ifdef CL_VERSION_2_0
+ size_t one = 1;
+ cl_int ret = clEnqueueNDRangeKernel(
+ m_queue, kernel, 1, 0, &one, &one,
+ events.size(), events.get_event_ptr(), &event_.get()
+ );
+ #else
+ cl_int ret = clEnqueueTask(
+ m_queue, kernel, events.size(), events.get_event_ptr(), &event_.get()
+ );
+ #endif
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ /// Enqueues a function to execute on the host.
+ event enqueue_native_kernel(void (BOOST_COMPUTE_CL_CALLBACK *user_func)(void *),
+ void *args,
+ size_t cb_args,
+ uint_ num_mem_objects,
+ const cl_mem *mem_list,
+ const void **args_mem_loc,
+ const wait_list &events = wait_list())
+ {
+ BOOST_ASSERT(m_queue != 0);
+
+ event event_;
+ cl_int ret = clEnqueueNativeKernel(
+ m_queue,
+ user_func,
+ args,
+ cb_args,
+ num_mem_objects,
+ mem_list,
+ args_mem_loc,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ /// Convenience overload for enqueue_native_kernel() which enqueues a
+ /// native kernel on the host with a nullary function.
+ event enqueue_native_kernel(void (BOOST_COMPUTE_CL_CALLBACK *user_func)(void),
+ const wait_list &events = wait_list())
+ {
+ return enqueue_native_kernel(
+ detail::nullary_native_kernel_trampoline,
+ reinterpret_cast<void *>(&user_func),
+ sizeof(user_func),
+ 0,
+ 0,
+ 0,
+ events
+ );
+ }
+
+ /// Flushes the command queue.
+ ///
+ /// \see_opencl_ref{clFlush}
+ void flush()
+ {
+ BOOST_ASSERT(m_queue != 0);
+
+ clFlush(m_queue);
+ }
+
+ /// Blocks until all outstanding commands in the queue have finished.
+ ///
+ /// \see_opencl_ref{clFinish}
+ void finish()
+ {
+ BOOST_ASSERT(m_queue != 0);
+
+ clFinish(m_queue);
+ }
+
+ /// Enqueues a barrier in the queue.
+ void enqueue_barrier()
+ {
+ BOOST_ASSERT(m_queue != 0);
+ cl_int ret = CL_SUCCESS;
+
+ #ifdef CL_VERSION_1_2
+ if(get_device().check_version(1, 2)){
+ ret = clEnqueueBarrierWithWaitList(m_queue, 0, 0, 0);
+ } else
+ #endif // CL_VERSION_1_2
+ {
+ // Suppress deprecated declarations warning
+ BOOST_COMPUTE_DISABLE_DEPRECATED_DECLARATIONS();
+ ret = clEnqueueBarrier(m_queue);
+ BOOST_COMPUTE_ENABLE_DEPRECATED_DECLARATIONS();
+ }
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+ }
+
+ #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ /// Enqueues a barrier in the queue after \p events.
+ ///
+ /// \opencl_version_warning{1,2}
+ event enqueue_barrier(const wait_list &events)
+ {
+ BOOST_ASSERT(m_queue != 0);
+
+ event event_;
+ cl_int ret = CL_SUCCESS;
+
+ ret = clEnqueueBarrierWithWaitList(
+ m_queue, events.size(), events.get_event_ptr(), &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+ #endif // CL_VERSION_1_2
+
+ /// Enqueues a marker in the queue and returns an event that can be
+ /// used to track its progress.
+ event enqueue_marker()
+ {
+ event event_;
+ cl_int ret = CL_SUCCESS;
+
+ #ifdef CL_VERSION_1_2
+ if(get_device().check_version(1, 2)){
+ ret = clEnqueueMarkerWithWaitList(m_queue, 0, 0, &event_.get());
+ } else
+ #endif
+ {
+ // Suppress deprecated declarations warning
+ BOOST_COMPUTE_DISABLE_DEPRECATED_DECLARATIONS();
+ ret = clEnqueueMarker(m_queue, &event_.get());
+ BOOST_COMPUTE_ENABLE_DEPRECATED_DECLARATIONS();
+ }
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ /// Enqueues a marker after \p events in the queue and returns an
+ /// event that can be used to track its progress.
+ ///
+ /// \opencl_version_warning{1,2}
+ event enqueue_marker(const wait_list &events)
+ {
+ event event_;
+
+ cl_int ret = clEnqueueMarkerWithWaitList(
+ m_queue, events.size(), events.get_event_ptr(), &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+ #endif // CL_VERSION_1_2
+
+ #if defined(CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ /// Enqueues a command to copy \p size bytes of data from \p src_ptr to
+ /// \p dst_ptr.
+ ///
+ /// \opencl_version_warning{2,0}
+ ///
+ /// \see_opencl2_ref{clEnqueueSVMMemcpy}
+ event enqueue_svm_memcpy(void *dst_ptr,
+ const void *src_ptr,
+ size_t size,
+ const wait_list &events = wait_list())
+ {
+ event event_;
+
+ cl_int ret = clEnqueueSVMMemcpy(
+ m_queue,
+ CL_TRUE,
+ dst_ptr,
+ src_ptr,
+ size,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ /// Enqueues a command to copy \p size bytes of data from \p src_ptr to
+ /// \p dst_ptr. The operation is performed asynchronously.
+ ///
+ /// \opencl_version_warning{2,0}
+ ///
+ /// \see_opencl2_ref{clEnqueueSVMMemcpy}
+ event enqueue_svm_memcpy_async(void *dst_ptr,
+ const void *src_ptr,
+ size_t size,
+ const wait_list &events = wait_list())
+ {
+ event event_;
+
+ cl_int ret = clEnqueueSVMMemcpy(
+ m_queue,
+ CL_FALSE,
+ dst_ptr,
+ src_ptr,
+ size,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ /// Enqueues a command to fill \p size bytes of data at \p svm_ptr with
+ /// \p pattern.
+ ///
+ /// \opencl_version_warning{2,0}
+ ///
+ /// \see_opencl2_ref{clEnqueueSVMMemFill}
+ event enqueue_svm_fill(void *svm_ptr,
+ const void *pattern,
+ size_t pattern_size,
+ size_t size,
+ const wait_list &events = wait_list())
+
+ {
+ event event_;
+
+ cl_int ret = clEnqueueSVMMemFill(
+ m_queue,
+ svm_ptr,
+ pattern,
+ pattern_size,
+ size,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ /// Enqueues a command to free \p svm_ptr.
+ ///
+ /// \opencl_version_warning{2,0}
+ ///
+ /// \see_opencl2_ref{clEnqueueSVMFree}
+ ///
+ /// \see svm_free()
+ event enqueue_svm_free(void *svm_ptr,
+ const wait_list &events = wait_list())
+ {
+ event event_;
+
+ cl_int ret = clEnqueueSVMFree(
+ m_queue,
+ 1,
+ &svm_ptr,
+ 0,
+ 0,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ /// Enqueues a command to map \p svm_ptr to the host memory space.
+ ///
+ /// \opencl_version_warning{2,0}
+ ///
+ /// \see_opencl2_ref{clEnqueueSVMMap}
+ event enqueue_svm_map(void *svm_ptr,
+ size_t size,
+ cl_map_flags flags,
+ const wait_list &events = wait_list())
+ {
+ event event_;
+
+ cl_int ret = clEnqueueSVMMap(
+ m_queue,
+ CL_TRUE,
+ flags,
+ svm_ptr,
+ size,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+
+ /// Enqueues a command to unmap \p svm_ptr from the host memory space.
+ ///
+ /// \opencl_version_warning{2,0}
+ ///
+ /// \see_opencl2_ref{clEnqueueSVMUnmap}
+ event enqueue_svm_unmap(void *svm_ptr,
+ const wait_list &events = wait_list())
+ {
+ event event_;
+
+ cl_int ret = clEnqueueSVMUnmap(
+ m_queue,
+ svm_ptr,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get()
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+ }
+ #endif // CL_VERSION_2_0
+
+ /// Returns \c true if the command queue is the same at \p other.
+ bool operator==(const command_queue &other) const
+ {
+ return m_queue == other.m_queue;
+ }
+
+ /// Returns \c true if the command queue is different from \p other.
+ bool operator!=(const command_queue &other) const
+ {
+ return m_queue != other.m_queue;
+ }
+
+ /// \internal_
+ operator cl_command_queue() const
+ {
+ return m_queue;
+ }
+
+ /// \internal_
+ bool check_device_version(int major, int minor) const
+ {
+ return get_device().check_version(major, minor);
+ }
+
+private:
+ cl_command_queue m_queue;
+};
+
+inline buffer buffer::clone(command_queue &queue) const
+{
+ buffer copy(get_context(), size(), get_memory_flags());
+ queue.enqueue_copy_buffer(*this, copy, 0, 0, size());
+ return copy;
+}
+
+inline image1d image1d::clone(command_queue &queue) const
+{
+ image1d copy(
+ get_context(), width(), format(), get_memory_flags()
+ );
+
+ queue.enqueue_copy_image(*this, copy, origin(), copy.origin(), size());
+
+ return copy;
+}
+
+inline image2d image2d::clone(command_queue &queue) const
+{
+ image2d copy(
+ get_context(), width(), height(), format(), get_memory_flags()
+ );
+
+ queue.enqueue_copy_image(*this, copy, origin(), copy.origin(), size());
+
+ return copy;
+}
+
+inline image3d image3d::clone(command_queue &queue) const
+{
+ image3d copy(
+ get_context(), width(), height(), depth(), format(), get_memory_flags()
+ );
+
+ queue.enqueue_copy_image(*this, copy, origin(), copy.origin(), size());
+
+ return copy;
+}
+
+/// \internal_ define get_info() specializations for command_queue
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(command_queue,
+ ((cl_context, CL_QUEUE_CONTEXT))
+ ((cl_device_id, CL_QUEUE_DEVICE))
+ ((uint_, CL_QUEUE_REFERENCE_COUNT))
+ ((cl_command_queue_properties, CL_QUEUE_PROPERTIES))
+)
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_COMMAND_QUEUE_HPP
diff --git a/boost/compute/config.hpp b/boost/compute/config.hpp
new file mode 100644
index 0000000000..77d0d7b9df
--- /dev/null
+++ b/boost/compute/config.hpp
@@ -0,0 +1,70 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_CONFIG_HPP
+#define BOOST_COMPUTE_CONFIG_HPP
+
+#include <boost/config.hpp>
+#include <boost/version.hpp>
+#include <boost/compute/cl.hpp>
+
+// check for minimum required boost version
+#if BOOST_VERSION < 104800
+#error Boost.Compute requires Boost version 1.48 or later
+#endif
+
+// the BOOST_COMPUTE_NO_VARIADIC_TEMPLATES macro is defined
+// if the compiler does not *fully* support variadic templates
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \
+ defined(BOOST_NO_VARIADIC_TEMPLATES) || \
+ (defined(__GNUC__) && !defined(__clang__) && \
+ __GNUC__ == 4 && __GNUC_MINOR__ <= 6)
+ #define BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
+#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+// the BOOST_COMPUTE_NO_STD_TUPLE macro is defined if the
+// compiler/stdlib does not support std::tuple
+#if defined(BOOST_NO_CXX11_HDR_TUPLE) || \
+ defined(BOOST_NO_0X_HDR_TUPLE) || \
+ defined(BOOST_COMPUTE_NO_VARIADIC_TEMPLATES)
+ #define BOOST_COMPUTE_NO_STD_TUPLE
+#endif // BOOST_NO_CXX11_HDR_TUPLE
+
+// defines BOOST_COMPUTE_CL_CALLBACK to the value of CL_CALLBACK
+// if it is defined (it was added in OpenCL 1.1). this is used to
+// annotate certain callback functions registered with OpenCL
+#ifdef CL_CALLBACK
+# define BOOST_COMPUTE_CL_CALLBACK CL_CALLBACK
+#else
+# define BOOST_COMPUTE_CL_CALLBACK
+#endif
+
+// Maximum number of iterators acceptable for make_zip_iterator
+#ifndef BOOST_COMPUTE_MAX_ARITY
+ // should be no more than max boost::tuple size (10 by default)
+# define BOOST_COMPUTE_MAX_ARITY 10
+#endif
+
+#if !defined(BOOST_COMPUTE_DOXYGEN_INVOKED) && \
+ (defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_RVALUE_REFERENCES))
+# define BOOST_COMPUTE_NO_RVALUE_REFERENCES
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
+
+#if defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) || \
+ defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
+# define BOOST_COMPUTE_NO_HDR_INITIALIZER_LIST
+#endif // BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+
+#if defined(BOOST_NO_CXX11_HDR_CHRONO) || \
+ defined(BOOST_NO_0X_HDR_CHRONO)
+# define BOOST_COMPUTE_NO_HDR_CHRONO
+#endif // BOOST_NO_CXX11_HDR_CHRONO
+
+#endif // BOOST_COMPUTE_CONFIG_HPP
diff --git a/boost/compute/container.hpp b/boost/compute/container.hpp
new file mode 100644
index 0000000000..fc14f5fde2
--- /dev/null
+++ b/boost/compute/container.hpp
@@ -0,0 +1,27 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_CONTAINER_HPP
+#define BOOST_COMPUTE_CONTAINER_HPP
+
+/// \file
+///
+/// Meta-header to include all Boost.Compute container headers.
+
+#include <boost/compute/container/array.hpp>
+#include <boost/compute/container/basic_string.hpp>
+#include <boost/compute/container/dynamic_bitset.hpp>
+#include <boost/compute/container/flat_map.hpp>
+#include <boost/compute/container/flat_set.hpp>
+#include <boost/compute/container/mapped_view.hpp>
+#include <boost/compute/container/string.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#endif // BOOST_COMPUTE_CONTAINER_HPP
diff --git a/boost/compute/container/array.hpp b/boost/compute/container/array.hpp
new file mode 100644
index 0000000000..919be6eeac
--- /dev/null
+++ b/boost/compute/container/array.hpp
@@ -0,0 +1,281 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_CONTAINER_ARRAY_HPP
+#define BOOST_COMPUTE_CONTAINER_ARRAY_HPP
+
+#include <cstddef>
+#include <iterator>
+#include <exception>
+
+#include <boost/array.hpp>
+#include <boost/throw_exception.hpp>
+
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/algorithm/swap_ranges.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+#include <boost/compute/type_traits/detail/capture_traits.hpp>
+#include <boost/compute/detail/buffer_value.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class array
+/// \brief A fixed-size container.
+///
+/// The array container is very similar to the \ref vector container except
+/// its size is fixed at compile-time rather than being dynamically resizable
+/// at run-time.
+///
+/// For example, to create a fixed-size array with eight values on the device:
+/// \code
+/// boost::compute::array<int, 8> values(context);
+/// \endcode
+///
+/// The Boost.Compute \c array class provides a STL-like API and is modeled
+/// after the \c std::array class from the C++ standard library.
+///
+/// \see \ref vector "vector<T>"
+template<class T, std::size_t N>
+class array
+{
+public:
+ typedef T value_type;
+ typedef std::size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef detail::buffer_value<T> reference;
+ typedef const detail::buffer_value<T> const_reference;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef buffer_iterator<T> iterator;
+ typedef buffer_iterator<T> const_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ enum {
+ static_size = N
+ };
+
+ explicit array(const context &context = system::default_context())
+ : m_buffer(context, sizeof(T) * N)
+ {
+ }
+
+ array(const array<T, N> &other)
+ : m_buffer(other.m_buffer.get_context(), sizeof(T) * N)
+ {
+ boost::compute::copy(other.begin(), other.end(), begin());
+ }
+
+ array(const boost::array<T, N> &array,
+ const context &context = system::default_context())
+ : m_buffer(context, sizeof(T) * N)
+ {
+ boost::compute::copy(array.begin(), array.end(), begin());
+ }
+
+ array<T, N>& operator=(const array<T, N> &other)
+ {
+ if(this != &other){
+ boost::compute::copy(other.begin(), other.end(), begin());
+ }
+
+ return *this;
+ }
+
+ array<T, N>& operator=(const boost::array<T, N> &array)
+ {
+ boost::compute::copy(array.begin(), array.end(), begin());
+
+ return *this;
+ }
+
+ ~array()
+ {
+ }
+
+ iterator begin()
+ {
+ return buffer_iterator<T>(m_buffer, 0);
+ }
+
+ const_iterator begin() const
+ {
+ return buffer_iterator<T>(m_buffer, 0);
+ }
+
+ const_iterator cbegin() const
+ {
+ return begin();
+ }
+
+ iterator end()
+ {
+ return buffer_iterator<T>(m_buffer, N);
+ }
+
+ const_iterator end() const
+ {
+ return buffer_iterator<T>(m_buffer, N);
+ }
+
+ const_iterator cend() const
+ {
+ return end();
+ }
+
+ reverse_iterator rbegin()
+ {
+ return reverse_iterator(end() - 1);
+ }
+
+ const_reverse_iterator rbegin() const
+ {
+ return reverse_iterator(end() - 1);
+ }
+
+ const_reverse_iterator crbegin() const
+ {
+ return rbegin();
+ }
+
+ reverse_iterator rend()
+ {
+ return reverse_iterator(begin() - 1);
+ }
+
+ const_reverse_iterator rend() const
+ {
+ return reverse_iterator(begin() - 1);
+ }
+
+ const_reverse_iterator crend() const
+ {
+ return rend();
+ }
+
+ size_type size() const
+ {
+ return N;
+ }
+
+ bool empty() const
+ {
+ return N == 0;
+ }
+
+ size_type max_size() const
+ {
+ return N;
+ }
+
+ reference operator[](size_type index)
+ {
+ return *(begin() + static_cast<difference_type>(index));
+ }
+
+ const_reference operator[](size_type index) const
+ {
+ return *(begin() + static_cast<difference_type>(index));
+ }
+
+ reference at(size_type index)
+ {
+ if(index >= N){
+ BOOST_THROW_EXCEPTION(std::out_of_range("index out of range"));
+ }
+
+ return operator[](index);
+ }
+
+ const_reference at(size_type index) const
+ {
+ if(index >= N){
+ BOOST_THROW_EXCEPTION(std::out_of_range("index out of range"));
+ }
+
+ return operator[](index);
+ }
+
+ reference front()
+ {
+ return *begin();
+ }
+
+ const_reference front() const
+ {
+ return *begin();
+ }
+
+ reference back()
+ {
+ return *(end() - static_cast<difference_type>(1));
+ }
+
+ const_reference back() const
+ {
+ return *(end() - static_cast<difference_type>(1));
+ }
+
+ void fill(const value_type &value)
+ {
+ ::boost::compute::fill(begin(), end(), value);
+ }
+
+ void swap(array<T, N> &other)
+ {
+ ::boost::compute::swap_ranges(begin(), end(), other.begin());
+ }
+
+ const buffer& get_buffer() const
+ {
+ return m_buffer;
+ }
+
+private:
+ buffer m_buffer;
+};
+
+namespace detail {
+
+// set_kernel_arg specialization for array<T, N>
+template<class T, std::size_t N>
+struct set_kernel_arg<array<T, N> >
+{
+ void operator()(kernel &kernel_, size_t index, const array<T, N> &array)
+ {
+ kernel_.set_arg(index, array.get_buffer());
+ }
+};
+
+// for capturing array<T, N> with BOOST_COMPUTE_CLOSURE()
+template<class T, size_t N>
+struct capture_traits<array<T, N> >
+{
+ static std::string type_name()
+ {
+ return std::string("__global ") + ::boost::compute::type_name<T>() + "*";
+ }
+};
+
+// meta_kernel streaming operator for array<T, N>
+template<class T, size_t N>
+meta_kernel& operator<<(meta_kernel &k, const array<T, N> &array)
+{
+ return k << k.get_buffer_identifier<T>(array.get_buffer());
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_CONTAINER_ARRAY_HPP
diff --git a/boost/compute/container/basic_string.hpp b/boost/compute/container/basic_string.hpp
new file mode 100644
index 0000000000..c5a2c46aa5
--- /dev/null
+++ b/boost/compute/container/basic_string.hpp
@@ -0,0 +1,331 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_CONTAINER_BASIC_STRING_HPP
+#define BOOST_COMPUTE_CONTAINER_BASIC_STRING_HPP
+
+#include <string>
+#include <cstring>
+
+#include <boost/compute/cl.hpp>
+#include <boost/compute/algorithm/find.hpp>
+#include <boost/compute/algorithm/search.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <iosfwd>
+
+namespace boost {
+namespace compute {
+
+/// \class basic_string
+/// \brief A template for a dynamically-sized character sequence.
+///
+/// The \c basic_string class provides a generic template for a dynamically-
+/// sized character sequence. This is most commonly used through the \c string
+/// typedef (for \c basic_string<char>).
+///
+/// For example, to create a string on the device with its contents copied
+/// from a C-string on the host:
+/// \code
+/// boost::compute::string str("hello, world!");
+/// \endcode
+///
+/// \see \ref vector "vector<T>"
+template<class CharT, class Traits = std::char_traits<CharT> >
+class basic_string
+{
+public:
+ typedef Traits traits_type;
+ typedef typename Traits::char_type value_type;
+ typedef size_t size_type;
+ static const size_type npos = size_type(-1);
+ typedef typename ::boost::compute::vector<CharT>::reference reference;
+ typedef typename ::boost::compute::vector<CharT>::const_reference const_reference;
+ typedef typename ::boost::compute::vector<CharT>::iterator iterator;
+ typedef typename ::boost::compute::vector<CharT>::const_iterator const_iterator;
+ typedef typename ::boost::compute::vector<CharT>::reverse_iterator reverse_iterator;
+ typedef typename ::boost::compute::vector<CharT>::const_reverse_iterator const_reverse_iterator;
+
+ basic_string()
+ {
+ }
+
+ basic_string(size_type count, CharT ch)
+ : m_data(count)
+ {
+ std::fill(m_data.begin(), m_data.end(), ch);
+ }
+
+ basic_string(const basic_string &other,
+ size_type pos,
+ size_type count = npos)
+ : m_data(other.begin() + pos,
+ other.begin() + (std::min)(other.size(), count))
+ {
+ }
+
+ basic_string(const char *s, size_type count)
+ : m_data(s, s + count)
+ {
+ }
+
+ basic_string(const char *s)
+ : m_data(s, s + std::strlen(s))
+ {
+ }
+
+ template<class InputIterator>
+ basic_string(InputIterator first, InputIterator last)
+ : m_data(first, last)
+ {
+ }
+
+ basic_string(const basic_string<CharT, Traits> &other)
+ : m_data(other.m_data)
+ {
+ }
+
+ basic_string<CharT, Traits>& operator=(const basic_string<CharT, Traits> &other)
+ {
+ if(this != &other){
+ m_data = other.m_data;
+ }
+
+ return *this;
+ }
+
+ ~basic_string()
+ {
+ }
+
+ reference at(size_type pos)
+ {
+ return m_data.at(pos);
+ }
+
+ const_reference at(size_type pos) const
+ {
+ return m_data.at(pos);
+ }
+
+ reference operator[](size_type pos)
+ {
+ return m_data[pos];
+ }
+
+ const_reference operator[](size_type pos) const
+ {
+ return m_data[pos];
+ }
+
+ reference front()
+ {
+ return m_data.front();
+ }
+
+ const_reference front() const
+ {
+ return m_data.front();
+ }
+
+ reference back()
+ {
+ return m_data.back();
+ }
+
+ const_reference back() const
+ {
+ return m_data.back();
+ }
+
+ iterator begin()
+ {
+ return m_data.begin();
+ }
+
+ const_iterator begin() const
+ {
+ return m_data.begin();
+ }
+
+ const_iterator cbegin() const
+ {
+ return m_data.cbegin();
+ }
+
+ iterator end()
+ {
+ return m_data.end();
+ }
+
+ const_iterator end() const
+ {
+ return m_data.end();
+ }
+
+ const_iterator cend() const
+ {
+ return m_data.cend();
+ }
+
+ reverse_iterator rbegin()
+ {
+ return m_data.rbegin();
+ }
+
+ const_reverse_iterator rbegin() const
+ {
+ return m_data.rbegin();
+ }
+
+ const_reverse_iterator crbegin() const
+ {
+ return m_data.crbegin();
+ }
+
+ reverse_iterator rend()
+ {
+ return m_data.rend();
+ }
+
+ const_reverse_iterator rend() const
+ {
+ return m_data.rend();
+ }
+
+ const_reverse_iterator crend() const
+ {
+ return m_data.crend();
+ }
+
+ bool empty() const
+ {
+ return m_data.empty();
+ }
+
+ size_type size() const
+ {
+ return m_data.size();
+ }
+
+ size_type length() const
+ {
+ return m_data.size();
+ }
+
+ size_type max_size() const
+ {
+ return m_data.max_size();
+ }
+
+ void reserve(size_type size)
+ {
+ m_data.reserve(size);
+ }
+
+ size_type capacity() const
+ {
+ return m_data.capacity();
+ }
+
+ void shrink_to_fit()
+ {
+ m_data.shrink_to_fit();
+ }
+
+ void clear()
+ {
+ m_data.clear();
+ }
+
+ void swap(basic_string<CharT, Traits> &other)
+ {
+ if(this != &other)
+ {
+ ::boost::compute::vector<CharT> temp_data(other.m_data);
+ other.m_data = m_data;
+ m_data = temp_data;
+ }
+ }
+
+ basic_string<CharT, Traits> substr(size_type pos = 0,
+ size_type count = npos) const
+ {
+ return basic_string<CharT, Traits>(*this, pos, count);
+ }
+
+ /// Finds the first character \p ch
+ size_type find(CharT ch, size_type pos = 0) const
+ {
+ const_iterator iter = ::boost::compute::find(begin() + pos, end(), ch);
+ if(iter == end()){
+ return npos;
+ }
+ else {
+ return static_cast<size_type>(std::distance(begin(), iter));
+ }
+ }
+
+ /// Finds the first substring equal to \p str
+ size_type find(basic_string& str, size_type pos = 0) const
+ {
+ const_iterator iter = ::boost::compute::search(begin() + pos, end(),
+ str.begin(), str.end());
+ if(iter == end()){
+ return npos;
+ }
+ else {
+ return static_cast<size_type>(std::distance(begin(), iter));
+ }
+ }
+
+ /// Finds the first substring equal to the character string
+ /// pointed to by \p s.
+ /// The length of the string is determined by the first null character.
+ ///
+ /// For example, the following code
+ /// \snippet test/test_string.cpp string_find
+ ///
+ /// will return 5 as position.
+ size_type find(const char* s, size_type pos = 0) const
+ {
+ basic_string str(s);
+ const_iterator iter = ::boost::compute::search(begin() + pos, end(),
+ str.begin(), str.end());
+ if(iter == end()){
+ return npos;
+ }
+ else {
+ return static_cast<size_type>(std::distance(begin(), iter));
+ }
+ }
+
+private:
+ ::boost::compute::vector<CharT> m_data;
+};
+
+template<class CharT, class Traits>
+std::ostream&
+operator<<(std::ostream& stream,
+ boost::compute::basic_string<CharT, Traits>const& outStr)
+{
+ command_queue queue = ::boost::compute::system::default_queue();
+ boost::compute::copy(outStr.begin(),
+ outStr.end(),
+ std::ostream_iterator<CharT>(stream),
+ queue);
+ return stream;
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_CONTAINER_BASIC_STRING_HPP
diff --git a/boost/compute/container/detail/scalar.hpp b/boost/compute/container/detail/scalar.hpp
new file mode 100644
index 0000000000..7ecd86e540
--- /dev/null
+++ b/boost/compute/container/detail/scalar.hpp
@@ -0,0 +1,61 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_CONTAINER_DETAIL_SCALAR_HPP
+#define BOOST_COMPUTE_CONTAINER_DETAIL_SCALAR_HPP
+
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/detail/read_write_single_value.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+// scalar<T> provides a trivial "container" that stores a
+// single value in a memory buffer on a compute device
+template<class T>
+class scalar
+{
+public:
+ typedef T value_type;
+
+ scalar(const context &context)
+ : m_buffer(context, sizeof(T))
+ {
+ }
+
+ ~scalar()
+ {
+ }
+
+ T read(command_queue &queue) const
+ {
+ return read_single_value<T>(m_buffer, 0, queue);
+ }
+
+ void write(const T &value, command_queue &queue)
+ {
+ write_single_value<T>(value, m_buffer, 0, queue);
+ }
+
+ const buffer& get_buffer() const
+ {
+ return m_buffer;
+ }
+
+private:
+ buffer m_buffer;
+};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_CONTAINER_DETAIL_SCALAR_HPP
diff --git a/boost/compute/container/dynamic_bitset.hpp b/boost/compute/container/dynamic_bitset.hpp
new file mode 100644
index 0000000000..7f41901d64
--- /dev/null
+++ b/boost/compute/container/dynamic_bitset.hpp
@@ -0,0 +1,237 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_CONTAINER_DYNAMIC_BITSET_HPP
+#define BOOST_COMPUTE_CONTAINER_DYNAMIC_BITSET_HPP
+
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/algorithm/any_of.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/algorithm/transform_reduce.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/functional/integer.hpp>
+#include <boost/compute/types/fundamental.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class dynamic_bitset
+/// \brief The dynamic_bitset class contains a resizable bit array.
+///
+/// For example, to create a dynamic-bitset with space for 1000 bits on the
+/// device:
+/// \code
+/// boost::compute::dynamic_bitset<> bits(1000, queue);
+/// \endcode
+///
+/// The Boost.Compute \c dynamic_bitset class provides a STL-like API and is
+/// modeled after the \c boost::dynamic_bitset class from Boost.
+///
+/// \see \ref vector "vector<T>"
+template<class Block = ulong_, class Alloc = buffer_allocator<Block> >
+class dynamic_bitset
+{
+public:
+ typedef Block block_type;
+ typedef Alloc allocator_type;
+ typedef vector<Block, Alloc> container_type;
+ typedef typename container_type::size_type size_type;
+
+ BOOST_STATIC_CONSTANT(size_type, bits_per_block = sizeof(block_type) * CHAR_BIT);
+ BOOST_STATIC_CONSTANT(size_type, npos = static_cast<size_type>(-1));
+
+ /// Creates a new dynamic bitset with storage for \p size bits. Initializes
+ /// all bits to zero.
+ dynamic_bitset(size_type size, command_queue &queue)
+ : m_bits(size / sizeof(block_type), queue.get_context()),
+ m_size(size)
+ {
+ // initialize all bits to zero
+ reset(queue);
+ }
+
+ /// Creates a new dynamic bitset as a copy of \p other.
+ dynamic_bitset(const dynamic_bitset &other)
+ : m_bits(other.m_bits),
+ m_size(other.m_size)
+ {
+ }
+
+ /// Copies the data from \p other to \c *this.
+ dynamic_bitset& operator=(const dynamic_bitset &other)
+ {
+ if(this != &other){
+ m_bits = other.m_bits;
+ m_size = other.m_size;
+ }
+
+ return *this;
+ }
+
+ /// Destroys the dynamic bitset.
+ ~dynamic_bitset()
+ {
+ }
+
+ /// Returns the size of the dynamic bitset.
+ size_type size() const
+ {
+ return m_size;
+ }
+
+ /// Returns the number of blocks to store the bits in the dynamic bitset.
+ size_type num_blocks() const
+ {
+ return m_bits.size();
+ }
+
+ /// Returns the maximum possible size for the dynamic bitset.
+ size_type max_size() const
+ {
+ return m_bits.max_size() * bits_per_block;
+ }
+
+ /// Returns \c true if the dynamic bitset is empty (i.e. \c size() == \c 0).
+ bool empty() const
+ {
+ return size() == 0;
+ }
+
+ /// Returns the number of set bits (i.e. '1') in the bitset.
+ size_type count(command_queue &queue) const
+ {
+ ulong_ count = 0;
+ transform_reduce(
+ m_bits.begin(),
+ m_bits.end(),
+ &count,
+ popcount<block_type>(),
+ plus<ulong_>(),
+ queue
+ );
+ return static_cast<size_type>(count);
+ }
+
+ /// Resizes the bitset to contain \p num_bits. If the new size is greater
+ /// than the current size the new bits are set to zero.
+ void resize(size_type num_bits, command_queue &queue)
+ {
+ // resize bits
+ const size_type current_block_count = m_bits.size();
+ m_bits.resize(num_bits * bits_per_block, queue);
+
+ // fill new block with zeros (if new blocks were added)
+ const size_type new_block_count = m_bits.size();
+ if(new_block_count > current_block_count){
+ fill_n(
+ m_bits.begin() + current_block_count,
+ new_block_count - current_block_count,
+ block_type(0),
+ queue
+ );
+ }
+
+ // store new size
+ m_size = num_bits;
+ }
+
+ /// Sets the bit at position \p n to \c true.
+ void set(size_type n, command_queue &queue)
+ {
+ set(n, true, queue);
+ }
+
+ /// Sets the bit at position \p n to \p value.
+ void set(size_type n, bool value, command_queue &queue)
+ {
+ const size_type bit = n % bits_per_block;
+ const size_type block = n / bits_per_block;
+
+ // load current block
+ block_type block_value;
+ copy_n(m_bits.begin() + block, 1, &block_value, queue);
+
+ // update block value
+ if(value){
+ block_value |= (size_type(1) << bit);
+ }
+ else {
+ block_value &= ~(size_type(1) << bit);
+ }
+
+ // store new block
+ copy_n(&block_value, 1, m_bits.begin() + block, queue);
+ }
+
+ /// Returns \c true if the bit at position \p n is set (i.e. '1').
+ bool test(size_type n, command_queue &queue)
+ {
+ const size_type bit = n % (sizeof(block_type) * CHAR_BIT);
+ const size_type block = n / (sizeof(block_type) * CHAR_BIT);
+
+ block_type block_value;
+ copy_n(m_bits.begin() + block, 1, &block_value, queue);
+
+ return block_value & (size_type(1) << bit);
+ }
+
+ /// Flips the value of the bit at position \p n.
+ void flip(size_type n, command_queue &queue)
+ {
+ set(n, !test(n, queue), queue);
+ }
+
+ /// Returns \c true if any bit in the bitset is set (i.e. '1').
+ bool any(command_queue &queue) const
+ {
+ return any_of(
+ m_bits.begin(), m_bits.end(), lambda::_1 != block_type(0), queue
+ );
+ }
+
+ /// Returns \c true if all of the bits in the bitset are set to zero.
+ bool none(command_queue &queue) const
+ {
+ return !any(queue);
+ }
+
+ /// Sets all of the bits in the bitset to zero.
+ void reset(command_queue &queue)
+ {
+ fill(m_bits.begin(), m_bits.end(), block_type(0), queue);
+ }
+
+ /// Sets the bit at position \p n to zero.
+ void reset(size_type n, command_queue &queue)
+ {
+ set(n, false, queue);
+ }
+
+ /// Empties the bitset (e.g. \c resize(0)).
+ void clear()
+ {
+ m_bits.clear();
+ }
+
+ /// Returns the allocator used to allocate storage for the bitset.
+ allocator_type get_allocator() const
+ {
+ return m_bits.get_allocator();
+ }
+
+private:
+ container_type m_bits;
+ size_type m_size;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_CONTAINER_DYNAMIC_BITSET_HPP
diff --git a/boost/compute/container/flat_map.hpp b/boost/compute/container/flat_map.hpp
new file mode 100644
index 0000000000..684c4da122
--- /dev/null
+++ b/boost/compute/container/flat_map.hpp
@@ -0,0 +1,406 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_CONTAINER_FLAT_MAP_HPP
+#define BOOST_COMPUTE_CONTAINER_FLAT_MAP_HPP
+
+#include <cstddef>
+#include <utility>
+#include <exception>
+
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+
+#include <boost/compute/exception.hpp>
+#include <boost/compute/algorithm/find.hpp>
+#include <boost/compute/algorithm/lower_bound.hpp>
+#include <boost/compute/algorithm/upper_bound.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/functional/get.hpp>
+#include <boost/compute/iterator/transform_iterator.hpp>
+#include <boost/compute/types/pair.hpp>
+#include <boost/compute/detail/buffer_value.hpp>
+
+namespace boost {
+namespace compute {
+
+template<class Key, class T>
+class flat_map
+{
+public:
+ typedef Key key_type;
+ typedef T mapped_type;
+ typedef typename ::boost::compute::vector<std::pair<Key, T> > vector_type;
+ typedef typename vector_type::value_type value_type;
+ typedef typename vector_type::size_type size_type;
+ typedef typename vector_type::difference_type difference_type;
+ typedef typename vector_type::reference reference;
+ typedef typename vector_type::const_reference const_reference;
+ typedef typename vector_type::pointer pointer;
+ typedef typename vector_type::const_pointer const_pointer;
+ typedef typename vector_type::iterator iterator;
+ typedef typename vector_type::const_iterator const_iterator;
+ typedef typename vector_type::reverse_iterator reverse_iterator;
+ typedef typename vector_type::const_reverse_iterator const_reverse_iterator;
+
+ explicit flat_map(const context &context = system::default_context())
+ : m_vector(context)
+ {
+ }
+
+ flat_map(const flat_map<Key, T> &other)
+ : m_vector(other.m_vector)
+ {
+ }
+
+ flat_map<Key, T>& operator=(const flat_map<Key, T> &other)
+ {
+ if(this != &other){
+ m_vector = other.m_vector;
+ }
+
+ return *this;
+ }
+
+ ~flat_map()
+ {
+ }
+
+ iterator begin()
+ {
+ return m_vector.begin();
+ }
+
+ const_iterator begin() const
+ {
+ return m_vector.begin();
+ }
+
+ const_iterator cbegin() const
+ {
+ return m_vector.cbegin();
+ }
+
+ iterator end()
+ {
+ return m_vector.end();
+ }
+
+ const_iterator end() const
+ {
+ return m_vector.end();
+ }
+
+ const_iterator cend() const
+ {
+ return m_vector.cend();
+ }
+
+ reverse_iterator rbegin()
+ {
+ return m_vector.rbegin();
+ }
+
+ const_reverse_iterator rbegin() const
+ {
+ return m_vector.rbegin();
+ }
+
+ const_reverse_iterator crbegin() const
+ {
+ return m_vector.crbegin();
+ }
+
+ reverse_iterator rend()
+ {
+ return m_vector.rend();
+ }
+
+ const_reverse_iterator rend() const
+ {
+ return m_vector.rend();
+ }
+
+ const_reverse_iterator crend() const
+ {
+ return m_vector.crend();
+ }
+
+ size_type size() const
+ {
+ return m_vector.size();
+ }
+
+ size_type max_size() const
+ {
+ return m_vector.max_size();
+ }
+
+ bool empty() const
+ {
+ return m_vector.empty();
+ }
+
+ size_type capacity() const
+ {
+ return m_vector.capacity();
+ }
+
+ void reserve(size_type size, command_queue &queue)
+ {
+ m_vector.reserve(size, queue);
+ }
+
+ void reserve(size_type size)
+ {
+ command_queue queue = m_vector.default_queue();
+ reserve(size, queue);
+ queue.finish();
+ }
+
+ void shrink_to_fit()
+ {
+ m_vector.shrink_to_fit();
+ }
+
+ void clear()
+ {
+ m_vector.clear();
+ }
+
+ std::pair<iterator, bool>
+ insert(const value_type &value, command_queue &queue)
+ {
+ iterator location = upper_bound(value.first, queue);
+
+ if(location != begin()){
+ value_type current_value;
+ ::boost::compute::copy_n(location - 1, 1, &current_value, queue);
+ if(value.first == current_value.first){
+ return std::make_pair(location - 1, false);
+ }
+ }
+
+ m_vector.insert(location, value);
+ return std::make_pair(location, true);
+ }
+
+ std::pair<iterator, bool> insert(const value_type &value)
+ {
+ command_queue queue = m_vector.default_queue();
+ std::pair<iterator, bool> result = insert(value, queue);
+ queue.finish();
+ return result;
+ }
+
+ iterator erase(const const_iterator &position, command_queue &queue)
+ {
+ return erase(position, position + 1, queue);
+ }
+
+ iterator erase(const const_iterator &position)
+ {
+ command_queue queue = m_vector.default_queue();
+ iterator iter = erase(position, queue);
+ queue.finish();
+ return iter;
+ }
+
+ iterator erase(const const_iterator &first,
+ const const_iterator &last,
+ command_queue &queue)
+ {
+ return m_vector.erase(first, last, queue);
+ }
+
+ iterator erase(const const_iterator &first, const const_iterator &last)
+ {
+ command_queue queue = m_vector.default_queue();
+ iterator iter = erase(first, last, queue);
+ queue.finish();
+ return iter;
+ }
+
+ size_type erase(const key_type &value, command_queue &queue)
+ {
+ iterator position = find(value, queue);
+
+ if(position == end()){
+ return 0;
+ }
+ else {
+ erase(position, queue);
+ return 1;
+ }
+ }
+
+ iterator find(const key_type &value, command_queue &queue)
+ {
+ ::boost::compute::get<0> get_key;
+
+ return ::boost::compute::find(
+ ::boost::compute::make_transform_iterator(begin(), get_key),
+ ::boost::compute::make_transform_iterator(end(), get_key),
+ value,
+ queue
+ ).base();
+ }
+
+ iterator find(const key_type &value)
+ {
+ command_queue queue = m_vector.default_queue();
+ iterator iter = find(value, queue);
+ queue.finish();
+ return iter;
+ }
+
+ const_iterator find(const key_type &value, command_queue &queue) const
+ {
+ ::boost::compute::get<0> get_key;
+
+ return ::boost::compute::find(
+ ::boost::compute::make_transform_iterator(begin(), get_key),
+ ::boost::compute::make_transform_iterator(end(), get_key),
+ value,
+ queue
+ ).base();
+ }
+
+ const_iterator find(const key_type &value) const
+ {
+ command_queue queue = m_vector.default_queue();
+ const_iterator iter = find(value, queue);
+ queue.finish();
+ return iter;
+ }
+
+ size_type count(const key_type &value, command_queue &queue) const
+ {
+ return find(value, queue) != end() ? 1 : 0;
+ }
+
+ size_type count(const key_type &value) const
+ {
+ command_queue queue = m_vector.default_queue();
+ size_type result = count(value, queue);
+ queue.finish();
+ return result;
+ }
+
+ iterator lower_bound(const key_type &value, command_queue &queue)
+ {
+ ::boost::compute::get<0> get_key;
+
+ return ::boost::compute::lower_bound(
+ ::boost::compute::make_transform_iterator(begin(), get_key),
+ ::boost::compute::make_transform_iterator(end(), get_key),
+ value,
+ queue
+ ).base();
+ }
+
+ iterator lower_bound(const key_type &value)
+ {
+ command_queue queue = m_vector.default_queue();
+ iterator iter = lower_bound(value, queue);
+ queue.finish();
+ return iter;
+ }
+
+ const_iterator lower_bound(const key_type &value, command_queue &queue) const
+ {
+ ::boost::compute::get<0> get_key;
+
+ return ::boost::compute::lower_bound(
+ ::boost::compute::make_transform_iterator(begin(), get_key),
+ ::boost::compute::make_transform_iterator(end(), get_key),
+ value,
+ queue
+ ).base();
+ }
+
+ const_iterator lower_bound(const key_type &value) const
+ {
+ command_queue queue = m_vector.default_queue();
+ const_iterator iter = lower_bound(value, queue);
+ queue.finish();
+ return iter;
+ }
+
+ iterator upper_bound(const key_type &value, command_queue &queue)
+ {
+ ::boost::compute::get<0> get_key;
+
+ return ::boost::compute::upper_bound(
+ ::boost::compute::make_transform_iterator(begin(), get_key),
+ ::boost::compute::make_transform_iterator(end(), get_key),
+ value,
+ queue
+ ).base();
+ }
+
+ iterator upper_bound(const key_type &value)
+ {
+ command_queue queue = m_vector.default_queue();
+ iterator iter = upper_bound(value, queue);
+ queue.finish();
+ return iter;
+ }
+
+ const_iterator upper_bound(const key_type &value, command_queue &queue) const
+ {
+ ::boost::compute::get<0> get_key;
+
+ return ::boost::compute::upper_bound(
+ ::boost::compute::make_transform_iterator(begin(), get_key),
+ ::boost::compute::make_transform_iterator(end(), get_key),
+ value,
+ queue
+ ).base();
+ }
+
+ const_iterator upper_bound(const key_type &value) const
+ {
+ command_queue queue = m_vector.default_queue();
+ const_iterator iter = upper_bound(value, queue);
+ queue.finish();
+ return iter;
+ }
+
+ const mapped_type at(const key_type &key) const
+ {
+ const_iterator iter = find(key);
+ if(iter == end()){
+ BOOST_THROW_EXCEPTION(std::out_of_range("key not found"));
+ }
+
+ return value_type(*iter).second;
+ }
+
+ detail::buffer_value<mapped_type> operator[](const key_type &key)
+ {
+ iterator iter = find(key);
+ if(iter == end()){
+ iter = insert(std::make_pair(key, mapped_type())).first;
+ }
+
+ size_t index = iter.get_index() * sizeof(value_type) + sizeof(key_type);
+
+ return detail::buffer_value<mapped_type>(m_vector.get_buffer(), index);
+ }
+
+private:
+ ::boost::compute::vector<std::pair<Key, T> > m_vector;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_CONTAINER_FLAT_MAP_HPP
diff --git a/boost/compute/container/flat_set.hpp b/boost/compute/container/flat_set.hpp
new file mode 100644
index 0000000000..8826f78846
--- /dev/null
+++ b/boost/compute/container/flat_set.hpp
@@ -0,0 +1,339 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_CONTAINER_FLAT_SET_HPP
+#define BOOST_COMPUTE_CONTAINER_FLAT_SET_HPP
+
+#include <cstddef>
+#include <utility>
+
+#include <boost/compute/algorithm/find.hpp>
+#include <boost/compute/algorithm/lower_bound.hpp>
+#include <boost/compute/algorithm/upper_bound.hpp>
+#include <boost/compute/container/vector.hpp>
+
+namespace boost {
+namespace compute {
+
+template<class T>
+class flat_set
+{
+public:
+ typedef T key_type;
+ typedef typename vector<T>::value_type value_type;
+ typedef typename vector<T>::size_type size_type;
+ typedef typename vector<T>::difference_type difference_type;
+ typedef typename vector<T>::reference reference;
+ typedef typename vector<T>::const_reference const_reference;
+ typedef typename vector<T>::pointer pointer;
+ typedef typename vector<T>::const_pointer const_pointer;
+ typedef typename vector<T>::iterator iterator;
+ typedef typename vector<T>::const_iterator const_iterator;
+ typedef typename vector<T>::reverse_iterator reverse_iterator;
+ typedef typename vector<T>::const_reverse_iterator const_reverse_iterator;
+
+ explicit flat_set(const context &context = system::default_context())
+ : m_vector(context)
+ {
+ }
+
+ flat_set(const flat_set<T> &other)
+ : m_vector(other.m_vector)
+ {
+ }
+
+ flat_set<T>& operator=(const flat_set<T> &other)
+ {
+ if(this != &other){
+ m_vector = other.m_vector;
+ }
+
+ return *this;
+ }
+
+ ~flat_set()
+ {
+ }
+
+ iterator begin()
+ {
+ return m_vector.begin();
+ }
+
+ const_iterator begin() const
+ {
+ return m_vector.begin();
+ }
+
+ const_iterator cbegin() const
+ {
+ return m_vector.cbegin();
+ }
+
+ iterator end()
+ {
+ return m_vector.end();
+ }
+
+ const_iterator end() const
+ {
+ return m_vector.end();
+ }
+
+ const_iterator cend() const
+ {
+ return m_vector.cend();
+ }
+
+ reverse_iterator rbegin()
+ {
+ return m_vector.rbegin();
+ }
+
+ const_reverse_iterator rbegin() const
+ {
+ return m_vector.rbegin();
+ }
+
+ const_reverse_iterator crbegin() const
+ {
+ return m_vector.crbegin();
+ }
+
+ reverse_iterator rend()
+ {
+ return m_vector.rend();
+ }
+
+ const_reverse_iterator rend() const
+ {
+ return m_vector.rend();
+ }
+
+ const_reverse_iterator crend() const
+ {
+ return m_vector.crend();
+ }
+
+ size_type size() const
+ {
+ return m_vector.size();
+ }
+
+ size_type max_size() const
+ {
+ return m_vector.max_size();
+ }
+
+ bool empty() const
+ {
+ return m_vector.empty();
+ }
+
+ size_type capacity() const
+ {
+ return m_vector.capacity();
+ }
+
+ void reserve(size_type size, command_queue &queue)
+ {
+ m_vector.reserve(size, queue);
+ }
+
+ void reserve(size_type size)
+ {
+ command_queue queue = m_vector.default_queue();
+ reserve(size, queue);
+ queue.finish();
+ }
+
+ void shrink_to_fit()
+ {
+ m_vector.shrink_to_fit();
+ }
+
+ void clear()
+ {
+ m_vector.clear();
+ }
+
+ std::pair<iterator, bool>
+ insert(const value_type &value, command_queue &queue)
+ {
+ iterator location = upper_bound(value, queue);
+
+ if(location != begin()){
+ value_type current_value;
+ ::boost::compute::copy_n(location - 1, 1, &current_value, queue);
+ if(value == current_value){
+ return std::make_pair(location - 1, false);
+ }
+ }
+
+ m_vector.insert(location, value, queue);
+ return std::make_pair(location, true);
+ }
+
+ std::pair<iterator, bool> insert(const value_type &value)
+ {
+ command_queue queue = m_vector.default_queue();
+ std::pair<iterator, bool> result = insert(value, queue);
+ queue.finish();
+ return result;
+ }
+
+ iterator erase(const const_iterator &position, command_queue &queue)
+ {
+ return erase(position, position + 1, queue);
+ }
+
+ iterator erase(const const_iterator &position)
+ {
+ command_queue queue = m_vector.default_queue();
+ iterator iter = erase(position, queue);
+ queue.finish();
+ return iter;
+ }
+
+ iterator erase(const const_iterator &first,
+ const const_iterator &last,
+ command_queue &queue)
+ {
+ return m_vector.erase(first, last, queue);
+ }
+
+ iterator erase(const const_iterator &first, const const_iterator &last)
+ {
+ command_queue queue = m_vector.default_queue();
+ iterator iter = erase(first, last, queue);
+ queue.finish();
+ return iter;
+ }
+
+ size_type erase(const key_type &value, command_queue &queue)
+ {
+ iterator position = find(value, queue);
+
+ if(position == end()){
+ return 0;
+ }
+ else {
+ erase(position, queue);
+ return 1;
+ }
+ }
+
+ size_type erase(const key_type &value)
+ {
+ command_queue queue = m_vector.default_queue();
+ size_type result = erase(value, queue);
+ queue.finish();
+ return result;
+ }
+
+ iterator find(const key_type &value, command_queue &queue)
+ {
+ return ::boost::compute::find(begin(), end(), value, queue);
+ }
+
+ iterator find(const key_type &value)
+ {
+ command_queue queue = m_vector.default_queue();
+ iterator iter = find(value, queue);
+ queue.finish();
+ return iter;
+ }
+
+ const_iterator find(const key_type &value, command_queue &queue) const
+ {
+ return ::boost::compute::find(begin(), end(), value, queue);
+ }
+
+ const_iterator find(const key_type &value) const
+ {
+ command_queue queue = m_vector.default_queue();
+ const_iterator iter = find(value, queue);
+ queue.finish();
+ return iter;
+ }
+
+ size_type count(const key_type &value, command_queue &queue) const
+ {
+ return find(value, queue) != end() ? 1 : 0;
+ }
+
+ size_type count(const key_type &value) const
+ {
+ command_queue queue = m_vector.default_queue();
+ size_type result = count(value, queue);
+ queue.finish();
+ return result;
+ }
+
+ iterator lower_bound(const key_type &value, command_queue &queue)
+ {
+ return ::boost::compute::lower_bound(begin(), end(), value, queue);
+ }
+
+ iterator lower_bound(const key_type &value)
+ {
+ command_queue queue = m_vector.default_queue();
+ iterator iter = lower_bound(value, queue);
+ queue.finish();
+ return iter;
+ }
+
+ const_iterator lower_bound(const key_type &value, command_queue &queue) const
+ {
+ return ::boost::compute::lower_bound(begin(), end(), value, queue);
+ }
+
+ const_iterator lower_bound(const key_type &value) const
+ {
+ command_queue queue = m_vector.default_queue();
+ const_iterator iter = lower_bound(value, queue);
+ queue.finish();
+ return iter;
+ }
+
+ iterator upper_bound(const key_type &value, command_queue &queue)
+ {
+ return ::boost::compute::upper_bound(begin(), end(), value, queue);
+ }
+
+ iterator upper_bound(const key_type &value)
+ {
+ command_queue queue = m_vector.default_queue();
+ iterator iter = upper_bound(value, queue);
+ queue.finish();
+ return iter;
+ }
+
+ const_iterator upper_bound(const key_type &value, command_queue &queue) const
+ {
+ return ::boost::compute::upper_bound(begin(), end(), value, queue);
+ }
+
+ const_iterator upper_bound(const key_type &value) const
+ {
+ command_queue queue = m_vector.default_queue();
+ const_iterator iter = upper_bound(value, queue);
+ queue.finish();
+ return iter;
+ }
+
+private:
+ vector<T> m_vector;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_CONTAINER_FLAT_SET_HPP
diff --git a/boost/compute/container/mapped_view.hpp b/boost/compute/container/mapped_view.hpp
new file mode 100644
index 0000000000..59b1e4e0a4
--- /dev/null
+++ b/boost/compute/container/mapped_view.hpp
@@ -0,0 +1,250 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_CONTAINER_MAPPED_VIEW_HPP
+#define BOOST_COMPUTE_CONTAINER_MAPPED_VIEW_HPP
+
+#include <cstddef>
+#include <exception>
+
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class mapped_view
+/// \brief A mapped view of host memory.
+///
+/// The mapped_view class simplifies mapping host-memory to a compute
+/// device. This allows for host-allocated memory to be used with the
+/// Boost.Compute algorithms.
+///
+/// The following example shows how to map a simple C-array containing
+/// data on the host to the device and run the reduce() algorithm to
+/// calculate the sum:
+///
+/// \snippet test/test_mapped_view.cpp reduce
+///
+/// \see buffer
+template<class T>
+class mapped_view
+{
+public:
+ typedef T value_type;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef buffer_iterator<T> iterator;
+ typedef buffer_iterator<T> const_iterator;
+
+ /// Creates a null mapped_view object.
+ mapped_view()
+ {
+ m_mapped_ptr = 0;
+ }
+
+ /// Creates a mapped_view for \p host_ptr with \p n elements. After
+ /// constructing a mapped_view the data is available for use by a
+ /// compute device. Use the \p unmap() method to make the updated data
+ /// available to the host.
+ mapped_view(T *host_ptr,
+ size_type n,
+ const context &context = system::default_context())
+ : m_buffer(_make_mapped_buffer(host_ptr, n, context))
+ {
+ m_mapped_ptr = 0;
+ }
+
+ /// Creates a read-only mapped_view for \p host_ptr with \p n elements.
+ /// After constructing a mapped_view the data is available for use by a
+ /// compute device. Use the \p unmap() method to make the updated data
+ /// available to the host.
+ mapped_view(const T *host_ptr,
+ size_type n,
+ const context &context = system::default_context())
+ : m_buffer(_make_mapped_buffer(host_ptr, n, context))
+ {
+ m_mapped_ptr = 0;
+ }
+
+ /// Creates a copy of \p other.
+ mapped_view(const mapped_view<T> &other)
+ : m_buffer(other.m_buffer)
+ {
+ m_mapped_ptr = 0;
+ }
+
+ /// Copies the mapped buffer from \p other.
+ mapped_view<T>& operator=(const mapped_view<T> &other)
+ {
+ if(this != &other){
+ m_buffer = other.m_buffer;
+ m_mapped_ptr = 0;
+ }
+
+ return *this;
+ }
+
+ /// Destroys the mapped_view object.
+ ~mapped_view()
+ {
+ }
+
+ /// Returns an iterator to the first element in the mapped_view.
+ iterator begin()
+ {
+ return ::boost::compute::make_buffer_iterator<T>(m_buffer, 0);
+ }
+
+ /// Returns a const_iterator to the first element in the mapped_view.
+ const_iterator begin() const
+ {
+ return ::boost::compute::make_buffer_iterator<T>(m_buffer, 0);
+ }
+
+ /// Returns a const_iterator to the first element in the mapped_view.
+ const_iterator cbegin() const
+ {
+ return begin();
+ }
+
+ /// Returns an iterator to one past the last element in the mapped_view.
+ iterator end()
+ {
+ return ::boost::compute::make_buffer_iterator<T>(m_buffer, size());
+ }
+
+ /// Returns a const_iterator to one past the last element in the mapped_view.
+ const_iterator end() const
+ {
+ return ::boost::compute::make_buffer_iterator<T>(m_buffer, size());
+ }
+
+ /// Returns a const_iterator to one past the last element in the mapped_view.
+ const_iterator cend() const
+ {
+ return end();
+ }
+
+ /// Returns the number of elements in the mapped_view.
+ size_type size() const
+ {
+ return m_buffer.size() / sizeof(T);
+ }
+
+ /// Returns the host data pointer.
+ T* get_host_ptr()
+ {
+ return static_cast<T *>(m_buffer.get_info<void *>(CL_MEM_HOST_PTR));
+ }
+
+ /// Returns the host data pointer.
+ const T* get_host_ptr() const
+ {
+ return static_cast<T *>(m_buffer.get_info<void *>(CL_MEM_HOST_PTR));
+ }
+
+ /// Resizes the mapped_view to \p size elements.
+ void resize(size_type size)
+ {
+ T *old_ptr = get_host_ptr();
+
+ m_buffer = _make_mapped_buffer(old_ptr, size, m_buffer.get_context());
+ }
+
+ /// Returns \c true if the mapped_view is empty.
+ bool empty() const
+ {
+ return size() == 0;
+ }
+
+ /// Returns the mapped buffer.
+ const buffer& get_buffer() const
+ {
+ return m_buffer;
+ }
+
+ /// Maps the buffer into the host address space.
+ ///
+ /// \see_opencl_ref{clEnqueueMapBuffer}
+ void map(cl_map_flags flags, command_queue &queue)
+ {
+ BOOST_ASSERT(m_mapped_ptr == 0);
+
+ m_mapped_ptr = queue.enqueue_map_buffer(
+ m_buffer, flags, 0, m_buffer.size()
+ );
+ }
+
+ /// Maps the buffer into the host address space for reading and writing.
+ ///
+ /// Equivalent to:
+ /// \code
+ /// map(CL_MAP_READ | CL_MAP_WRITE, queue);
+ /// \endcode
+ void map(command_queue &queue)
+ {
+ map(CL_MAP_READ | CL_MAP_WRITE, queue);
+ }
+
+ /// Unmaps the buffer from the host address space.
+ ///
+ /// \see_opencl_ref{clEnqueueUnmapMemObject}
+ void unmap(command_queue &queue)
+ {
+ BOOST_ASSERT(m_mapped_ptr != 0);
+
+ queue.enqueue_unmap_buffer(m_buffer, m_mapped_ptr);
+
+ m_mapped_ptr = 0;
+ }
+
+private:
+ /// \internal_
+ static buffer _make_mapped_buffer(T *host_ptr,
+ size_t n,
+ const context &context)
+ {
+ return buffer(
+ context,
+ n * sizeof(T),
+ buffer::read_write | buffer::use_host_ptr,
+ host_ptr
+ );
+ }
+
+ /// \internal_
+ static buffer _make_mapped_buffer(const T *host_ptr,
+ size_t n,
+ const context &context)
+ {
+ return buffer(
+ context,
+ n * sizeof(T),
+ buffer::read_only | buffer::use_host_ptr,
+ const_cast<void *>(static_cast<const void *>(host_ptr))
+ );
+ }
+
+private:
+ buffer m_buffer;
+ void *m_mapped_ptr;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_CONTAINER_MAPPED_VIEW_HPP
diff --git a/boost/compute/container/stack.hpp b/boost/compute/container/stack.hpp
new file mode 100644
index 0000000000..dc86df459a
--- /dev/null
+++ b/boost/compute/container/stack.hpp
@@ -0,0 +1,81 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_CONTAINER_STACK_HPP
+#define BOOST_COMPUTE_CONTAINER_STACK_HPP
+
+#include <boost/compute/container/vector.hpp>
+
+namespace boost {
+namespace compute {
+
+template<class T>
+class stack
+{
+public:
+ typedef vector<T> container_type;
+ typedef typename container_type::size_type size_type;
+ typedef typename container_type::value_type value_type;
+
+ stack()
+ {
+ }
+
+ stack(const stack<T> &other)
+ : m_vector(other.m_vector)
+ {
+ }
+
+ stack<T>& operator=(const stack<T> &other)
+ {
+ if(this != &other){
+ m_vector = other.m_vector;
+ }
+
+ return *this;
+ }
+
+ ~stack()
+ {
+ }
+
+ bool empty() const
+ {
+ return m_vector.empty();
+ }
+
+ size_type size() const
+ {
+ return m_vector.size();
+ }
+
+ value_type top() const
+ {
+ return m_vector.back();
+ }
+
+ void push(const T &value)
+ {
+ m_vector.push_back(value);
+ }
+
+ void pop()
+ {
+ m_vector.pop_back();
+ }
+
+private:
+ container_type m_vector;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_CONTAINER_STACK_HPP
diff --git a/boost/compute/container/string.hpp b/boost/compute/container/string.hpp
new file mode 100644
index 0000000000..a721ab5746
--- /dev/null
+++ b/boost/compute/container/string.hpp
@@ -0,0 +1,25 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_CONTAINER_STRING_HPP
+#define BOOST_COMPUTE_CONTAINER_STRING_HPP
+
+#include <boost/compute/types/fundamental.hpp>
+#include <boost/compute/container/basic_string.hpp>
+
+namespace boost {
+namespace compute {
+
+typedef basic_string<char_> string;
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_CONTAINER_STRING_HPP
diff --git a/boost/compute/container/valarray.hpp b/boost/compute/container/valarray.hpp
new file mode 100644
index 0000000000..8ac8e01753
--- /dev/null
+++ b/boost/compute/container/valarray.hpp
@@ -0,0 +1,499 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_CONTAINER_VALARRAY_HPP
+#define BOOST_COMPUTE_CONTAINER_VALARRAY_HPP
+
+#include <cstddef>
+#include <valarray>
+
+#include <boost/static_assert.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/algorithm/max_element.hpp>
+#include <boost/compute/algorithm/min_element.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/algorithm/accumulate.hpp>
+#include <boost/compute/detail/buffer_value.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/functional/bind.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+#include <boost/compute/type_traits.hpp>
+
+namespace boost {
+namespace compute {
+
+template<class T>
+class valarray
+{
+public:
+ explicit valarray(const context &context = system::default_context())
+ : m_buffer(context, 0)
+ {
+ }
+
+ explicit valarray(size_t size,
+ const context &context = system::default_context())
+ : m_buffer(context, size * sizeof(T))
+ {
+ }
+
+ valarray(const T &value,
+ size_t size,
+ const context &context = system::default_context())
+ : m_buffer(context, size * sizeof(T))
+ {
+ fill(begin(), end(), value);
+ }
+
+ valarray(const T *values,
+ size_t size,
+ const context &context = system::default_context())
+ : m_buffer(context, size * sizeof(T))
+ {
+ copy(values, values + size, begin());
+ }
+
+ valarray(const valarray<T> &other)
+ : m_buffer(other.m_buffer.get_context(), other.size() * sizeof(T))
+ {
+ }
+
+ valarray(const std::valarray<T> &valarray,
+ const context &context = system::default_context())
+ : m_buffer(context, valarray.size() * sizeof(T))
+ {
+ copy(&valarray[0], &valarray[valarray.size()], begin());
+ }
+
+ valarray<T>& operator=(const valarray<T> &other)
+ {
+ if(this != &other){
+ // change to other's OpenCL context
+ m_buffer = buffer(other.m_buffer.get_context(), other.size() * sizeof(T));
+ copy(other.begin(), other.end(), begin());
+ }
+
+ return *this;
+ }
+
+ valarray<T>& operator=(const std::valarray<T> &valarray)
+ {
+ m_buffer = buffer(m_buffer.get_context(), valarray.size() * sizeof(T));
+ copy(&valarray[0], &valarray[valarray.size()], begin());
+
+ return *this;
+ }
+
+ valarray<T>& operator*=(const T&);
+
+ valarray<T>& operator/=(const T&);
+
+ valarray<T>& operator%=(const T& val);
+
+ valarray<T> operator+() const
+ {
+ // This operator can be used with any type.
+ valarray<T> result(size());
+ copy(begin(), end(), result.begin());
+ return result;
+ }
+
+ valarray<T> operator-() const
+ {
+ BOOST_STATIC_ASSERT_MSG(
+ is_fundamental<T>::value,
+ "This operator can be used with all OpenCL built-in scalar"
+ " and vector types"
+ );
+ valarray<T> result(size());
+ BOOST_COMPUTE_FUNCTION(T, unary_minus, (T x),
+ {
+ return -x;
+ });
+ transform(begin(), end(), result.begin(), unary_minus);
+ return result;
+ }
+
+ valarray<T> operator~() const
+ {
+ BOOST_STATIC_ASSERT_MSG(
+ is_fundamental<T>::value &&
+ !is_floating_point<typename scalar_type<T>::type>::value,
+ "This operator can be used with all OpenCL built-in scalar"
+ " and vector types except the built-in scalar and vector float types"
+ );
+ valarray<T> result(size());
+ BOOST_COMPUTE_FUNCTION(T, bitwise_not, (T x),
+ {
+ return ~x;
+ });
+ transform(begin(), end(), result.begin(), bitwise_not);
+ return result;
+ }
+
+ /// In OpenCL there cannot be memory buffer with bool type, for
+ /// this reason return type is valarray<char> instead of valarray<bool>.
+ /// 1 means true, 0 means false.
+ valarray<char> operator!() const
+ {
+ BOOST_STATIC_ASSERT_MSG(
+ is_fundamental<T>::value,
+ "This operator can be used with all OpenCL built-in scalar"
+ " and vector types"
+ );
+ valarray<char> result(size());
+ BOOST_COMPUTE_FUNCTION(char, logical_not, (T x),
+ {
+ return !x;
+ });
+ transform(begin(), end(), &result[0], logical_not);
+ return result;
+ }
+
+ valarray<T>& operator+=(const T&);
+
+ valarray<T>& operator-=(const T&);
+
+ valarray<T>& operator^=(const T&);
+
+ valarray<T>& operator&=(const T&);
+
+ valarray<T>& operator|=(const T&);
+
+ valarray<T>& operator<<=(const T&);
+
+ valarray<T>& operator>>=(const T&);
+
+ valarray<T>& operator*=(const valarray<T>&);
+
+ valarray<T>& operator/=(const valarray<T>&);
+
+ valarray<T>& operator%=(const valarray<T>&);
+
+ valarray<T>& operator+=(const valarray<T>&);
+
+ valarray<T>& operator-=(const valarray<T>&);
+
+ valarray<T>& operator^=(const valarray<T>&);
+
+ valarray<T>& operator&=(const valarray<T>&);
+
+ valarray<T>& operator|=(const valarray<T>&);
+
+ valarray<T>& operator<<=(const valarray<T>&);
+
+ valarray<T>& operator>>=(const valarray<T>&);
+
+ ~valarray()
+ {
+
+ }
+
+ size_t size() const
+ {
+ return m_buffer.size() / sizeof(T);
+ }
+
+ void resize(size_t size, T value = T())
+ {
+ m_buffer = buffer(m_buffer.get_context(), size * sizeof(T));
+ fill(begin(), end(), value);
+ }
+
+ detail::buffer_value<T> operator[](size_t index)
+ {
+ return *(begin() + static_cast<ptrdiff_t>(index));
+ }
+
+ const detail::buffer_value<T> operator[](size_t index) const
+ {
+ return *(begin() + static_cast<ptrdiff_t>(index));
+ }
+
+ T (min)() const
+ {
+ return *(boost::compute::min_element(begin(), end()));
+ }
+
+ T (max)() const
+ {
+ return *(boost::compute::max_element(begin(), end()));
+ }
+
+ T sum() const
+ {
+ return boost::compute::accumulate(begin(), end(), T(0));
+ }
+
+ template<class UnaryFunction>
+ valarray<T> apply(UnaryFunction function) const
+ {
+ valarray<T> result(size());
+ transform(begin(), end(), result.begin(), function);
+ return result;
+ }
+
+ const buffer& get_buffer() const
+ {
+ return m_buffer;
+ }
+
+
+private:
+ buffer_iterator<T> begin() const
+ {
+ return buffer_iterator<T>(m_buffer, 0);
+ }
+
+ buffer_iterator<T> end() const
+ {
+ return buffer_iterator<T>(m_buffer, size());
+ }
+
+private:
+ buffer m_buffer;
+};
+
+/// \internal_
+#define BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT(op, op_name, assert) \
+ template<class T> \
+ inline valarray<T>& \
+ valarray<T>::operator op##=(const T& val) \
+ { \
+ assert \
+ transform(begin(), end(), begin(), \
+ ::boost::compute::bind(op_name<T>(), placeholders::_1, val)); \
+ return *this; \
+ } \
+ \
+ template<class T> \
+ inline valarray<T>& \
+ valarray<T>::operator op##=(const valarray<T> &rhs) \
+ { \
+ assert \
+ transform(begin(), end(), rhs.begin(), begin(), op_name<T>()); \
+ return *this; \
+ }
+
+/// \internal_
+#define BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(op, op_name) \
+ BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT(op, op_name, \
+ BOOST_STATIC_ASSERT_MSG( \
+ is_fundamental<T>::value, \
+ "This operator can be used with all OpenCL built-in scalar" \
+ " and vector types" \
+ ); \
+ )
+
+/// \internal_
+/// For some operators class T can't be floating point type.
+/// See OpenCL specification, operators chapter.
+#define BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(op, op_name) \
+ BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT(op, op_name, \
+ BOOST_STATIC_ASSERT_MSG( \
+ is_fundamental<T>::value && \
+ !is_floating_point<typename scalar_type<T>::type>::value, \
+ "This operator can be used with all OpenCL built-in scalar" \
+ " and vector types except the built-in scalar and vector float types" \
+ ); \
+ )
+
+// defining operators
+BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(+, plus)
+BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(-, minus)
+BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(*, multiplies)
+BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(/, divides)
+BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(^, bit_xor)
+BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(&, bit_and)
+BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(|, bit_or)
+BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(<<, shift_left)
+BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(>>, shift_right)
+
+// The remainder (%) operates on
+// integer scalar and integer vector data types only.
+// See OpenCL specification.
+BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT(%, modulus,
+ BOOST_STATIC_ASSERT_MSG(
+ is_integral<typename scalar_type<T>::type>::value,
+ "This operator can be used only with OpenCL built-in integer types"
+ );
+)
+
+#undef BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY
+#undef BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP
+
+#undef BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT
+
+/// \internal_
+/// Macro for defining binary operators for valarray
+#define BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR(op, op_name, assert) \
+ template<class T> \
+ valarray<T> operator op (const valarray<T>& lhs, const valarray<T>& rhs) \
+ { \
+ assert \
+ valarray<T> result(lhs.size()); \
+ transform(buffer_iterator<T>(lhs.get_buffer(), 0), \
+ buffer_iterator<T>(lhs.get_buffer(), lhs.size()), \
+ buffer_iterator<T>(rhs.get_buffer(), 0), \
+ buffer_iterator<T>(result.get_buffer(), 0), \
+ op_name<T>()); \
+ return result; \
+ } \
+ \
+ template<class T> \
+ valarray<T> operator op (const T& val, const valarray<T>& rhs) \
+ { \
+ assert \
+ valarray<T> result(rhs.size()); \
+ transform(buffer_iterator<T>(rhs.get_buffer(), 0), \
+ buffer_iterator<T>(rhs.get_buffer(), rhs.size()), \
+ buffer_iterator<T>(result.get_buffer(), 0), \
+ ::boost::compute::bind(op_name<T>(), val, placeholders::_1)); \
+ return result; \
+ } \
+ \
+ template<class T> \
+ valarray<T> operator op (const valarray<T>& lhs, const T& val) \
+ { \
+ assert \
+ valarray<T> result(lhs.size()); \
+ transform(buffer_iterator<T>(lhs.get_buffer(), 0), \
+ buffer_iterator<T>(lhs.get_buffer(), lhs.size()), \
+ buffer_iterator<T>(result.get_buffer(), 0), \
+ ::boost::compute::bind(op_name<T>(), placeholders::_1, val)); \
+ return result; \
+ }
+
+/// \internal_
+#define BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(op, op_name) \
+ BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR(op, op_name, \
+ BOOST_STATIC_ASSERT_MSG( \
+ is_fundamental<T>::value, \
+ "This operator can be used with all OpenCL built-in scalar" \
+ " and vector types" \
+ ); \
+ )
+
+/// \internal_
+/// For some operators class T can't be floating point type.
+/// See OpenCL specification, operators chapter.
+#define BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(op, op_name) \
+ BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR(op, op_name, \
+ BOOST_STATIC_ASSERT_MSG( \
+ is_fundamental<T>::value && \
+ !is_floating_point<typename scalar_type<T>::type>::value, \
+ "This operator can be used with all OpenCL built-in scalar" \
+ " and vector types except the built-in scalar and vector float types" \
+ ); \
+ )
+
+// defining binary operators for valarray
+BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(+, plus)
+BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(-, minus)
+BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(*, multiplies)
+BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(/, divides)
+BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(^, bit_xor)
+BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(&, bit_and)
+BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(|, bit_or)
+BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(<<, shift_left)
+BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(>>, shift_right)
+
+#undef BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY
+#undef BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP
+
+#undef BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR
+
+/// \internal_
+/// Macro for defining valarray comparison operators.
+/// For return type valarray<char> is used instead of valarray<bool> because
+/// in OpenCL there cannot be memory buffer with bool type.
+///
+/// Note it's also used for defining binary logical operators (==, &&)
+#define BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(op, op_name) \
+ template<class T> \
+ valarray<char> operator op (const valarray<T>& lhs, const valarray<T>& rhs) \
+ { \
+ BOOST_STATIC_ASSERT_MSG( \
+ is_fundamental<T>::value, \
+ "This operator can be used with all OpenCL built-in scalar" \
+ " and vector types" \
+ ); \
+ valarray<char> result(lhs.size()); \
+ transform(buffer_iterator<T>(lhs.get_buffer(), 0), \
+ buffer_iterator<T>(lhs.get_buffer(), lhs.size()), \
+ buffer_iterator<T>(rhs.get_buffer(), 0), \
+ buffer_iterator<char>(result.get_buffer(), 0), \
+ op_name<T>()); \
+ return result; \
+ } \
+ \
+ template<class T> \
+ valarray<char> operator op (const T& val, const valarray<T>& rhs) \
+ { \
+ BOOST_STATIC_ASSERT_MSG( \
+ is_fundamental<T>::value, \
+ "This operator can be used with all OpenCL built-in scalar" \
+ " and vector types" \
+ ); \
+ valarray<char> result(rhs.size()); \
+ transform(buffer_iterator<T>(rhs.get_buffer(), 0), \
+ buffer_iterator<T>(rhs.get_buffer(), rhs.size()), \
+ buffer_iterator<char>(result.get_buffer(), 0), \
+ ::boost::compute::bind(op_name<T>(), val, placeholders::_1)); \
+ return result; \
+ } \
+ \
+ template<class T> \
+ valarray<char> operator op (const valarray<T>& lhs, const T& val) \
+ { \
+ BOOST_STATIC_ASSERT_MSG( \
+ is_fundamental<T>::value, \
+ "This operator can be used with all OpenCL built-in scalar" \
+ " and vector types" \
+ ); \
+ valarray<char> result(lhs.size()); \
+ transform(buffer_iterator<T>(lhs.get_buffer(), 0), \
+ buffer_iterator<T>(lhs.get_buffer(), lhs.size()), \
+ buffer_iterator<char>(result.get_buffer(), 0), \
+ ::boost::compute::bind(op_name<T>(), placeholders::_1, val)); \
+ return result; \
+ }
+
+BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(==, equal_to)
+BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(!=, not_equal_to)
+BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(>, greater)
+BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(<, less)
+BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(>=, greater_equal)
+BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(<=, less_equal)
+
+/// \internal_
+/// Macro for defining binary logical operators for valarray.
+///
+/// For return type valarray<char> is used instead of valarray<bool> because
+/// in OpenCL there cannot be memory buffer with bool type.
+/// 1 means true, 0 means false.
+#define BOOST_COMPUTE_DEFINE_VALARRAY_LOGICAL_OPERATOR(op, op_name) \
+ BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(op, op_name)
+
+BOOST_COMPUTE_DEFINE_VALARRAY_LOGICAL_OPERATOR(&&, logical_and)
+BOOST_COMPUTE_DEFINE_VALARRAY_LOGICAL_OPERATOR(||, logical_or)
+
+#undef BOOST_COMPUTE_DEFINE_VALARRAY_LOGICAL_OPERATOR
+
+#undef BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_CONTAINER_VALARRAY_HPP
diff --git a/boost/compute/container/vector.hpp b/boost/compute/container/vector.hpp
new file mode 100644
index 0000000000..47d649ad99
--- /dev/null
+++ b/boost/compute/container/vector.hpp
@@ -0,0 +1,761 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_CONTAINER_VECTOR_HPP
+#define BOOST_COMPUTE_CONTAINER_VECTOR_HPP
+
+#include <vector>
+#include <cstddef>
+#include <iterator>
+#include <exception>
+
+#include <boost/throw_exception.hpp>
+
+#include <boost/compute/config.hpp>
+
+#ifndef BOOST_COMPUTE_NO_HDR_INITIALIZER_LIST
+#include <initializer_list>
+#endif
+
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/device.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/algorithm/fill_n.hpp>
+#include <boost/compute/allocator/buffer_allocator.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+#include <boost/compute/type_traits/detail/capture_traits.hpp>
+#include <boost/compute/detail/buffer_value.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class vector
+/// \brief A resizable array of values.
+///
+/// The vector<T> class stores a dynamic array of values. Internally, the data
+/// is stored in an OpenCL buffer object.
+///
+/// The vector class is the prefered container for storing and accessing data
+/// on a compute device. In most cases it should be used instead of directly
+/// dealing with buffer objects. If the undelying buffer is needed, it can be
+/// accessed with the get_buffer() method.
+///
+/// The internal storage is allocated in a specific OpenCL context which is
+/// passed as an argument to the constructor when the vector is created.
+///
+/// For example, to create a vector on the device containing space for ten
+/// \c int values:
+/// \code
+/// boost::compute::vector<int> vec(10, context);
+/// \endcode
+///
+/// Allocation and data transfer can also be performed in a single step:
+/// \code
+/// // values on the host
+/// int data[] = { 1, 2, 3, 4 };
+///
+/// // create a vector of size four and copy the values from data
+/// boost::compute::vector<int> vec(data, data + 4, queue);
+/// \endcode
+///
+/// The Boost.Compute \c vector class provides a STL-like API and is modeled
+/// after the \c std::vector class from the C++ standard library. It can be
+/// used with any of the STL-like algorithms provided by Boost.Compute
+/// including \c copy(), \c transform(), and \c sort() (among many others).
+///
+/// For example:
+/// \code
+/// // a vector on a compute device
+/// boost::compute::vector<float> vec = ...
+///
+/// // copy data to the vector from a host std:vector
+/// boost::compute::copy(host_vec.begin(), host_vec.end(), vec.begin(), queue);
+///
+/// // copy data from the vector to a host std::vector
+/// boost::compute::copy(vec.begin(), vec.end(), host_vec.begin(), queue);
+///
+/// // sort the values in the vector
+/// boost::compute::sort(vec.begin(), vec.end(), queue);
+///
+/// // calculate the sum of the values in the vector (also see reduce())
+/// float sum = boost::compute::accumulate(vec.begin(), vec.end(), 0, queue);
+///
+/// // reverse the values in the vector
+/// boost::compute::reverse(vec.begin(), vec.end(), queue);
+///
+/// // fill the vector with ones
+/// boost::compute::fill(vec.begin(), vec.end(), 1, queue);
+/// \endcode
+///
+/// \see \ref array "array<T, N>", buffer
+template<class T, class Alloc = buffer_allocator<T> >
+class vector
+{
+public:
+ typedef T value_type;
+ typedef Alloc allocator_type;
+ typedef typename allocator_type::size_type size_type;
+ typedef typename allocator_type::difference_type difference_type;
+ typedef detail::buffer_value<T> reference;
+ typedef const detail::buffer_value<T> const_reference;
+ typedef typename allocator_type::pointer pointer;
+ typedef typename allocator_type::const_pointer const_pointer;
+ typedef buffer_iterator<T> iterator;
+ typedef buffer_iterator<T> const_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ /// Creates an empty vector in \p context.
+ explicit vector(const context &context = system::default_context())
+ : m_size(0),
+ m_allocator(context)
+ {
+ m_data = m_allocator.allocate(_minimum_capacity());
+ }
+
+ /// Creates a vector with space for \p count elements in \p context.
+ ///
+ /// Note that unlike \c std::vector's constructor, this will not initialize
+ /// the values in the container. Either call the vector constructor which
+ /// takes a value to initialize with or use the fill() algorithm to set
+ /// the initial values.
+ ///
+ /// For example:
+ /// \code
+ /// // create a vector on the device with space for ten ints
+ /// boost::compute::vector<int> vec(10, context);
+ /// \endcode
+ explicit vector(size_type count,
+ const context &context = system::default_context())
+ : m_size(count),
+ m_allocator(context)
+ {
+ m_data = m_allocator.allocate((std::max)(count, _minimum_capacity()));
+ }
+
+ /// Creates a vector with space for \p count elements and sets each equal
+ /// to \p value.
+ ///
+ /// For example:
+ /// \code
+ /// // creates a vector with four values set to nine (e.g. [9, 9, 9, 9]).
+ /// boost::compute::vector<int> vec(4, 9, queue);
+ /// \endcode
+ vector(size_type count,
+ const T &value,
+ command_queue &queue = system::default_queue())
+ : m_size(count),
+ m_allocator(queue.get_context())
+ {
+ m_data = m_allocator.allocate((std::max)(count, _minimum_capacity()));
+
+ ::boost::compute::fill_n(begin(), count, value, queue);
+ }
+
+ /// Creates a vector with space for the values in the range [\p first,
+ /// \p last) and copies them into the vector with \p queue.
+ ///
+ /// For example:
+ /// \code
+ /// // values on the host
+ /// int data[] = { 1, 2, 3, 4 };
+ ///
+ /// // create a vector of size four and copy the values from data
+ /// boost::compute::vector<int> vec(data, data + 4, queue);
+ /// \endcode
+ template<class InputIterator>
+ vector(InputIterator first,
+ InputIterator last,
+ command_queue &queue = system::default_queue())
+ : m_size(detail::iterator_range_size(first, last)),
+ m_allocator(queue.get_context())
+ {
+ m_data = m_allocator.allocate((std::max)(m_size, _minimum_capacity()));
+
+ ::boost::compute::copy(first, last, begin(), queue);
+ }
+
+ /// Creates a new vector and copies the values from \p other.
+ vector(const vector &other,
+ command_queue &queue = system::default_queue())
+ : m_size(other.m_size),
+ m_allocator(other.m_allocator)
+ {
+ m_data = m_allocator.allocate((std::max)(m_size, _minimum_capacity()));
+
+ if(!other.empty()){
+ ::boost::compute::copy(other.begin(), other.end(), begin(), queue);
+ queue.finish();
+ }
+ }
+
+ /// Creates a new vector and copies the values from \p other.
+ template<class OtherAlloc>
+ vector(const vector<T, OtherAlloc> &other,
+ command_queue &queue = system::default_queue())
+ : m_size(other.size()),
+ m_allocator(queue.get_context())
+ {
+ m_data = m_allocator.allocate((std::max)(m_size, _minimum_capacity()));
+
+ if(!other.empty()){
+ ::boost::compute::copy(other.begin(), other.end(), begin(), queue);
+ queue.finish();
+ }
+ }
+
+ /// Creates a new vector and copies the values from \p vector.
+ template<class OtherAlloc>
+ vector(const std::vector<T, OtherAlloc> &vector,
+ command_queue &queue = system::default_queue())
+ : m_size(vector.size()),
+ m_allocator(queue.get_context())
+ {
+ m_data = m_allocator.allocate((std::max)(m_size, _minimum_capacity()));
+
+ ::boost::compute::copy(vector.begin(), vector.end(), begin(), queue);
+ }
+
+ #ifndef BOOST_COMPUTE_NO_HDR_INITIALIZER_LIST
+ vector(std::initializer_list<T> list,
+ command_queue &queue = system::default_queue())
+ : m_size(list.size()),
+ m_allocator(queue.get_context())
+ {
+ m_data = m_allocator.allocate((std::max)(m_size, _minimum_capacity()));
+
+ ::boost::compute::copy(list.begin(), list.end(), begin(), queue);
+ }
+ #endif // BOOST_COMPUTE_NO_HDR_INITIALIZER_LIST
+
+ vector& operator=(const vector &other)
+ {
+ if(this != &other){
+ command_queue queue = default_queue();
+ resize(other.size(), queue);
+ ::boost::compute::copy(other.begin(), other.end(), begin(), queue);
+ queue.finish();
+ }
+
+ return *this;
+ }
+
+ template<class OtherAlloc>
+ vector& operator=(const std::vector<T, OtherAlloc> &vector)
+ {
+ command_queue queue = default_queue();
+ resize(vector.size(), queue);
+ ::boost::compute::copy(vector.begin(), vector.end(), begin(), queue);
+ queue.finish();
+ return *this;
+ }
+
+ #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+ /// Move-constructs a new vector from \p other.
+ vector(vector&& other)
+ : m_data(std::move(other.m_data)),
+ m_size(other.m_size),
+ m_allocator(std::move(other.m_allocator))
+ {
+ other.m_size = 0;
+ }
+
+ /// Move-assigns the data from \p other to \c *this.
+ vector& operator=(vector&& other)
+ {
+ if(m_size){
+ m_allocator.deallocate(m_data, m_size);
+ }
+
+ m_data = std::move(other.m_data);
+ m_size = other.m_size;
+ m_allocator = std::move(other.m_allocator);
+
+ other.m_size = 0;
+
+ return *this;
+ }
+ #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+ /// Destroys the vector object.
+ ~vector()
+ {
+ if(m_size){
+ m_allocator.deallocate(m_data, m_size);
+ }
+ }
+
+ iterator begin()
+ {
+ return ::boost::compute::make_buffer_iterator<T>(m_data.get_buffer(), 0);
+ }
+
+ const_iterator begin() const
+ {
+ return ::boost::compute::make_buffer_iterator<T>(m_data.get_buffer(), 0);
+ }
+
+ const_iterator cbegin() const
+ {
+ return begin();
+ }
+
+ iterator end()
+ {
+ return ::boost::compute::make_buffer_iterator<T>(m_data.get_buffer(), m_size);
+ }
+
+ const_iterator end() const
+ {
+ return ::boost::compute::make_buffer_iterator<T>(m_data.get_buffer(), m_size);
+ }
+
+ const_iterator cend() const
+ {
+ return end();
+ }
+
+ reverse_iterator rbegin()
+ {
+ return reverse_iterator(end() - 1);
+ }
+
+ const_reverse_iterator rbegin() const
+ {
+ return reverse_iterator(end() - 1);
+ }
+
+ const_reverse_iterator crbegin() const
+ {
+ return rbegin();
+ }
+
+ reverse_iterator rend()
+ {
+ return reverse_iterator(begin() - 1);
+ }
+
+ const_reverse_iterator rend() const
+ {
+ return reverse_iterator(begin() - 1);
+ }
+
+ const_reverse_iterator crend() const
+ {
+ return rend();
+ }
+
+ /// Returns the number of elements in the vector.
+ size_type size() const
+ {
+ return m_size;
+ }
+
+ size_type max_size() const
+ {
+ return m_allocator.max_size();
+ }
+
+ /// Resizes the vector to \p size.
+ void resize(size_type size, command_queue &queue)
+ {
+ if(size < capacity()){
+ m_size = size;
+ }
+ else {
+ // allocate new buffer
+ pointer new_data =
+ m_allocator.allocate(
+ static_cast<size_type>(
+ static_cast<float>(size) * _growth_factor()
+ )
+ );
+
+ // copy old values to the new buffer
+ ::boost::compute::copy(m_data, m_data + m_size, new_data, queue);
+
+ // free old memory
+ m_allocator.deallocate(m_data, m_size);
+
+ // set new data and size
+ m_data = new_data;
+ m_size = size;
+ }
+ }
+
+ /// \overload
+ void resize(size_type size)
+ {
+ command_queue queue = default_queue();
+ resize(size, queue);
+ queue.finish();
+ }
+
+ /// Returns \c true if the vector is empty.
+ bool empty() const
+ {
+ return m_size == 0;
+ }
+
+ /// Returns the capacity of the vector.
+ size_type capacity() const
+ {
+ return m_data.get_buffer().size() / sizeof(T);
+ }
+
+ void reserve(size_type size, command_queue &queue)
+ {
+ (void) size;
+ (void) queue;
+ }
+
+ void reserve(size_type size)
+ {
+ command_queue queue = default_queue();
+ reserve(size, queue);
+ queue.finish();
+ }
+
+ void shrink_to_fit(command_queue &queue)
+ {
+ (void) queue;
+ }
+
+ void shrink_to_fit()
+ {
+ command_queue queue = default_queue();
+ shrink_to_fit(queue);
+ queue.finish();
+ }
+
+ reference operator[](size_type index)
+ {
+ return *(begin() + static_cast<difference_type>(index));
+ }
+
+ const_reference operator[](size_type index) const
+ {
+ return *(begin() + static_cast<difference_type>(index));
+ }
+
+ reference at(size_type index)
+ {
+ if(index >= size()){
+ BOOST_THROW_EXCEPTION(std::out_of_range("index out of range"));
+ }
+
+ return operator[](index);
+ }
+
+ const_reference at(size_type index) const
+ {
+ if(index >= size()){
+ BOOST_THROW_EXCEPTION(std::out_of_range("index out of range"));
+ }
+
+ return operator[](index);
+ }
+
+ reference front()
+ {
+ return *begin();
+ }
+
+ const_reference front() const
+ {
+ return *begin();
+ }
+
+ reference back()
+ {
+ return *(end() - static_cast<difference_type>(1));
+ }
+
+ const_reference back() const
+ {
+ return *(end() - static_cast<difference_type>(1));
+ }
+
+ template<class InputIterator>
+ void assign(InputIterator first,
+ InputIterator last,
+ command_queue &queue)
+ {
+ // resize vector for new contents
+ resize(detail::iterator_range_size(first, last), queue);
+
+ // copy values into the vector
+ ::boost::compute::copy(first, last, begin(), queue);
+ }
+
+ template<class InputIterator>
+ void assign(InputIterator first, InputIterator last)
+ {
+ command_queue queue = default_queue();
+ assign(first, last, queue);
+ queue.finish();
+ }
+
+ void assign(size_type n, const T &value, command_queue &queue)
+ {
+ // resize vector for new contents
+ resize(n, queue);
+
+ // fill vector with value
+ ::boost::compute::fill_n(begin(), n, value, queue);
+ }
+
+ void assign(size_type n, const T &value)
+ {
+ command_queue queue = default_queue();
+ assign(n, value, queue);
+ queue.finish();
+ }
+
+ /// Inserts \p value at the end of the vector (resizing if neccessary).
+ ///
+ /// Note that calling \c push_back() to insert data values one at a time
+ /// is inefficient as there is a non-trivial overhead in performing a data
+ /// transfer to the device. It is usually better to store a set of values
+ /// on the host (for example, in a \c std::vector) and then transfer them
+ /// in bulk using the \c insert() method or the copy() algorithm.
+ void push_back(const T &value, command_queue &queue)
+ {
+ insert(end(), value, queue);
+ }
+
+ /// \overload
+ void push_back(const T &value)
+ {
+ command_queue queue = default_queue();
+ push_back(value, queue);
+ queue.finish();
+ }
+
+ void pop_back(command_queue &queue)
+ {
+ resize(size() - 1, queue);
+ }
+
+ void pop_back()
+ {
+ command_queue queue = default_queue();
+ pop_back(queue);
+ queue.finish();
+ }
+
+ iterator insert(iterator position, const T &value, command_queue &queue)
+ {
+ if(position == end()){
+ resize(m_size + 1, queue);
+ position = begin() + position.get_index();
+ ::boost::compute::copy_n(&value, 1, position, queue);
+ }
+ else {
+ ::boost::compute::vector<T, Alloc> tmp(position, end(), queue);
+ resize(m_size + 1, queue);
+ position = begin() + position.get_index();
+ ::boost::compute::copy_n(&value, 1, position, queue);
+ ::boost::compute::copy(tmp.begin(), tmp.end(), position + 1, queue);
+ }
+
+ return position + 1;
+ }
+
+ iterator insert(iterator position, const T &value)
+ {
+ command_queue queue = default_queue();
+ iterator iter = insert(position, value, queue);
+ queue.finish();
+ return iter;
+ }
+
+ void insert(iterator position,
+ size_type count,
+ const T &value,
+ command_queue &queue)
+ {
+ ::boost::compute::vector<T, Alloc> tmp(position, end(), queue);
+ resize(size() + count, queue);
+
+ position = begin() + position.get_index();
+
+ ::boost::compute::fill_n(position, count, value, queue);
+ ::boost::compute::copy(
+ tmp.begin(),
+ tmp.end(),
+ position + static_cast<difference_type>(count),
+ queue
+ );
+ }
+
+ void insert(iterator position, size_type count, const T &value)
+ {
+ command_queue queue = default_queue();
+ insert(position, count, value, queue);
+ queue.finish();
+ }
+
+ /// Inserts the values in the range [\p first, \p last) into the vector at
+ /// \p position using \p queue.
+ template<class InputIterator>
+ void insert(iterator position,
+ InputIterator first,
+ InputIterator last,
+ command_queue &queue)
+ {
+ ::boost::compute::vector<T, Alloc> tmp(position, end(), queue);
+
+ size_type count = detail::iterator_range_size(first, last);
+ resize(size() + count, queue);
+
+ position = begin() + position.get_index();
+
+ ::boost::compute::copy(first, last, position, queue);
+ ::boost::compute::copy(
+ tmp.begin(),
+ tmp.end(),
+ position + static_cast<difference_type>(count),
+ queue
+ );
+ }
+
+ /// \overload
+ template<class InputIterator>
+ void insert(iterator position, InputIterator first, InputIterator last)
+ {
+ command_queue queue = default_queue();
+ insert(position, first, last, queue);
+ queue.finish();
+ }
+
+ iterator erase(iterator position, command_queue &queue)
+ {
+ return erase(position, position + 1, queue);
+ }
+
+ iterator erase(iterator position)
+ {
+ command_queue queue = default_queue();
+ iterator iter = erase(position, queue);
+ queue.finish();
+ return iter;
+ }
+
+ iterator erase(iterator first, iterator last, command_queue &queue)
+ {
+ if(last != end()){
+ ::boost::compute::vector<T, Alloc> tmp(last, end(), queue);
+ ::boost::compute::copy(tmp.begin(), tmp.end(), first, queue);
+ }
+
+ difference_type count = std::distance(first, last);
+ resize(size() - static_cast<size_type>(count), queue);
+
+ return begin() + first.get_index() + count;
+ }
+
+ iterator erase(iterator first, iterator last)
+ {
+ command_queue queue = default_queue();
+ iterator iter = erase(first, last, queue);
+ queue.finish();
+ return iter;
+ }
+
+ /// Swaps the contents of \c *this with \p other.
+ void swap(vector &other)
+ {
+ std::swap(m_data, other.m_data);
+ std::swap(m_size, other.m_size);
+ std::swap(m_allocator, other.m_allocator);
+ }
+
+ /// Removes all elements from the vector.
+ void clear()
+ {
+ m_size = 0;
+ }
+
+ allocator_type get_allocator() const
+ {
+ return m_allocator;
+ }
+
+ /// Returns the underlying buffer.
+ const buffer& get_buffer() const
+ {
+ return m_data.get_buffer();
+ }
+
+ /// \internal_
+ ///
+ /// Returns a command queue usable to issue commands for the vector's
+ /// memory buffer. This is used when a member function is called without
+ /// specifying an existing command queue to use.
+ command_queue default_queue() const
+ {
+ const context &context = m_allocator.get_context();
+ command_queue queue(context, context.get_device());
+ return queue;
+ }
+
+private:
+ /// \internal_
+ BOOST_CONSTEXPR size_type _minimum_capacity() const { return 4; }
+
+ /// \internal_
+ BOOST_CONSTEXPR float _growth_factor() const { return 1.5; }
+
+private:
+ pointer m_data;
+ size_type m_size;
+ allocator_type m_allocator;
+};
+
+namespace detail {
+
+// set_kernel_arg specialization for vector<T>
+template<class T, class Alloc>
+struct set_kernel_arg<vector<T, Alloc> >
+{
+ void operator()(kernel &kernel_, size_t index, const vector<T, Alloc> &vector)
+ {
+ kernel_.set_arg(index, vector.get_buffer());
+ }
+};
+
+// for capturing vector<T> with BOOST_COMPUTE_CLOSURE()
+template<class T, class Alloc>
+struct capture_traits<vector<T, Alloc> >
+{
+ static std::string type_name()
+ {
+ return std::string("__global ") + ::boost::compute::type_name<T>() + "*";
+ }
+};
+
+// meta_kernel streaming operator for vector<T>
+template<class T, class Alloc>
+meta_kernel& operator<<(meta_kernel &k, const vector<T, Alloc> &vector)
+{
+ return k << k.get_buffer_identifier<T>(vector.get_buffer());
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_CONTAINER_VECTOR_HPP
diff --git a/boost/compute/context.hpp b/boost/compute/context.hpp
new file mode 100644
index 0000000000..5db39e9d83
--- /dev/null
+++ b/boost/compute/context.hpp
@@ -0,0 +1,245 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_CONTEXT_HPP
+#define BOOST_COMPUTE_CONTEXT_HPP
+
+#include <vector>
+
+#include <boost/throw_exception.hpp>
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/device.hpp>
+#include <boost/compute/exception/opencl_error.hpp>
+#include <boost/compute/detail/assert_cl_success.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class context
+/// \brief A compute context.
+///
+/// The context class represents a compute context.
+///
+/// A context object manages a set of OpenCL resources including memory
+/// buffers and program objects. Before allocating memory on the device or
+/// executing kernels you must set up a context object.
+///
+/// To create a context for the default device on the system:
+/// \code
+/// // get the default compute device
+/// boost::compute::device gpu = boost::compute::system::default_device();
+///
+/// // create a context for the device
+/// boost::compute::context context(gpu);
+/// \endcode
+///
+/// Once a context is created, memory can be allocated using the buffer class
+/// and kernels can be executed using the command_queue class.
+///
+/// \see device, command_queue
+class context
+{
+public:
+ /// Create a null context object.
+ context()
+ : m_context(0)
+ {
+ }
+
+ /// Creates a new context for \p device with \p properties.
+ ///
+ /// \see_opencl_ref{clCreateContext}
+ explicit context(const device &device,
+ const cl_context_properties *properties = 0)
+ {
+ BOOST_ASSERT(device.id() != 0);
+
+ cl_device_id device_id = device.id();
+
+ cl_int error = 0;
+ m_context = clCreateContext(properties, 1, &device_id, 0, 0, &error);
+
+ if(!m_context){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+ }
+
+ /// Creates a new context for \p devices with \p properties.
+ ///
+ /// \see_opencl_ref{clCreateContext}
+ explicit context(const std::vector<device> &devices,
+ const cl_context_properties *properties = 0)
+ {
+ BOOST_ASSERT(!devices.empty());
+
+ cl_int error = 0;
+
+ m_context = clCreateContext(
+ properties,
+ static_cast<cl_uint>(devices.size()),
+ reinterpret_cast<const cl_device_id *>(&devices[0]),
+ 0,
+ 0,
+ &error
+ );
+
+ if(!m_context){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+ }
+
+ /// Creates a new context object for \p context. If \p retain is
+ /// \c true, the reference count for \p context will be incremented.
+ explicit context(cl_context context, bool retain = true)
+ : m_context(context)
+ {
+ if(m_context && retain){
+ clRetainContext(m_context);
+ }
+ }
+
+ /// Creates a new context object as a copy of \p other.
+ context(const context &other)
+ : m_context(other.m_context)
+ {
+ if(m_context){
+ clRetainContext(m_context);
+ }
+ }
+
+ /// Copies the context object from \p other to \c *this.
+ context& operator=(const context &other)
+ {
+ if(this != &other){
+ if(m_context){
+ clReleaseContext(m_context);
+ }
+
+ m_context = other.m_context;
+
+ if(m_context){
+ clRetainContext(m_context);
+ }
+ }
+
+ return *this;
+ }
+
+ #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+ /// Move-constructs a new context object from \p other.
+ context(context&& other) BOOST_NOEXCEPT
+ : m_context(other.m_context)
+ {
+ other.m_context = 0;
+ }
+
+ /// Move-assigns the context from \p other to \c *this.
+ context& operator=(context&& other) BOOST_NOEXCEPT
+ {
+ if(m_context){
+ clReleaseContext(m_context);
+ }
+
+ m_context = other.m_context;
+ other.m_context = 0;
+
+ return *this;
+ }
+ #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+ /// Destroys the context object.
+ ~context()
+ {
+ if(m_context){
+ BOOST_COMPUTE_ASSERT_CL_SUCCESS(
+ clReleaseContext(m_context)
+ );
+ }
+ }
+
+ /// Returns the underlying OpenCL context.
+ cl_context& get() const
+ {
+ return const_cast<cl_context &>(m_context);
+ }
+
+ /// Returns the device for the context. If the context contains multiple
+ /// devices, the first is returned.
+ device get_device() const
+ {
+ std::vector<device> devices = get_devices();
+
+ if(devices.empty()) {
+ return device();
+ }
+
+ return devices.front();
+ }
+
+ /// Returns a vector of devices for the context.
+ std::vector<device> get_devices() const
+ {
+ return get_info<std::vector<device> >(CL_CONTEXT_DEVICES);
+ }
+
+ /// Returns information about the context.
+ ///
+ /// \see_opencl_ref{clGetContextInfo}
+ template<class T>
+ T get_info(cl_context_info info) const
+ {
+ return detail::get_object_info<T>(clGetContextInfo, m_context, info);
+ }
+
+ /// \overload
+ template<int Enum>
+ typename detail::get_object_info_type<context, Enum>::type
+ get_info() const;
+
+ /// Returns \c true if the context is the same at \p other.
+ bool operator==(const context &other) const
+ {
+ return m_context == other.m_context;
+ }
+
+ /// Returns \c true if the context is different from \p other.
+ bool operator!=(const context &other) const
+ {
+ return m_context != other.m_context;
+ }
+
+ /// \internal_
+ operator cl_context() const
+ {
+ return m_context;
+ }
+
+private:
+ cl_context m_context;
+};
+
+/// \internal_ define get_info() specializations for context
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(context,
+ ((cl_uint, CL_CONTEXT_REFERENCE_COUNT))
+ ((std::vector<cl_device_id>, CL_CONTEXT_DEVICES))
+ ((std::vector<cl_context_properties>, CL_CONTEXT_PROPERTIES))
+)
+
+#ifdef CL_VERSION_1_1
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(context,
+ ((cl_uint, CL_CONTEXT_NUM_DEVICES))
+)
+#endif // CL_VERSION_1_1
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_CONTEXT_HPP
diff --git a/boost/compute/core.hpp b/boost/compute/core.hpp
new file mode 100644
index 0000000000..a8e2eb92a6
--- /dev/null
+++ b/boost/compute/core.hpp
@@ -0,0 +1,32 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_CORE_HPP
+#define BOOST_COMPUTE_CORE_HPP
+
+/// \file
+///
+/// Meta-header to include all Boost.Compute core headers.
+
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/config.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/device.hpp>
+#include <boost/compute/event.hpp>
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/memory_object.hpp>
+#include <boost/compute/platform.hpp>
+#include <boost/compute/program.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/user_event.hpp>
+#include <boost/compute/version.hpp>
+
+#endif // BOOST_COMPUTE_CORE_HPP
diff --git a/boost/compute/detail/assert_cl_success.hpp b/boost/compute/detail/assert_cl_success.hpp
new file mode 100644
index 0000000000..78acaf6caf
--- /dev/null
+++ b/boost/compute/detail/assert_cl_success.hpp
@@ -0,0 +1,24 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_ASSERT_CL_SUCCESS_HPP
+#define BOOST_COMPUTE_DETAIL_ASSERT_CL_SUCCESS_HPP
+
+#include <boost/assert.hpp>
+
+#if defined(BOOST_DISABLE_ASSERTS) || defined(NDEBUG)
+#define BOOST_COMPUTE_ASSERT_CL_SUCCESS(function) \
+ function
+#else
+#define BOOST_COMPUTE_ASSERT_CL_SUCCESS(function) \
+ BOOST_ASSERT(function == CL_SUCCESS)
+#endif
+
+#endif // BOOST_COMPUTE_DETAIL_ASSERT_CL_SUCCESS_HPP
diff --git a/boost/compute/detail/buffer_value.hpp b/boost/compute/detail/buffer_value.hpp
new file mode 100644
index 0000000000..6a4e78fc19
--- /dev/null
+++ b/boost/compute/detail/buffer_value.hpp
@@ -0,0 +1,178 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_BUFFER_VALUE_HPP
+#define BOOST_COMPUTE_DETAIL_BUFFER_VALUE_HPP
+
+#include <boost/compute/context.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/detail/device_ptr.hpp>
+#include <boost/compute/detail/read_write_single_value.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class T>
+class buffer_value
+{
+public:
+ typedef T value_type;
+
+ buffer_value()
+ {
+ }
+
+ buffer_value(const value_type &value)
+ : m_value(value)
+ {
+ }
+
+ // creates a reference for the value in buffer at index (in bytes).
+ buffer_value(const buffer &buffer, size_t index)
+ : m_buffer(buffer.get(), false),
+ m_index(index)
+ {
+ }
+
+ buffer_value(const buffer_value<T> &other)
+ : m_buffer(other.m_buffer.get(), false),
+ m_index(other.m_index)
+ {
+ }
+
+ ~buffer_value()
+ {
+ // set buffer to null so that its reference count will
+ // not be decremented when its destructor is called
+ m_buffer.get() = 0;
+ }
+
+ operator value_type() const
+ {
+ if(m_buffer.get()){
+ const context &context = m_buffer.get_context();
+ const device &device = context.get_device();
+ command_queue queue(context, device);
+
+ return detail::read_single_value<T>(m_buffer, m_index / sizeof(T), queue);
+ }
+ else {
+ return m_value;
+ }
+ }
+
+ buffer_value<T> operator-() const
+ {
+ return -T(*this);
+ }
+
+ bool operator<(const T &value) const
+ {
+ return T(*this) < value;
+ }
+
+ bool operator>(const T &value) const
+ {
+ return T(*this) > value;
+ }
+
+ bool operator<=(const T &value) const
+ {
+ return T(*this) <= value;
+ }
+
+ bool operator>=(const T &value) const
+ {
+ return T(*this) <= value;
+ }
+
+ bool operator==(const T &value) const
+ {
+ return T(*this) == value;
+ }
+
+ bool operator==(const buffer_value<T> &other) const
+ {
+ if(m_buffer.get() != other.m_buffer.get()){
+ return false;
+ }
+
+ if(m_buffer.get()){
+ return m_index == other.m_index;
+ }
+ else {
+ return m_value == other.m_value;
+ }
+ }
+
+ bool operator!=(const T &value) const
+ {
+ return T(*this) != value;
+ }
+
+ buffer_value<T>& operator=(const T &value)
+ {
+ if(m_buffer.get()){
+ const context &context = m_buffer.get_context();
+ command_queue queue(context, context.get_device());
+
+ detail::write_single_value<T>(value, m_buffer, m_index / sizeof(T), queue);
+
+ return *this;
+ }
+ else {
+ m_value = value;
+ return *this;
+ }
+ }
+
+ buffer_value<T>& operator=(const buffer_value<T> &value)
+ {
+ return operator=(T(value));
+ }
+
+ detail::device_ptr<T> operator&() const
+ {
+ return detail::device_ptr<T>(m_buffer, m_index);
+ }
+
+ buffer_value<T>& operator++()
+ {
+ if(m_buffer.get()){
+ T value = T(*this);
+ value++;
+ *this = value;
+ }
+ else {
+ m_value++;
+ }
+
+ return *this;
+ }
+
+ buffer_value<T> operator++(int)
+ {
+ buffer_value<T> result(*this);
+ ++(*this);
+ return result;
+ }
+
+private:
+ const buffer m_buffer;
+ size_t m_index;
+ value_type m_value;
+};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DETAIL_BUFFER_VALUE_HPP
diff --git a/boost/compute/detail/device_ptr.hpp b/boost/compute/detail/device_ptr.hpp
new file mode 100644
index 0000000000..29ecd13631
--- /dev/null
+++ b/boost/compute/detail/device_ptr.hpp
@@ -0,0 +1,215 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DEVICE_PTR_HPP
+#define BOOST_COMPUTE_DEVICE_PTR_HPP
+
+#include <boost/type_traits.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/config.hpp>
+#include <boost/compute/detail/is_buffer_iterator.hpp>
+#include <boost/compute/detail/read_write_single_value.hpp>
+#include <boost/compute/type_traits/is_device_iterator.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class T, class IndexExpr>
+struct device_ptr_index_expr
+{
+ typedef T result_type;
+
+ device_ptr_index_expr(const buffer &buffer,
+ uint_ index,
+ const IndexExpr &expr)
+ : m_buffer(buffer),
+ m_index(index),
+ m_expr(expr)
+ {
+ }
+
+ operator T() const
+ {
+ BOOST_STATIC_ASSERT_MSG(boost::is_integral<IndexExpr>::value,
+ "Index expression must be integral");
+
+ BOOST_ASSERT(m_buffer.get());
+
+ const context &context = m_buffer.get_context();
+ const device &device = context.get_device();
+ command_queue queue(context, device);
+
+ return detail::read_single_value<T>(m_buffer, m_expr, queue);
+ }
+
+ const buffer &m_buffer;
+ uint_ m_index;
+ IndexExpr m_expr;
+};
+
+template<class T>
+class device_ptr
+{
+public:
+ typedef T value_type;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef T* pointer;
+ typedef T& reference;
+
+ device_ptr()
+ : m_index(0)
+ {
+ }
+
+ device_ptr(const buffer &buffer, size_t index = 0)
+ : m_buffer(buffer.get(), false),
+ m_index(index)
+ {
+ }
+
+ device_ptr(const device_ptr<T> &other)
+ : m_buffer(other.m_buffer.get(), false),
+ m_index(other.m_index)
+ {
+ }
+
+ device_ptr<T>& operator=(const device_ptr<T> &other)
+ {
+ if(this != &other){
+ m_buffer.get() = other.m_buffer.get();
+ m_index = other.m_index;
+ }
+
+ return *this;
+ }
+
+ #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+ device_ptr(device_ptr<T>&& other) BOOST_NOEXCEPT
+ : m_buffer(other.m_buffer.get(), false),
+ m_index(other.m_index)
+ {
+ other.m_buffer.get() = 0;
+ }
+
+ device_ptr<T>& operator=(device_ptr<T>&& other) BOOST_NOEXCEPT
+ {
+ m_buffer.get() = other.m_buffer.get();
+ m_index = other.m_index;
+
+ other.m_buffer.get() = 0;
+
+ return *this;
+ }
+ #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+ ~device_ptr()
+ {
+ // set buffer to null so that its reference count will
+ // not be decremented when its destructor is called
+ m_buffer.get() = 0;
+ }
+
+ size_type get_index() const
+ {
+ return m_index;
+ }
+
+ const buffer& get_buffer() const
+ {
+ return m_buffer;
+ }
+
+ template<class OT>
+ device_ptr<OT> cast() const
+ {
+ return device_ptr<OT>(m_buffer, m_index);
+ }
+
+ device_ptr<T> operator+(difference_type n) const
+ {
+ return device_ptr<T>(m_buffer, m_index + n);
+ }
+
+ device_ptr<T> operator+(const device_ptr<T> &other) const
+ {
+ return device_ptr<T>(m_buffer, m_index + other.m_index);
+ }
+
+ device_ptr<T>& operator+=(difference_type n)
+ {
+ m_index += static_cast<size_t>(n);
+ return *this;
+ }
+
+ difference_type operator-(const device_ptr<T> &other) const
+ {
+ return static_cast<difference_type>(m_index - other.m_index);
+ }
+
+ device_ptr<T>& operator-=(difference_type n)
+ {
+ m_index -= n;
+ return *this;
+ }
+
+ bool operator==(const device_ptr<T> &other) const
+ {
+ return m_buffer.get() == other.m_buffer.get() &&
+ m_index == other.m_index;
+ }
+
+ bool operator!=(const device_ptr<T> &other) const
+ {
+ return !(*this == other);
+ }
+
+ template<class Expr>
+ detail::device_ptr_index_expr<T, Expr>
+ operator[](const Expr &expr) const
+ {
+ BOOST_ASSERT(m_buffer.get());
+
+ return detail::device_ptr_index_expr<T, Expr>(m_buffer,
+ uint_(m_index),
+ expr);
+ }
+
+private:
+ const buffer m_buffer;
+ size_t m_index;
+};
+
+// is_buffer_iterator specialization for device_ptr
+template<class Iterator>
+struct is_buffer_iterator<
+ Iterator,
+ typename boost::enable_if<
+ boost::is_same<
+ device_ptr<typename Iterator::value_type>,
+ typename boost::remove_const<Iterator>::type
+ >
+ >::type
+> : public boost::true_type {};
+
+} // end detail namespace
+
+// is_device_iterator specialization for device_ptr
+template<class T>
+struct is_device_iterator<detail::device_ptr<T> > : boost::true_type {};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DEVICE_PTR_HPP
diff --git a/boost/compute/detail/diagnostic.hpp b/boost/compute/detail/diagnostic.hpp
new file mode 100644
index 0000000000..76a69f6570
--- /dev/null
+++ b/boost/compute/detail/diagnostic.hpp
@@ -0,0 +1,112 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2016 Jakub Szuppe <j.szuppe@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_DIAGNOSTIC_HPP
+#define BOOST_COMPUTE_DETAIL_DIAGNOSTIC_HPP
+
+// Macros for suppressing warnings for GCC version 4.6 or later. Usage:
+//
+// BOOST_COMPUTE_BOOST_COMPUTE_GCC_DIAG_OFF(sign-compare);
+// if(a < b){
+// BOOST_COMPUTE_BOOST_COMPUTE_GCC_DIAG_ON(sign-compare);
+//
+// Source: https://svn.boost.org/trac/boost/wiki/Guidelines/WarningsGuidelines
+#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402
+#define BOOST_COMPUTE_GCC_DIAG_STR(s) #s
+#define BOOST_COMPUTE_GCC_DIAG_JOINSTR(x,y) BOOST_COMPUTE_GCC_DIAG_STR(x ## y)
+# define BOOST_COMPUTE_GCC_DIAG_DO_PRAGMA(x) _Pragma (#x)
+# define BOOST_COMPUTE_GCC_DIAG_PRAGMA(x) BOOST_COMPUTE_GCC_DIAG_DO_PRAGMA(GCC diagnostic x)
+# if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406
+# define BOOST_COMPUTE_GCC_DIAG_OFF(x) BOOST_COMPUTE_GCC_DIAG_PRAGMA(push) \
+ BOOST_COMPUTE_GCC_DIAG_PRAGMA(ignored BOOST_COMPUTE_GCC_DIAG_JOINSTR(-W,x))
+# define BOOST_COMPUTE_GCC_DIAG_ON(x) BOOST_COMPUTE_GCC_DIAG_PRAGMA(pop)
+# else
+# define BOOST_COMPUTE_GCC_DIAG_OFF(x) \
+ BOOST_COMPUTE_GCC_DIAG_PRAGMA(ignored BOOST_COMPUTE_GCC_DIAG_JOINSTR(-W,x))
+# define BOOST_COMPUTE_GCC_DIAG_ON(x) \
+ BOOST_COMPUTE_GCC_DIAG_PRAGMA(warning BOOST_COMPUTE_GCC_DIAG_JOINSTR(-W,x))
+# endif
+#else // Ensure these macros do nothing for other compilers.
+# define BOOST_COMPUTE_GCC_DIAG_OFF(x)
+# define BOOST_COMPUTE_GCC_DIAG_ON(x)
+#endif
+
+// Macros for suppressing warnings for Clang.
+//
+// BOOST_COMPUTE_BOOST_COMPUTE_CLANG_DIAG_OFF(sign-compare);
+// if(a < b){
+// BOOST_COMPUTE_BOOST_COMPUTE_CLANG_DIAG_ON(sign-compare);
+//
+// Source: https://svn.boost.org/trac/boost/wiki/Guidelines/WarningsGuidelines
+#ifdef __clang__
+# define BOOST_COMPUTE_CLANG_DIAG_STR(s) # s
+// stringize s to "no-sign-compare"
+# define BOOST_COMPUTE_CLANG_DIAG_JOINSTR(x,y) BOOST_COMPUTE_CLANG_DIAG_STR(x ## y)
+// join -W with no-unused-variable to "-Wno-sign-compare"
+# define BOOST_COMPUTE_CLANG_DIAG_DO_PRAGMA(x) _Pragma (#x)
+// _Pragma is unary operator #pragma ("")
+# define BOOST_COMPUTE_CLANG_DIAG_PRAGMA(x) \
+ BOOST_COMPUTE_CLANG_DIAG_DO_PRAGMA(clang diagnostic x)
+# define BOOST_COMPUTE_CLANG_DIAG_OFF(x) BOOST_COMPUTE_CLANG_DIAG_PRAGMA(push) \
+ BOOST_COMPUTE_CLANG_DIAG_PRAGMA(ignored BOOST_COMPUTE_CLANG_DIAG_JOINSTR(-W,x))
+// For example: #pragma clang diagnostic ignored "-Wno-sign-compare"
+# define BOOST_COMPUTE_CLANG_DIAG_ON(x) BOOST_COMPUTE_CLANG_DIAG_PRAGMA(pop)
+// For example: #pragma clang diagnostic warning "-Wno-sign-compare"
+#else // Ensure these macros do nothing for other compilers.
+# define BOOST_COMPUTE_CLANG_DIAG_OFF(x)
+# define BOOST_COMPUTE_CLANG_DIAG_ON(x)
+# define BOOST_COMPUTE_CLANG_DIAG_PRAGMA(x)
+#endif
+
+// Macros for suppressing warnings for MSVC. Usage:
+//
+// BOOST_COMPUTE_BOOST_COMPUTE_MSVC_DIAG_OFF(4018); //sign-compare
+// if(a < b){
+// BOOST_COMPUTE_BOOST_COMPUTE_MSVC_DIAG_ON(4018);
+//
+#if defined(_MSC_VER)
+# define BOOST_COMPUTE_MSVC_DIAG_DO_PRAGMA(x) __pragma(x)
+# define BOOST_COMPUTE_MSVC_DIAG_PRAGMA(x) \
+ BOOST_COMPUTE_MSVC_DIAG_DO_PRAGMA(warning(x))
+# define BOOST_COMPUTE_MSVC_DIAG_OFF(x) BOOST_COMPUTE_MSVC_DIAG_PRAGMA(push) \
+ BOOST_COMPUTE_MSVC_DIAG_PRAGMA(disable: x)
+# define BOOST_COMPUTE_MSVC_DIAG_ON(x) BOOST_COMPUTE_MSVC_DIAG_PRAGMA(pop)
+#else // Ensure these macros do nothing for other compilers.
+# define BOOST_COMPUTE_MSVC_DIAG_OFF(x)
+# define BOOST_COMPUTE_MSVC_DIAG_ON(x)
+#endif
+
+// Macros for suppressing warnings for GCC, Clang and MSVC. Usage:
+//
+// BOOST_COMPUTE_DIAG_OFF(sign-compare, sign-compare, 4018);
+// if(a < b){
+// BOOST_COMPUTE_DIAG_ON(sign-compare, sign-compare, 4018);
+//
+#if defined(_MSC_VER) // MSVC
+# define BOOST_COMPUTE_DIAG_OFF(gcc, clang, msvc) BOOST_COMPUTE_MSVC_DIAG_OFF(msvc)
+# define BOOST_COMPUTE_DIAG_ON(gcc, clang, msvc) BOOST_COMPUTE_MSVC_DIAG_ON(msvc)
+#elif defined(__clang__) // Clang
+# define BOOST_COMPUTE_DIAG_OFF(gcc, clang, msvc) BOOST_COMPUTE_CLANG_DIAG_OFF(clang)
+# define BOOST_COMPUTE_DIAG_ON(gcc, clang, msvc) BOOST_COMPUTE_CLANG_DIAG_ON(clang)
+#elif defined(__GNUC__) // GCC/G++
+# define BOOST_COMPUTE_DIAG_OFF(gcc, clang, msvc) BOOST_COMPUTE_GCC_DIAG_OFF(gcc)
+# define BOOST_COMPUTE_DIAG_ON(gcc, clang, msvc) BOOST_COMPUTE_GCC_DIAG_ON(gcc)
+#else // Ensure these macros do nothing for other compilers.
+# define BOOST_COMPUTE_DIAG_OFF(gcc, clang, msvc)
+# define BOOST_COMPUTE_DIAG_ON(gcc, clang, msvc)
+#endif
+
+#define BOOST_COMPUTE_DISABLE_DEPRECATED_DECLARATIONS() \
+ BOOST_COMPUTE_DIAG_OFF(deprecated-declarations, deprecated-declarations, 4996)
+#define BOOST_COMPUTE_ENABLE_DEPRECATED_DECLARATIONS() \
+ BOOST_COMPUTE_DIAG_ON(deprecated-declarations, deprecated-declarations, 4996);
+
+
+#endif /* BOOST_COMPUTE_DETAIL_DIAGNOSTIC_HPP */
diff --git a/boost/compute/detail/duration.hpp b/boost/compute/detail/duration.hpp
new file mode 100644
index 0000000000..601f12d291
--- /dev/null
+++ b/boost/compute/detail/duration.hpp
@@ -0,0 +1,50 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_DURATION_HPP
+#define BOOST_COMPUTE_DETAIL_DURATION_HPP
+
+#include <boost/config.hpp>
+
+#ifndef BOOST_COMPUTE_NO_HDR_CHRONO
+#include <chrono>
+#endif
+
+#include <boost/chrono/duration.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+#ifndef BOOST_COMPUTE_NO_HDR_CHRONO
+template<class Rep, class Period>
+inline std::chrono::duration<Rep, Period>
+make_duration_from_nanoseconds(std::chrono::duration<Rep, Period>, size_t nanoseconds)
+{
+ return std::chrono::duration_cast<std::chrono::duration<Rep, Period> >(
+ std::chrono::nanoseconds(nanoseconds)
+ );
+}
+#endif // BOOST_COMPUTE_NO_HDR_CHRONO
+
+template<class Rep, class Period>
+inline boost::chrono::duration<Rep, Period>
+make_duration_from_nanoseconds(boost::chrono::duration<Rep, Period>, size_t nanoseconds)
+{
+ return boost::chrono::duration_cast<boost::chrono::duration<Rep, Period> >(
+ boost::chrono::nanoseconds(nanoseconds)
+ );
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DETAIL_DURATION_HPP
diff --git a/boost/compute/detail/get_object_info.hpp b/boost/compute/detail/get_object_info.hpp
new file mode 100644
index 0000000000..cdc20cbc13
--- /dev/null
+++ b/boost/compute/detail/get_object_info.hpp
@@ -0,0 +1,216 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_GET_OBJECT_INFO_HPP
+#define BOOST_COMPUTE_DETAIL_GET_OBJECT_INFO_HPP
+
+#include <string>
+#include <vector>
+
+#include <boost/preprocessor/seq/for_each.hpp>
+#include <boost/preprocessor/tuple/elem.hpp>
+
+#include <boost/throw_exception.hpp>
+
+#include <boost/compute/cl.hpp>
+#include <boost/compute/exception/opencl_error.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class Function, class Object, class AuxInfo>
+struct bound_info_function
+{
+ bound_info_function(Function function, Object object, AuxInfo aux_info)
+ : m_function(function),
+ m_object(object),
+ m_aux_info(aux_info)
+ {
+ }
+
+ template<class Info>
+ cl_int operator()(Info info, size_t size, void *value, size_t *size_ret) const
+ {
+ return m_function(m_object, m_aux_info, info, size, value, size_ret);
+ }
+
+ Function m_function;
+ Object m_object;
+ AuxInfo m_aux_info;
+};
+
+template<class Function, class Object>
+struct bound_info_function<Function, Object, void>
+{
+ bound_info_function(Function function, Object object)
+ : m_function(function),
+ m_object(object)
+ {
+ }
+
+ template<class Info>
+ cl_int operator()(Info info, size_t size, void *value, size_t *size_ret) const
+ {
+ return m_function(m_object, info, size, value, size_ret);
+ }
+
+ Function m_function;
+ Object m_object;
+};
+
+template<class Function, class Object>
+inline bound_info_function<Function, Object, void>
+bind_info_function(Function f, Object o)
+{
+ return bound_info_function<Function, Object, void>(f, o);
+}
+
+template<class Function, class Object, class AuxInfo>
+inline bound_info_function<Function, Object, AuxInfo>
+bind_info_function(Function f, Object o, AuxInfo j)
+{
+ return bound_info_function<Function, Object, AuxInfo>(f, o, j);
+}
+
+// default implementation
+template<class T>
+struct get_object_info_impl
+{
+ template<class Function, class Info>
+ T operator()(Function function, Info info) const
+ {
+ T value;
+
+ cl_int ret = function(info, sizeof(T), &value, 0);
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return value;
+ }
+};
+
+// specialization for bool
+template<>
+struct get_object_info_impl<bool>
+{
+ template<class Function, class Info>
+ bool operator()(Function function, Info info) const
+ {
+ cl_bool value;
+
+ cl_int ret = function(info, sizeof(cl_bool), &value, 0);
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return value == CL_TRUE;
+ }
+};
+
+// specialization for std::string
+template<>
+struct get_object_info_impl<std::string>
+{
+ template<class Function, class Info>
+ std::string operator()(Function function, Info info) const
+ {
+ size_t size = 0;
+
+ cl_int ret = function(info, 0, 0, &size);
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ if(size == 0){
+ return std::string();
+ }
+
+ std::string value(size - 1, 0);
+
+ ret = function(info, size, &value[0], 0);
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return value;
+ }
+};
+
+// specialization for std::vector<T>
+template<class T>
+struct get_object_info_impl<std::vector<T> >
+{
+ template<class Function, class Info>
+ std::vector<T> operator()(Function function, Info info) const
+ {
+ size_t size = 0;
+
+ cl_int ret = function(info, 0, 0, &size);
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ std::vector<T> vector(size / sizeof(T));
+ ret = function(info, size, &vector[0], 0);
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return vector;
+ }
+};
+
+// returns the value (of type T) from the given clGet*Info() function call.
+template<class T, class Function, class Object, class Info>
+inline T get_object_info(Function f, Object o, Info i)
+{
+ return get_object_info_impl<T>()(bind_info_function(f, o), i);
+}
+
+template<class T, class Function, class Object, class Info, class AuxInfo>
+inline T get_object_info(Function f, Object o, Info i, AuxInfo j)
+{
+ return get_object_info_impl<T>()(bind_info_function(f, o, j), i);
+}
+
+// returns the value type for the clGet*Info() call on Object with Enum.
+template<class Object, int Enum>
+struct get_object_info_type;
+
+// defines the object::get_info<Enum>() specialization
+#define BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATION(object_type, result_type, value) \
+ namespace detail { \
+ template<> struct get_object_info_type<object_type, value> { typedef result_type type; }; \
+ } \
+ template<> inline result_type object_type::get_info<value>() const \
+ { \
+ return get_info<result_type>(value); \
+ }
+
+// used by BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS()
+#define BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_IMPL(r, data, elem) \
+ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATION( \
+ data, BOOST_PP_TUPLE_ELEM(2, 0, elem), BOOST_PP_TUPLE_ELEM(2, 1, elem) \
+ )
+
+// defines the object::get_info<Enum>() specialization for each
+// (result_type, value) tuple in seq for object_type.
+#define BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(object_type, seq) \
+ BOOST_PP_SEQ_FOR_EACH( \
+ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_IMPL, object_type, seq \
+ )
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DETAIL_GET_OBJECT_INFO_HPP
diff --git a/boost/compute/detail/getenv.hpp b/boost/compute/detail/getenv.hpp
new file mode 100644
index 0000000000..ceb3605d5a
--- /dev/null
+++ b/boost/compute/detail/getenv.hpp
@@ -0,0 +1,36 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_GETENV_HPP
+#define BOOST_COMPUTE_DETAIL_GETENV_HPP
+
+#include <cstdlib>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+inline const char* getenv(const char *env_var)
+{
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4996)
+#endif
+ return std::getenv(env_var);
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DETAIL_GETENV_HPP
diff --git a/boost/compute/detail/global_static.hpp b/boost/compute/detail/global_static.hpp
new file mode 100644
index 0000000000..d8014e4252
--- /dev/null
+++ b/boost/compute/detail/global_static.hpp
@@ -0,0 +1,37 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_GLOBAL_STATIC_HPP
+#define BOOST_COMPUTE_DETAIL_GLOBAL_STATIC_HPP
+
+#include <boost/compute/config.hpp>
+
+#ifdef BOOST_COMPUTE_THREAD_SAFE
+# ifdef BOOST_COMPUTE_HAVE_THREAD_LOCAL
+ // use c++11 thread local storage
+# define BOOST_COMPUTE_DETAIL_GLOBAL_STATIC(type, name, ctor) \
+ thread_local type name ctor;
+# else
+ // use thread_specific_ptr from boost.thread
+# include <boost/thread/tss.hpp>
+# define BOOST_COMPUTE_DETAIL_GLOBAL_STATIC(type, name, ctor) \
+ static ::boost::thread_specific_ptr< type > BOOST_PP_CAT(name, _tls_ptr_); \
+ if(!BOOST_PP_CAT(name, _tls_ptr_).get()){ \
+ BOOST_PP_CAT(name, _tls_ptr_).reset(new type ctor); \
+ } \
+ static type &name = *BOOST_PP_CAT(name, _tls_ptr_);
+# endif
+#else
+ // no thread-safety, just use static
+# define BOOST_COMPUTE_DETAIL_GLOBAL_STATIC(type, name, ctor) \
+ static type name ctor;
+#endif
+
+#endif // BOOST_COMPUTE_DETAIL_GLOBAL_STATIC_HPP
diff --git a/boost/compute/detail/is_buffer_iterator.hpp b/boost/compute/detail/is_buffer_iterator.hpp
new file mode 100644
index 0000000000..c0caa050d6
--- /dev/null
+++ b/boost/compute/detail/is_buffer_iterator.hpp
@@ -0,0 +1,30 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_IS_BUFFER_ITERATOR_HPP
+#define BOOST_COMPUTE_DETAIL_IS_BUFFER_ITERATOR_HPP
+
+#include <boost/config.hpp>
+#include <boost/type_traits.hpp>
+#include <boost/utility/enable_if.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+// default = false
+template<class Iterator, class Enable = void>
+struct is_buffer_iterator : public boost::false_type {};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DETAIL_IS_BUFFER_ITERATOR_HPP
diff --git a/boost/compute/detail/is_contiguous_iterator.hpp b/boost/compute/detail/is_contiguous_iterator.hpp
new file mode 100644
index 0000000000..d0889b2f9e
--- /dev/null
+++ b/boost/compute/detail/is_contiguous_iterator.hpp
@@ -0,0 +1,118 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_IS_CONTIGUOUS_ITERATOR_HPP
+#define BOOST_COMPUTE_DETAIL_IS_CONTIGUOUS_ITERATOR_HPP
+
+#include <vector>
+#include <valarray>
+
+#include <boost/config.hpp>
+#include <boost/type_traits.hpp>
+#include <boost/utility/enable_if.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+// default = false
+template<class Iterator, class Enable = void>
+struct _is_contiguous_iterator : public boost::false_type {};
+
+// std::vector<T>::iterator = true
+template<class Iterator>
+struct _is_contiguous_iterator<
+ Iterator,
+ typename boost::enable_if<
+ typename boost::is_same<
+ Iterator,
+ typename std::vector<typename Iterator::value_type>::iterator
+ >::type
+ >::type
+> : public boost::true_type {};
+
+// std::vector<T>::const_iterator = true
+template<class Iterator>
+struct _is_contiguous_iterator<
+ Iterator,
+ typename boost::enable_if<
+ typename boost::is_same<
+ Iterator,
+ typename std::vector<typename Iterator::value_type>::const_iterator
+ >::type
+ >::type
+> : public boost::true_type {};
+
+// std::valarray<T>::iterator = true
+template<class Iterator>
+struct _is_contiguous_iterator<
+ Iterator,
+ typename boost::enable_if<
+ typename boost::is_same<
+ Iterator,
+ typename std::valarray<typename Iterator::value_type>::iterator
+ >::type
+ >::type
+> : public boost::true_type {};
+
+// std::valarray<T>::const_iterator = true
+template<class Iterator>
+struct _is_contiguous_iterator<
+ Iterator,
+ typename boost::enable_if<
+ typename boost::is_same<
+ Iterator,
+ typename std::valarray<typename Iterator::value_type>::const_iterator
+ >::type
+ >::type
+> : public boost::true_type {};
+
+// T* = true
+template<class Iterator>
+struct _is_contiguous_iterator<
+ Iterator,
+ typename boost::enable_if<
+ boost::is_pointer<Iterator>
+ >::type
+> : public boost::true_type {};
+
+// the is_contiguous_iterator meta-function returns true if Iterator points
+// to a range of contiguous values. examples of contiguous iterators are
+// std::vector<>::iterator and float*. examples of non-contiguous iterators
+// are std::set<>::iterator and std::insert_iterator<>.
+//
+// the implementation consists of two phases. the first checks that value_type
+// for the iterator is not void. this must be done as for many containers void
+// is not a valid value_type (ex. std::vector<void>::iterator is not valid).
+// after ensuring a non-void value_type, the _is_contiguous_iterator function
+// is invoked. it has specializations retuning true for all (known) contiguous
+// iterators types and a default value of false.
+template<class Iterator, class Enable = void>
+struct is_contiguous_iterator :
+ public _is_contiguous_iterator<
+ typename boost::remove_cv<Iterator>::type
+ > {};
+
+// value_type of void = false
+template<class Iterator>
+struct is_contiguous_iterator<
+ Iterator,
+ typename boost::enable_if<
+ typename boost::is_void<
+ typename Iterator::value_type
+ >::type
+ >::type
+> : public boost::false_type {};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DETAIL_IS_CONTIGUOUS_ITERATOR_HPP
diff --git a/boost/compute/detail/iterator_plus_distance.hpp b/boost/compute/detail/iterator_plus_distance.hpp
new file mode 100644
index 0000000000..26e95f16c0
--- /dev/null
+++ b/boost/compute/detail/iterator_plus_distance.hpp
@@ -0,0 +1,53 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_ITERATOR_PLUS_DISTANCE_HPP
+#define BOOST_COMPUTE_DETAIL_ITERATOR_PLUS_DISTANCE_HPP
+
+#include <iterator>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class Iterator, class Distance, class Tag>
+inline Iterator iterator_plus_distance(Iterator i, Distance n, Tag)
+{
+ while(n--){ i++; }
+
+ return i;
+}
+
+template<class Iterator, class Distance>
+inline Iterator iterator_plus_distance(Iterator i,
+ Distance n,
+ std::random_access_iterator_tag)
+{
+ typedef typename
+ std::iterator_traits<Iterator>::difference_type difference_type;
+
+ return i + static_cast<difference_type>(n);
+}
+
+// similar to std::advance() except returns the advanced iterator and
+// also works with iterators that don't define difference_type
+template<class Iterator, class Distance>
+inline Iterator iterator_plus_distance(Iterator i, Distance n)
+{
+ typedef typename std::iterator_traits<Iterator>::iterator_category tag;
+
+ return iterator_plus_distance(i, n, tag());
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DETAIL_ITERATOR_PLUS_DISTANCE_HPP
diff --git a/boost/compute/detail/iterator_range_size.hpp b/boost/compute/detail/iterator_range_size.hpp
new file mode 100644
index 0000000000..67a675f833
--- /dev/null
+++ b/boost/compute/detail/iterator_range_size.hpp
@@ -0,0 +1,44 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_ITERATOR_RANGE_SIZE_H
+#define BOOST_COMPUTE_DETAIL_ITERATOR_RANGE_SIZE_H
+
+#include <cstddef>
+#include <algorithm>
+#include <iterator>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+// This is a convenience function which returns the size of a range
+// bounded by two iterators. This function has two differences from
+// the std::distance() function: 1) the return type (size_t) is
+// unsigned, and 2) the return value is always positive.
+template<class Iterator>
+inline size_t iterator_range_size(Iterator first, Iterator last)
+{
+ typedef typename
+ std::iterator_traits<Iterator>::difference_type
+ difference_type;
+
+ difference_type difference = std::distance(first, last);
+
+ return static_cast<size_t>(
+ (std::max)(difference, static_cast<difference_type>(0))
+ );
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DETAIL_ITERATOR_RANGE_SIZE_H
diff --git a/boost/compute/detail/iterator_traits.hpp b/boost/compute/detail/iterator_traits.hpp
new file mode 100644
index 0000000000..45f0f683e6
--- /dev/null
+++ b/boost/compute/detail/iterator_traits.hpp
@@ -0,0 +1,35 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_ITERATOR_TRAITS_HPP
+#define BOOST_COMPUTE_DETAIL_ITERATOR_TRAITS_HPP
+
+#include <iterator>
+
+#include <boost/compute/detail/is_contiguous_iterator.hpp>
+#include <boost/compute/type_traits/is_device_iterator.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class Iterator>
+struct iterator_traits : public std::iterator_traits<Iterator>
+{
+ static const bool is_contiguous = is_contiguous_iterator<Iterator>::value;
+ static const bool is_on_device = is_device_iterator<Iterator>::value;
+ static const bool is_on_host = !is_on_device;
+};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ITERATOR_TRAITS_HPP
diff --git a/boost/compute/detail/literal.hpp b/boost/compute/detail/literal.hpp
new file mode 100644
index 0000000000..0d23b1d4d2
--- /dev/null
+++ b/boost/compute/detail/literal.hpp
@@ -0,0 +1,45 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_LITERAL_HPP
+#define BOOST_COMPUTE_DETAIL_LITERAL_HPP
+
+#include <iomanip>
+#include <limits>
+#include <sstream>
+
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/compute/types/fundamental.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class T>
+std::string make_literal(T x)
+{
+ std::stringstream s;
+ s << std::setprecision(std::numeric_limits<T>::digits10)
+ << std::scientific
+ << x;
+
+ if(boost::is_same<T, float>::value || boost::is_same<T, float_>::value){
+ s << "f";
+ }
+
+ return s.str();
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DETAIL_LITERAL_HPP
diff --git a/boost/compute/detail/lru_cache.hpp b/boost/compute/detail/lru_cache.hpp
new file mode 100644
index 0000000000..fe1a56f74b
--- /dev/null
+++ b/boost/compute/detail/lru_cache.hpp
@@ -0,0 +1,139 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_LRU_CACHE_HPP
+#define BOOST_COMPUTE_DETAIL_LRU_CACHE_HPP
+
+#include <map>
+#include <list>
+#include <utility>
+
+#include <boost/optional.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+// a cache which evicts the least recently used item when it is full
+template<class Key, class Value>
+class lru_cache
+{
+public:
+ typedef Key key_type;
+ typedef Value value_type;
+ typedef std::list<key_type> list_type;
+ typedef std::map<
+ key_type,
+ std::pair<value_type, typename list_type::iterator>
+ > map_type;
+
+ lru_cache(size_t capacity)
+ : m_capacity(capacity)
+ {
+ }
+
+ ~lru_cache()
+ {
+ }
+
+ size_t size() const
+ {
+ return m_map.size();
+ }
+
+ size_t capacity() const
+ {
+ return m_capacity;
+ }
+
+ bool empty() const
+ {
+ return m_map.empty();
+ }
+
+ bool contains(const key_type &key)
+ {
+ return m_map.find(key) != m_map.end();
+ }
+
+ void insert(const key_type &key, const value_type &value)
+ {
+ typename map_type::iterator i = m_map.find(key);
+ if(i == m_map.end()){
+ // insert item into the cache, but first check if it is full
+ if(size() >= m_capacity){
+ // cache is full, evict the least recently used item
+ evict();
+ }
+
+ // insert the new item
+ m_list.push_front(key);
+ m_map[key] = std::make_pair(value, m_list.begin());
+ }
+ }
+
+ boost::optional<value_type> get(const key_type &key)
+ {
+ // lookup value in the cache
+ typename map_type::iterator i = m_map.find(key);
+ if(i == m_map.end()){
+ // value not in cache
+ return boost::none;
+ }
+
+ // return the value, but first update its place in the most
+ // recently used list
+ typename list_type::iterator j = i->second.second;
+ if(j != m_list.begin()){
+ // move item to the front of the most recently used list
+ m_list.erase(j);
+ m_list.push_front(key);
+
+ // update iterator in map
+ j = m_list.begin();
+ const value_type &value = i->second.first;
+ m_map[key] = std::make_pair(value, j);
+
+ // return the value
+ return value;
+ }
+ else {
+ // the item is already at the front of the most recently
+ // used list so just return it
+ return i->second.first;
+ }
+ }
+
+ void clear()
+ {
+ m_map.clear();
+ m_list.clear();
+ }
+
+private:
+ void evict()
+ {
+ // evict item from the end of most recently used list
+ typename list_type::iterator i = --m_list.end();
+ m_map.erase(*i);
+ m_list.erase(i);
+ }
+
+private:
+ map_type m_map;
+ list_type m_list;
+ size_t m_capacity;
+};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DETAIL_LRU_CACHE_HPP
diff --git a/boost/compute/detail/meta_kernel.hpp b/boost/compute/detail/meta_kernel.hpp
new file mode 100644
index 0000000000..7be778b025
--- /dev/null
+++ b/boost/compute/detail/meta_kernel.hpp
@@ -0,0 +1,1054 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_META_KERNEL_HPP
+#define BOOST_COMPUTE_DETAIL_META_KERNEL_HPP
+
+#include <set>
+#include <string>
+#include <vector>
+#include <iomanip>
+#include <sstream>
+#include <utility>
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/type_traits.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/algorithm/string/find.hpp>
+#include <boost/preprocessor/repetition.hpp>
+
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/closure.hpp>
+#include <boost/compute/function.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/type_traits.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/image/image2d.hpp>
+#include <boost/compute/image/image_sampler.hpp>
+#include <boost/compute/memory_object.hpp>
+#include <boost/compute/detail/device_ptr.hpp>
+#include <boost/compute/detail/sha1.hpp>
+#include <boost/compute/utility/program_cache.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class T>
+class meta_kernel_variable
+{
+public:
+ typedef T result_type;
+
+ meta_kernel_variable(const std::string &name)
+ : m_name(name)
+ {
+ }
+
+ meta_kernel_variable(const meta_kernel_variable &other)
+ : m_name(other.m_name)
+ {
+ }
+
+ meta_kernel_variable& operator=(const meta_kernel_variable &other)
+ {
+ if(this != &other){
+ m_name = other.m_name;
+ }
+
+ return *this;
+ }
+
+ ~meta_kernel_variable()
+ {
+ }
+
+ std::string name() const
+ {
+ return m_name;
+ }
+
+private:
+ std::string m_name;
+};
+
+template<class T>
+class meta_kernel_literal
+{
+public:
+ typedef T result_type;
+
+ meta_kernel_literal(const T &value)
+ : m_value(value)
+ {
+ }
+
+ meta_kernel_literal(const meta_kernel_literal &other)
+ : m_value(other.m_value)
+ {
+ }
+
+ meta_kernel_literal& operator=(const meta_kernel_literal &other)
+ {
+ if(this != &other){
+ m_value = other.m_value;
+ }
+
+ return *this;
+ }
+
+ ~meta_kernel_literal()
+ {
+ }
+
+ const T& value() const
+ {
+ return m_value;
+ }
+
+private:
+ T m_value;
+};
+
+struct meta_kernel_stored_arg
+{
+ meta_kernel_stored_arg()
+ : m_size(0),
+ m_value(0)
+ {
+ }
+
+ meta_kernel_stored_arg(const meta_kernel_stored_arg &other)
+ : m_size(0),
+ m_value(0)
+ {
+ set_value(other.m_size, other.m_value);
+ }
+
+ meta_kernel_stored_arg& operator=(const meta_kernel_stored_arg &other)
+ {
+ if(this != &other){
+ set_value(other.m_size, other.m_value);
+ }
+
+ return *this;
+ }
+
+ template<class T>
+ meta_kernel_stored_arg(const T &value)
+ : m_size(0),
+ m_value(0)
+ {
+ set_value(value);
+ }
+
+ ~meta_kernel_stored_arg()
+ {
+ if(m_value){
+ std::free(m_value);
+ }
+ }
+
+ void set_value(size_t size, const void *value)
+ {
+ if(m_value){
+ std::free(m_value);
+ }
+
+ m_size = size;
+
+ if(value){
+ m_value = std::malloc(size);
+ std::memcpy(m_value, value, size);
+ }
+ else {
+ m_value = 0;
+ }
+ }
+
+ template<class T>
+ void set_value(const T &value)
+ {
+ set_value(sizeof(T), boost::addressof(value));
+ }
+
+ size_t m_size;
+ void *m_value;
+};
+
+struct meta_kernel_buffer_info
+{
+ meta_kernel_buffer_info(const buffer &buffer,
+ const std::string &id,
+ memory_object::address_space addr_space,
+ size_t i)
+ : m_mem(buffer.get()),
+ identifier(id),
+ address_space(addr_space),
+ index(i)
+ {
+ }
+
+ cl_mem m_mem;
+ std::string identifier;
+ memory_object::address_space address_space;
+ size_t index;
+};
+
+class meta_kernel;
+
+template<class Type>
+struct inject_type_impl
+{
+ void operator()(meta_kernel &)
+ {
+ // default implementation does nothing
+ }
+};
+
+#define BOOST_COMPUTE_META_KERNEL_DECLARE_SCALAR_TYPE_STREAM_OPERATOR(type) \
+ meta_kernel& operator<<(const type &x) \
+ { \
+ m_source << x; \
+ return *this; \
+ }
+
+#define BOOST_COMPUTE_META_KERNEL_DECLARE_VECTOR_TYPE_STREAM_OPERATOR(type) \
+ meta_kernel& operator<<(const type &x) \
+ { \
+ m_source << "(" << type_name<type>() << ")"; \
+ m_source << "("; \
+ for(size_t i = 0; i < vector_size<type>::value; i++){ \
+ *this << lit(x[i]); \
+ \
+ if(i != vector_size<type>::value - 1){ \
+ m_source << ","; \
+ } \
+ } \
+ m_source << ")"; \
+ return *this; \
+ }
+
+#define BOOST_COMPUTE_META_KERNEL_DECLARE_TYPE_STREAM_OPERATORS(type) \
+ BOOST_COMPUTE_META_KERNEL_DECLARE_SCALAR_TYPE_STREAM_OPERATOR(BOOST_PP_CAT(type, _)) \
+ BOOST_COMPUTE_META_KERNEL_DECLARE_VECTOR_TYPE_STREAM_OPERATOR(BOOST_PP_CAT(BOOST_PP_CAT(type, 2), _)) \
+ BOOST_COMPUTE_META_KERNEL_DECLARE_VECTOR_TYPE_STREAM_OPERATOR(BOOST_PP_CAT(BOOST_PP_CAT(type, 4), _)) \
+ BOOST_COMPUTE_META_KERNEL_DECLARE_VECTOR_TYPE_STREAM_OPERATOR(BOOST_PP_CAT(BOOST_PP_CAT(type, 8), _)) \
+ BOOST_COMPUTE_META_KERNEL_DECLARE_VECTOR_TYPE_STREAM_OPERATOR(BOOST_PP_CAT(BOOST_PP_CAT(type, 16), _))
+
+class meta_kernel
+{
+public:
+ template<class T>
+ class argument
+ {
+ public:
+ argument(const std::string &name, size_t index)
+ : m_name(name),
+ m_index(index)
+ {
+ }
+
+ const std::string &name() const
+ {
+ return m_name;
+ }
+
+ size_t index() const
+ {
+ return m_index;
+ }
+
+ private:
+ std::string m_name;
+ size_t m_index;
+ };
+
+ explicit meta_kernel(const std::string &name)
+ : m_name(name)
+ {
+ }
+
+ meta_kernel(const meta_kernel &other)
+ {
+ m_source.str(other.m_source.str());
+ }
+
+ meta_kernel& operator=(const meta_kernel &other)
+ {
+ if(this != &other){
+ m_source.str(other.m_source.str());
+ }
+
+ return *this;
+ }
+
+ ~meta_kernel()
+ {
+ }
+
+ std::string name() const
+ {
+ return m_name;
+ }
+
+ std::string source() const
+ {
+ std::stringstream stream;
+
+ // add pragmas
+ if(!m_pragmas.empty()){
+ stream << m_pragmas << "\n";
+ }
+
+ // add macros
+ stream << "#define boost_pair_type(t1, t2) _pair_ ## t1 ## _ ## t2 ## _t\n";
+ stream << "#define boost_pair_get(x, n) (n == 0 ? x.first ## x.second)\n";
+ stream << "#define boost_make_pair(t1, x, t2, y) (boost_pair_type(t1, t2)) { x, y }\n";
+ stream << "#define boost_tuple_get(x, n) (x.v ## n)\n";
+
+ // add type declaration source
+ stream << m_type_declaration_source.str() << "\n";
+
+ // add external function source
+ stream << m_external_function_source.str() << "\n";
+
+ // add kernel source
+ stream << "__kernel void " << m_name
+ << "(" << boost::join(m_args, ", ") << ")\n"
+ << "{\n" << m_source.str() << "\n}\n";
+
+ return stream.str();
+ }
+
+ kernel compile(const context &context, const std::string &options = std::string())
+ {
+ // generate the program source
+ std::string source = this->source();
+
+ // generate cache key
+ std::string cache_key = "__boost_meta_kernel_" +
+ static_cast<std::string>(detail::sha1(source));
+
+ // load program cache
+ boost::shared_ptr<program_cache> cache =
+ program_cache::get_global_cache(context);
+
+ // load (or build) program from cache
+ ::boost::compute::program program =
+ cache->get_or_build(cache_key, options, source, context);
+
+ // create kernel
+ ::boost::compute::kernel kernel = program.create_kernel(name());
+
+ // bind stored args
+ for(size_t i = 0; i < m_stored_args.size(); i++){
+ const detail::meta_kernel_stored_arg &arg = m_stored_args[i];
+
+ if(arg.m_size != 0){
+ kernel.set_arg(i, arg.m_size, arg.m_value);
+ }
+ }
+
+ // bind buffer args
+ for(size_t i = 0; i < m_stored_buffers.size(); i++){
+ const detail::meta_kernel_buffer_info &bi = m_stored_buffers[i];
+
+ kernel.set_arg(bi.index, bi.m_mem);
+ }
+
+ return kernel;
+ }
+
+ template<class T>
+ size_t add_arg(const std::string &name)
+ {
+ std::stringstream stream;
+ stream << type<T>() << " " << name;
+
+ // add argument to list
+ m_args.push_back(stream.str());
+
+ // return index
+ return m_args.size() - 1;
+ }
+
+ template<class T>
+ size_t add_arg(memory_object::address_space address_space,
+ const std::string &name)
+ {
+ return add_arg_with_qualifiers<T>(address_space_prefix(address_space), name);
+ }
+
+ template<class T>
+ void set_arg(size_t index, const T &value)
+ {
+ if(index >= m_stored_args.size()){
+ m_stored_args.resize(index + 1);
+ }
+
+ m_stored_args[index] = detail::meta_kernel_stored_arg(value);
+ }
+
+ void set_arg(size_t index, const memory_object &mem)
+ {
+ set_arg<cl_mem>(index, mem.get());
+ }
+
+ void set_arg(size_t index, const image_sampler &sampler)
+ {
+ set_arg<cl_sampler>(index, cl_sampler(sampler));
+ }
+
+ template<class T>
+ size_t add_set_arg(const std::string &name, const T &value)
+ {
+ size_t index = add_arg<T>(name);
+ set_arg<T>(index, value);
+ return index;
+ }
+
+ void add_extension_pragma(const std::string &extension,
+ const std::string &value = "enable")
+ {
+ m_pragmas += "#pragma OPENCL EXTENSION " + extension + " : " + value + "\n";
+ }
+
+ void add_extension_pragma(const std::string &extension,
+ const std::string &value) const
+ {
+ return const_cast<meta_kernel *>(this)->add_extension_pragma(extension, value);
+ }
+
+ template<class T>
+ std::string type() const
+ {
+ std::stringstream stream;
+
+ // const qualifier
+ if(boost::is_const<T>::value){
+ stream << "const ";
+ }
+
+ // volatile qualifier
+ if(boost::is_volatile<T>::value){
+ stream << "volatile ";
+ }
+
+ // type
+ typedef
+ typename boost::remove_cv<
+ typename boost::remove_pointer<T>::type
+ >::type Type;
+ stream << type_name<Type>();
+
+ // pointer
+ if(boost::is_pointer<T>::value){
+ stream << "*";
+ }
+
+ // inject type pragmas and/or definitions
+ inject_type<Type>();
+
+ return stream.str();
+ }
+
+ template<class T>
+ std::string decl(const std::string &name) const
+ {
+ return type<T>() + " " + name;
+ }
+
+ template<class T, class Expr>
+ std::string decl(const std::string &name, const Expr &init) const
+ {
+ meta_kernel tmp((std::string()));
+ tmp << tmp.decl<T>(name) << " = " << init;
+ return tmp.m_source.str();
+ }
+
+ template<class T>
+ detail::meta_kernel_variable<T> var(const std::string &name) const
+ {
+ type<T>();
+
+ return make_var<T>(name);
+ }
+
+ template<class T>
+ detail::meta_kernel_literal<T> lit(const T &value) const
+ {
+ type<T>();
+
+ return detail::meta_kernel_literal<T>(value);
+ }
+
+ template<class T>
+ detail::meta_kernel_variable<T> expr(const std::string &expr) const
+ {
+ type<T>();
+
+ return detail::meta_kernel_variable<T>(expr);
+ }
+
+ // define stream operators for scalar and vector types
+ BOOST_COMPUTE_META_KERNEL_DECLARE_TYPE_STREAM_OPERATORS(char)
+ BOOST_COMPUTE_META_KERNEL_DECLARE_TYPE_STREAM_OPERATORS(uchar)
+ BOOST_COMPUTE_META_KERNEL_DECLARE_TYPE_STREAM_OPERATORS(short)
+ BOOST_COMPUTE_META_KERNEL_DECLARE_TYPE_STREAM_OPERATORS(ushort)
+ BOOST_COMPUTE_META_KERNEL_DECLARE_TYPE_STREAM_OPERATORS(int)
+ BOOST_COMPUTE_META_KERNEL_DECLARE_TYPE_STREAM_OPERATORS(uint)
+ BOOST_COMPUTE_META_KERNEL_DECLARE_TYPE_STREAM_OPERATORS(long)
+ BOOST_COMPUTE_META_KERNEL_DECLARE_TYPE_STREAM_OPERATORS(ulong)
+ BOOST_COMPUTE_META_KERNEL_DECLARE_TYPE_STREAM_OPERATORS(double)
+
+ // define stream operators for float scalar and vector types
+ meta_kernel& operator<<(const float &x)
+ {
+ m_source << std::showpoint << x << 'f';
+ return *this;
+ }
+
+ BOOST_COMPUTE_META_KERNEL_DECLARE_VECTOR_TYPE_STREAM_OPERATOR(float2_)
+ BOOST_COMPUTE_META_KERNEL_DECLARE_VECTOR_TYPE_STREAM_OPERATOR(float4_)
+ BOOST_COMPUTE_META_KERNEL_DECLARE_VECTOR_TYPE_STREAM_OPERATOR(float8_)
+ BOOST_COMPUTE_META_KERNEL_DECLARE_VECTOR_TYPE_STREAM_OPERATOR(float16_)
+
+ // define stream operators for variable types
+ template<class T>
+ meta_kernel& operator<<(const meta_kernel_variable<T> &variable)
+ {
+ return *this << variable.name();
+ }
+
+ // define stream operators for literal types
+ template<class T>
+ meta_kernel& operator<<(const meta_kernel_literal<T> &literal)
+ {
+ return *this << literal.value();
+ }
+
+ meta_kernel& operator<<(const meta_kernel_literal<bool> &literal)
+ {
+ return *this << (literal.value() ? "true" : "false");
+ }
+
+ meta_kernel& operator<<(const meta_kernel_literal<char> &literal)
+ {
+ const char c = literal.value();
+
+ switch(c){
+ // control characters
+ case '\0':
+ return *this << "'\\0'";
+ case '\a':
+ return *this << "'\\a'";
+ case '\b':
+ return *this << "'\\b'";
+ case '\t':
+ return *this << "'\\t'";
+ case '\n':
+ return *this << "'\\n'";
+ case '\v':
+ return *this << "'\\v'";
+ case '\f':
+ return *this << "'\\f'";
+ case '\r':
+ return *this << "'\\r'";
+
+ // characters which need escaping
+ case '\"':
+ case '\'':
+ case '\?':
+ case '\\':
+ return *this << "'\\" << c << "'";
+
+ // all other characters
+ default:
+ return *this << "'" << c << "'";
+ }
+ }
+
+ meta_kernel& operator<<(const meta_kernel_literal<signed char> &literal)
+ {
+ return *this << lit<char>(literal.value());
+ }
+
+ meta_kernel& operator<<(const meta_kernel_literal<unsigned char> &literal)
+ {
+ return *this << uint_(literal.value());
+ }
+
+ // define stream operators for strings
+ meta_kernel& operator<<(char ch)
+ {
+ m_source << ch;
+ return *this;
+ }
+
+ meta_kernel& operator<<(const char *string)
+ {
+ m_source << string;
+ return *this;
+ }
+
+ meta_kernel& operator<<(const std::string &string)
+ {
+ m_source << string;
+ return *this;
+ }
+
+ template<class T>
+ static detail::meta_kernel_variable<T> make_var(const std::string &name)
+ {
+ return detail::meta_kernel_variable<T>(name);
+ }
+
+ template<class T>
+ static detail::meta_kernel_literal<T> make_lit(const T &value)
+ {
+ return detail::meta_kernel_literal<T>(value);
+ }
+
+ template<class T>
+ static detail::meta_kernel_variable<T> make_expr(const std::string &expr)
+ {
+ return detail::meta_kernel_variable<T>(expr);
+ }
+
+ event exec(command_queue &queue)
+ {
+ return exec_1d(queue, 0, 1);
+ }
+
+ event exec_1d(command_queue &queue,
+ size_t global_work_offset,
+ size_t global_work_size)
+ {
+ const context &context = queue.get_context();
+
+ ::boost::compute::kernel kernel = compile(context);
+
+ return queue.enqueue_1d_range_kernel(
+ kernel,
+ global_work_offset,
+ global_work_size,
+ 0
+ );
+ }
+
+ event exec_1d(command_queue &queue,
+ size_t global_work_offset,
+ size_t global_work_size,
+ size_t local_work_size)
+ {
+ const context &context = queue.get_context();
+
+ ::boost::compute::kernel kernel = compile(context);
+
+ return queue.enqueue_1d_range_kernel(
+ kernel,
+ global_work_offset,
+ global_work_size,
+ local_work_size
+ );
+ }
+
+ template<class T>
+ std::string get_buffer_identifier(const buffer &buffer,
+ const memory_object::address_space address_space =
+ memory_object::global_memory)
+ {
+ // check if we've already seen buffer
+ for(size_t i = 0; i < m_stored_buffers.size(); i++){
+ const detail::meta_kernel_buffer_info &bi = m_stored_buffers[i];
+
+ if(bi.m_mem == buffer.get() &&
+ bi.address_space == address_space){
+ return bi.identifier;
+ }
+ }
+
+ // create a new binding
+ std::string identifier =
+ "_buf" + lexical_cast<std::string>(m_stored_buffers.size());
+ size_t index = add_arg<T *>(address_space, identifier);
+
+ // store new buffer info
+ m_stored_buffers.push_back(
+ detail::meta_kernel_buffer_info(buffer, identifier, address_space, index));
+
+ return identifier;
+ }
+
+ std::string get_image_identifier(const char *qualifiers, const image2d &image)
+ {
+ size_t index = add_arg_with_qualifiers<image2d>(qualifiers, "image");
+
+ set_arg(index, image);
+
+ return "image";
+ }
+
+ std::string get_sampler_identifier(bool normalized_coords,
+ cl_addressing_mode addressing_mode,
+ cl_filter_mode filter_mode)
+ {
+ (void) normalized_coords;
+ (void) addressing_mode;
+ (void) filter_mode;
+
+ m_pragmas += "const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE |\n"
+ " CLK_ADDRESS_NONE |\n"
+ " CLK_FILTER_NEAREST;\n";
+
+ return "sampler";
+ }
+
+ template<class Expr>
+ static std::string expr_to_string(const Expr &expr)
+ {
+ meta_kernel tmp((std::string()));
+ tmp << expr;
+ return tmp.m_source.str();
+ }
+
+ template<class Predicate>
+ detail::invoked_function<bool, boost::tuple<Predicate> > if_(Predicate pred) const
+ {
+ return detail::invoked_function<bool, boost::tuple<Predicate> >(
+ "if", std::string(), boost::make_tuple(pred)
+ );
+ }
+
+ template<class Predicate>
+ detail::invoked_function<bool, boost::tuple<Predicate> > else_if_(Predicate pred) const
+ {
+ return detail::invoked_function<bool, boost::tuple<Predicate> >(
+ "else if", std::string(), boost::make_tuple(pred)
+ );
+ }
+
+ detail::meta_kernel_variable<cl_uint> get_global_id(size_t dim) const
+ {
+ return expr<cl_uint>("get_global_id(" + lexical_cast<std::string>(dim) + ")");
+ }
+
+ void add_function(const std::string &name, const std::string &source)
+ {
+ if(m_external_function_names.count(name)){
+ return;
+ }
+
+ m_external_function_names.insert(name);
+ m_external_function_source << source << "\n";
+ }
+
+ void add_function(const std::string &name,
+ const std::string &source,
+ const std::map<std::string, std::string> &definitions)
+ {
+ typedef std::map<std::string, std::string>::const_iterator iter;
+
+ std::stringstream s;
+
+ // add #define's
+ for(iter i = definitions.begin(); i != definitions.end(); i++){
+ s << "#define " << i->first;
+ if(!i->second.empty()){
+ s << " " << i->second;
+ }
+ s << "\n";
+ }
+
+ s << source << "\n";
+
+ // add #undef's
+ for(iter i = definitions.begin(); i != definitions.end(); i++){
+ s << "#undef " << i->first << "\n";
+ }
+
+ add_function(name, s.str());
+ }
+
+ template<class Type>
+ void add_type_declaration(const std::string &declaration)
+ {
+ const char *name = type_name<Type>();
+
+ // check if the type has already been declared
+ std::string source = m_type_declaration_source.str();
+ if(source.find(name) != std::string::npos){
+ return;
+ }
+
+ m_type_declaration_source << declaration;
+ }
+
+ template<class Type>
+ void inject_type() const
+ {
+ inject_type_impl<Type>()(const_cast<meta_kernel &>(*this));
+ }
+
+ // the insert_function_call() method inserts a call to a function with
+ // the given name tuple of argument values.
+ template<class ArgTuple>
+ void insert_function_call(const std::string &name, const ArgTuple &args)
+ {
+ *this << name << '(';
+ insert_function_call_args(args);
+ *this << ')';
+ }
+
+ // the insert_function_call_args() method takes a tuple of argument values
+ // and inserts them into the source string with a comma in-between each.
+ // this is useful for creating function calls given a tuple of values.
+ void insert_function_call_args(const boost::tuple<>&)
+ {
+ }
+
+ #define BOOST_COMPUTE_META_KERNEL_INSERT_FUNCTION_ARG_TYPE(z, n, unused) \
+ inject_type<BOOST_PP_CAT(T, n)>();
+
+ #define BOOST_COMPUTE_META_KERNEL_STREAM_FUNCTION_ARG(z, n, unused) \
+ << boost::get<BOOST_PP_DEC(n)>(args) << ", "
+
+ #define BOOST_COMPUTE_META_KERNEL_INSERT_FUNCTION_ARGS(z, n, unused) \
+ template<BOOST_PP_ENUM_PARAMS(n, class T)> \
+ void insert_function_call_args( \
+ const boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> &args \
+ ) \
+ { \
+ BOOST_PP_REPEAT_FROM_TO( \
+ 0, n, BOOST_COMPUTE_META_KERNEL_INSERT_FUNCTION_ARG_TYPE, ~ \
+ ) \
+ *this \
+ BOOST_PP_REPEAT_FROM_TO( \
+ 1, n, BOOST_COMPUTE_META_KERNEL_STREAM_FUNCTION_ARG, ~ \
+ ) \
+ << boost::get<BOOST_PP_DEC(n)>(args); \
+ }
+
+ BOOST_PP_REPEAT_FROM_TO(
+ 1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_META_KERNEL_INSERT_FUNCTION_ARGS, ~
+ )
+
+ #undef BOOST_COMPUTE_META_KERNEL_INSERT_FUNCTION_ARG_TYPE
+ #undef BOOST_COMPUTE_META_KERNEL_STREAM_FUNCTION_ARG
+ #undef BOOST_COMPUTE_META_KERNEL_INSERT_FUNCTION_ARGS
+
+ static const char* address_space_prefix(const memory_object::address_space value)
+ {
+ switch(value){
+ case memory_object::global_memory: return "__global";
+ case memory_object::local_memory: return "__local";
+ case memory_object::private_memory: return "__private";
+ case memory_object::constant_memory: return "__constant";
+ };
+
+ return 0; // unreachable
+ }
+
+private:
+ template<class T>
+ size_t add_arg_with_qualifiers(const char *qualifiers, const std::string &name)
+ {
+ size_t index = add_arg<T>(name);
+
+ // update argument type declaration with qualifiers
+ std::stringstream s;
+ s << qualifiers << " " << m_args[index];
+ m_args[index] = s.str();
+
+ return index;
+ }
+
+private:
+ std::string m_name;
+ std::stringstream m_source;
+ std::stringstream m_external_function_source;
+ std::stringstream m_type_declaration_source;
+ std::set<std::string> m_external_function_names;
+ std::vector<std::string> m_args;
+ std::string m_pragmas;
+ std::vector<detail::meta_kernel_stored_arg> m_stored_args;
+ std::vector<detail::meta_kernel_buffer_info> m_stored_buffers;
+};
+
+template<class ResultType, class ArgTuple>
+inline meta_kernel&
+operator<<(meta_kernel &kernel, const invoked_function<ResultType, ArgTuple> &expr)
+{
+ if(!expr.source().empty()){
+ kernel.add_function(expr.name(), expr.source(), expr.definitions());
+ }
+
+ kernel.insert_function_call(expr.name(), expr.args());
+
+ return kernel;
+}
+
+template<class ResultType, class ArgTuple, class CaptureTuple>
+inline meta_kernel&
+operator<<(meta_kernel &kernel,
+ const invoked_closure<ResultType, ArgTuple, CaptureTuple> &expr)
+{
+ if(!expr.source().empty()){
+ kernel.add_function(expr.name(), expr.source(), expr.definitions());
+ }
+
+ kernel << expr.name() << '(';
+ kernel.insert_function_call_args(expr.args());
+ kernel << ", ";
+ kernel.insert_function_call_args(expr.capture());
+ kernel << ')';
+
+ return kernel;
+}
+
+template<class Arg1, class Arg2, class Result>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const invoked_binary_operator<Arg1,
+ Arg2,
+ Result> &expr)
+{
+ return kernel << "((" << expr.arg1() << ")"
+ << expr.op()
+ << "(" << expr.arg2() << "))";
+}
+
+template<class T, class IndexExpr>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const detail::device_ptr_index_expr<T, IndexExpr> &expr)
+{
+ if(expr.m_index == 0){
+ return kernel <<
+ kernel.get_buffer_identifier<T>(expr.m_buffer) <<
+ '[' << expr.m_expr << ']';
+ }
+ else {
+ return kernel <<
+ kernel.get_buffer_identifier<T>(expr.m_buffer) <<
+ '[' << expr.m_index << "+(" << expr.m_expr << ")]";
+ }
+}
+
+template<class T1, class T2, class IndexExpr>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const detail::device_ptr_index_expr<std::pair<T1, T2>, IndexExpr> &expr)
+{
+ typedef std::pair<T1, T2> T;
+
+ if(expr.m_index == 0){
+ return kernel <<
+ kernel.get_buffer_identifier<T>(expr.m_buffer) <<
+ '[' << expr.m_expr << ']';
+ }
+ else {
+ return kernel <<
+ kernel.get_buffer_identifier<T>(expr.m_buffer) <<
+ '[' << expr.m_index << "+(" << expr.m_expr << ")]";
+ }
+}
+
+template<class Predicate, class Arg>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const invoked_unary_negate_function<Predicate,
+ Arg> &expr)
+{
+ return kernel << "!(" << expr.pred()(expr.expr()) << ')';
+}
+
+template<class Predicate, class Arg1, class Arg2>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const invoked_binary_negate_function<Predicate,
+ Arg1,
+ Arg2> &expr)
+{
+ return kernel << "!(" << expr.pred()(expr.expr1(), expr.expr2()) << ')';
+}
+
+// get<N>() for vector types
+template<size_t N, class Arg, class T>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const invoked_get<N, Arg, T> &expr)
+{
+ BOOST_STATIC_ASSERT(N < 16);
+
+ if(N < 10){
+ return kernel << expr.m_arg << ".s" << uint_(N);
+ }
+ else if(N < 16){
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4307)
+#endif
+ return kernel << expr.m_arg << ".s" << char('a' + (N - 10));
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+ }
+
+ return kernel;
+}
+
+template<class T, class Arg>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const invoked_field<T, Arg> &expr)
+{
+ return kernel << expr.m_arg << "." << expr.m_field;
+}
+
+template<class T, class Arg>
+inline meta_kernel& operator<<(meta_kernel &k,
+ const invoked_as<T, Arg> &expr)
+{
+ return k << "as_" << type_name<T>() << "(" << expr.m_arg << ")";
+}
+
+template<class T, class Arg>
+inline meta_kernel& operator<<(meta_kernel &k,
+ const invoked_convert<T, Arg> &expr)
+{
+ return k << "convert_" << type_name<T>() << "(" << expr.m_arg << ")";
+}
+
+template<class T, class Arg>
+inline meta_kernel& operator<<(meta_kernel &k,
+ const invoked_identity<T, Arg> &expr)
+{
+ return k << expr.m_arg;
+}
+
+template<>
+struct inject_type_impl<double_>
+{
+ void operator()(meta_kernel &kernel)
+ {
+ kernel.add_extension_pragma("cl_khr_fp64", "enable");
+ }
+};
+
+template<class Scalar, size_t N>
+struct inject_type_impl<vector_type<Scalar, N> >
+{
+ void operator()(meta_kernel &kernel)
+ {
+ kernel.inject_type<Scalar>();
+ }
+};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DETAIL_META_KERNEL_HPP
diff --git a/boost/compute/detail/mpl_vector_to_tuple.hpp b/boost/compute/detail/mpl_vector_to_tuple.hpp
new file mode 100644
index 0000000000..292a6e36e1
--- /dev/null
+++ b/boost/compute/detail/mpl_vector_to_tuple.hpp
@@ -0,0 +1,65 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_MPL_VECTOR_TO_TUPLE_HPP
+#define BOOST_COMPUTE_DETAIL_MPL_VECTOR_TO_TUPLE_HPP
+
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/fusion/include/mpl.hpp>
+#include <boost/fusion/adapted/boost_tuple.hpp>
+#include <boost/preprocessor/repetition.hpp>
+
+#include <boost/compute/config.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+namespace mpl = boost::mpl;
+
+template<class Vector, size_t N>
+struct mpl_vector_to_tuple_impl;
+
+#define BOOST_COMPUTE_PRINT_ELEM(z, n, unused) \
+ typename mpl::at_c<Vector, n>::type
+
+#define BOOST_COMPUTE_VEC2TUP(z, n, unused) \
+template<class Vector> \
+struct mpl_vector_to_tuple_impl<Vector, n> \
+{ \
+ typedef typename \
+ boost::tuple< \
+ BOOST_PP_ENUM(n, BOOST_COMPUTE_PRINT_ELEM, ~) \
+ > type; \
+};
+
+BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_VEC2TUP, ~)
+
+#undef BOOST_COMPUTE_VEC2TUP
+#undef BOOST_COMPUTE_PRINT_ELEM
+
+// meta-function which converts a mpl::vector to a boost::tuple
+template<class Vector>
+struct mpl_vector_to_tuple
+{
+ typedef typename
+ mpl_vector_to_tuple_impl<
+ Vector,
+ mpl::size<Vector>::value
+ >::type type;
+};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DETAIL_MPL_VECTOR_TO_TUPLE_HPP
diff --git a/boost/compute/detail/nvidia_compute_capability.hpp b/boost/compute/detail/nvidia_compute_capability.hpp
new file mode 100644
index 0000000000..3f859562bd
--- /dev/null
+++ b/boost/compute/detail/nvidia_compute_capability.hpp
@@ -0,0 +1,60 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_NVIDIA_COMPUTE_CAPABILITY_HPP
+#define BOOST_COMPUTE_DETAIL_NVIDIA_COMPUTE_CAPABILITY_HPP
+
+#include <boost/compute/device.hpp>
+
+#ifdef BOOST_COMPUTE_HAVE_HDR_CL_EXT
+ #include <CL/cl_ext.h>
+#endif
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+#ifdef CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV
+ #define BOOST_COMPUTE_CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV
+#else
+ #define BOOST_COMPUTE_CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV 0x4000
+#endif
+
+#ifdef CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV
+ #define BOOST_COMPUTE_CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV
+#else
+ #define BOOST_COMPUTE_CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV 0x4001
+#endif
+
+inline void get_nvidia_compute_capability(const device &device, int &major, int &minor)
+{
+ if(!device.supports_extension("cl_nv_device_attribute_query")){
+ major = minor = 0;
+ return;
+ }
+
+ major = device.get_info<uint_>(BOOST_COMPUTE_CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV);
+ minor = device.get_info<uint_>(BOOST_COMPUTE_CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV);
+}
+
+inline bool check_nvidia_compute_capability(const device &device, int major, int minor)
+{
+ int actual_major, actual_minor;
+ get_nvidia_compute_capability(device, actual_major, actual_minor);
+
+ return actual_major > major ||
+ (actual_major == major && actual_minor >= minor);
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DETAIL_NVIDIA_COMPUTE_CAPABILITY_HPP
diff --git a/boost/compute/detail/parameter_cache.hpp b/boost/compute/detail/parameter_cache.hpp
new file mode 100644
index 0000000000..2a856311e1
--- /dev/null
+++ b/boost/compute/detail/parameter_cache.hpp
@@ -0,0 +1,215 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_PARAMETER_CACHE_HPP
+#define BOOST_COMPUTE_DETAIL_PARAMETER_CACHE_HPP
+
+#include <algorithm>
+#include <string>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/noncopyable.hpp>
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/device.hpp>
+#include <boost/compute/detail/global_static.hpp>
+#include <boost/compute/version.hpp>
+
+#ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE
+#include <boost/algorithm/string/trim.hpp>
+#include <boost/compute/detail/path.hpp>
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/json_parser.hpp>
+#endif // BOOST_COMPUTE_USE_OFFLINE_CACHE
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+class parameter_cache : boost::noncopyable
+{
+public:
+ parameter_cache(const device &device)
+ : m_dirty(false),
+ m_device_name(device.name())
+ {
+ #ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE
+ // get offline cache file name (e.g. /home/user/.boost_compute/tune/device.json)
+ m_file_name = make_file_name();
+
+ // load parameters from offline cache file (if it exists)
+ if(boost::filesystem::exists(m_file_name)){
+ read_from_disk();
+ }
+ #endif // BOOST_COMPUTE_USE_OFFLINE_CACHE
+ }
+
+ ~parameter_cache()
+ {
+ #ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE
+ write_to_disk();
+ #endif // BOOST_COMPUTE_USE_OFFLINE_CACHE
+ }
+
+ void set(const std::string &object, const std::string &parameter, uint_ value)
+ {
+ m_cache[std::make_pair(object, parameter)] = value;
+
+ // set the dirty flag to true. this will cause the updated parameters
+ // to be stored to disk.
+ m_dirty = true;
+ }
+
+ uint_ get(const std::string &object, const std::string &parameter, uint_ default_value)
+ {
+ std::map<std::pair<std::string, std::string>, uint_>::iterator
+ iter = m_cache.find(std::make_pair(object, parameter));
+ if(iter != m_cache.end()){
+ return iter->second;
+ }
+ else {
+ return default_value;
+ }
+ }
+
+ static boost::shared_ptr<parameter_cache> get_global_cache(const device &device)
+ {
+ // device name -> parameter cache
+ typedef std::map<std::string, boost::shared_ptr<parameter_cache> > cache_map;
+
+ BOOST_COMPUTE_DETAIL_GLOBAL_STATIC(cache_map, caches, ((std::less<std::string>())));
+
+ cache_map::iterator iter = caches.find(device.name());
+ if(iter == caches.end()){
+ boost::shared_ptr<parameter_cache> cache =
+ boost::make_shared<parameter_cache>(device);
+
+ caches.insert(iter, std::make_pair(device.name(), cache));
+
+ return cache;
+ }
+ else {
+ return iter->second;
+ }
+ }
+
+private:
+#ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE
+ // returns a string containing a cannoical device name
+ static std::string cannonical_device_name(std::string name)
+ {
+ boost::algorithm::trim(name);
+ std::replace(name.begin(), name.end(), ' ', '_');
+ std::replace(name.begin(), name.end(), '(', '_');
+ std::replace(name.begin(), name.end(), ')', '_');
+ return name;
+ }
+
+ // returns the boost.compute version string
+ static std::string version_string()
+ {
+ char buf[32];
+ std::snprintf(buf, sizeof(buf), "%d.%d.%d", BOOST_COMPUTE_VERSION_MAJOR,
+ BOOST_COMPUTE_VERSION_MINOR,
+ BOOST_COMPUTE_VERSION_PATCH);
+ return buf;
+ }
+
+ // returns the file path for the cached parameters
+ std::string make_file_name() const
+ {
+ return detail::parameter_cache_path(true) + cannonical_device_name(m_device_name) + ".json";
+ }
+
+ // store current parameters to disk
+ void write_to_disk()
+ {
+ BOOST_ASSERT(!m_file_name.empty());
+
+ if(m_dirty){
+ // save current parameters to disk
+ boost::property_tree::ptree pt;
+ pt.put("header.device", m_device_name);
+ pt.put("header.version", version_string());
+ typedef std::map<std::pair<std::string, std::string>, uint_> map_type;
+ for(map_type::const_iterator iter = m_cache.begin(); iter != m_cache.end(); ++iter){
+ const std::pair<std::string, std::string> &key = iter->first;
+ pt.add(key.first + "." + key.second, iter->second);
+ }
+ write_json(m_file_name, pt);
+
+ m_dirty = false;
+ }
+ }
+
+ // load stored parameters from disk
+ void read_from_disk()
+ {
+ BOOST_ASSERT(!m_file_name.empty());
+
+ m_cache.clear();
+
+ boost::property_tree::ptree pt;
+ try {
+ read_json(m_file_name, pt);
+ }
+ catch(boost::property_tree::json_parser::json_parser_error &e){
+ // no saved cache file, ignore
+ return;
+ }
+
+ std::string stored_device;
+ try {
+ stored_device = pt.get<std::string>("header.device");
+ }
+ catch(boost::property_tree::ptree_bad_path&){
+ return;
+ }
+
+ std::string stored_version;
+ try {
+ stored_version = pt.get<std::string>("header.version");
+ }
+ catch(boost::property_tree::ptree_bad_path&){
+ return;
+ }
+
+ if(stored_device == m_device_name && stored_version == version_string()){
+ typedef boost::property_tree::ptree::const_iterator pt_iter;
+ for(pt_iter iter = pt.begin(); iter != pt.end(); ++iter){
+ if(iter->first == "header"){
+ // skip header
+ continue;
+ }
+
+ boost::property_tree::ptree child_pt = pt.get_child(iter->first);
+ for(pt_iter child_iter = child_pt.begin(); child_iter != child_pt.end(); ++child_iter){
+ set(iter->first, child_iter->first, boost::lexical_cast<uint_>(child_iter->second.data()));
+ }
+ }
+ }
+
+ m_dirty = false;
+ }
+#endif // BOOST_COMPUTE_USE_OFFLINE_CACHE
+
+private:
+ bool m_dirty;
+ std::string m_device_name;
+ std::string m_file_name;
+ std::map<std::pair<std::string, std::string>, uint_> m_cache;
+};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DETAIL_PARAMETER_CACHE_HPP
diff --git a/boost/compute/detail/path.hpp b/boost/compute/detail/path.hpp
new file mode 100644
index 0000000000..ec8760eaf9
--- /dev/null
+++ b/boost/compute/detail/path.hpp
@@ -0,0 +1,73 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_PATH_HPP
+#define BOOST_COMPUTE_DETAIL_PATH_HPP
+
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/compute/detail/getenv.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+// Path delimiter symbol for the current OS.
+static const std::string& path_delim()
+{
+ static const std::string delim =
+ boost::filesystem::path("/").make_preferred().string();
+ return delim;
+}
+
+// Path to appdata folder.
+inline const std::string& appdata_path()
+{
+ #ifdef WIN32
+ static const std::string appdata = detail::getenv("APPDATA")
+ + path_delim() + "boost_compute";
+ #else
+ static const std::string appdata = detail::getenv("HOME")
+ + path_delim() + ".boost_compute";
+ #endif
+ return appdata;
+}
+
+// Path to cached binaries.
+inline std::string program_binary_path(const std::string &hash, bool create = false)
+{
+ std::string dir = detail::appdata_path() + path_delim()
+ + hash.substr(0, 2) + path_delim()
+ + hash.substr(2);
+
+ if(create && !boost::filesystem::exists(dir)){
+ boost::filesystem::create_directories(dir);
+ }
+
+ return dir + path_delim();
+}
+
+// Path to parameter caches.
+inline std::string parameter_cache_path(bool create = false)
+{
+ const static std::string dir = appdata_path() + path_delim() + "tune";
+
+ if(create && !boost::filesystem::exists(dir)){
+ boost::filesystem::create_directories(dir);
+ }
+
+ return dir + path_delim();
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DETAIL_PATH_HPP
diff --git a/boost/compute/detail/print_range.hpp b/boost/compute/detail/print_range.hpp
new file mode 100644
index 0000000000..bfe02f6828
--- /dev/null
+++ b/boost/compute/detail/print_range.hpp
@@ -0,0 +1,82 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_PRINT_RANGE_HPP
+#define BOOST_COMPUTE_DETAIL_PRINT_RANGE_HPP
+
+#include <vector>
+#include <iostream>
+#include <iterator>
+
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/is_buffer_iterator.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputIterator>
+inline void print_range(InputIterator first,
+ InputIterator last,
+ command_queue &queue,
+ typename boost::enable_if<
+ is_buffer_iterator<InputIterator>
+ >::type* = 0)
+{
+ typedef typename
+ std::iterator_traits<InputIterator>::value_type
+ value_type;
+
+ const size_t size = iterator_range_size(first, last);
+
+ // copy values to temporary vector on the host
+ std::vector<value_type> tmp(size);
+ ::boost::compute::copy(first, last, tmp.begin(), queue);
+
+ // print values
+ std::cout << "[ ";
+ for(size_t i = 0; i < size; i++){
+ std::cout << tmp[i];
+ if(i != size - 1){
+ std::cout << ", ";
+ }
+ }
+ std::cout << " ]" << std::endl;
+}
+
+template<class InputIterator>
+inline void print_range(InputIterator first,
+ InputIterator last,
+ command_queue &queue,
+ typename boost::enable_if_c<
+ !is_buffer_iterator<InputIterator>::value
+ >::type* = 0)
+{
+ typedef typename
+ std::iterator_traits<InputIterator>::value_type
+ value_type;
+
+ const context &context = queue.get_context();
+ const size_t size = iterator_range_size(first, last);
+
+ // copy values to temporary vector on the device
+ ::boost::compute::vector<value_type> tmp(size, context);
+ ::boost::compute::copy(first, last, tmp.begin(), queue);
+
+ print_range(tmp.begin(), tmp.end(), queue);
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DETAIL_PRINT_RANGE_HPP
diff --git a/boost/compute/detail/read_write_single_value.hpp b/boost/compute/detail/read_write_single_value.hpp
new file mode 100644
index 0000000000..fde40d946c
--- /dev/null
+++ b/boost/compute/detail/read_write_single_value.hpp
@@ -0,0 +1,77 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_READ_WRITE_SINGLE_VALUE_HPP
+#define BOOST_COMPUTE_DETAIL_READ_WRITE_SINGLE_VALUE_HPP
+
+#include <boost/throw_exception.hpp>
+
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/exception.hpp>
+#include <boost/compute/command_queue.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+// reads and returns a single value at index in the buffer
+template<class T>
+inline T read_single_value(const buffer &buffer,
+ size_t index,
+ command_queue &queue)
+{
+ BOOST_ASSERT(index < buffer.size() / sizeof(T));
+ BOOST_ASSERT(buffer.get_context() == queue.get_context());
+
+ T value;
+ queue.enqueue_read_buffer(buffer,
+ sizeof(T) * index,
+ sizeof(T),
+ &value);
+ return value;
+}
+
+// reads and returns a the first value in the buffer
+template<class T>
+inline T read_single_value(const buffer &buffer, command_queue &queue)
+{
+ return read_single_value<T>(buffer, 0, queue);
+}
+
+// writes a single value at index to the buffer
+template<class T>
+inline void write_single_value(const T &value,
+ const buffer &buffer,
+ size_t index,
+ command_queue &queue)
+{
+ BOOST_ASSERT(index < buffer.size() / sizeof(T));
+ BOOST_ASSERT(buffer.get_context() == queue.get_context());
+
+ queue.enqueue_write_buffer(buffer,
+ index * sizeof(T),
+ sizeof(T),
+ &value);
+}
+
+// writes value to the first location in buffer
+template<class T>
+inline void write_single_value(const T &value,
+ const buffer &buffer,
+ command_queue &queue)
+{
+ write_single_value<T>(value, buffer, 0, queue);
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DETAIL_READ_WRITE_SINGLE_VALUE_HPP
diff --git a/boost/compute/detail/sha1.hpp b/boost/compute/detail/sha1.hpp
new file mode 100644
index 0000000000..5685fa4407
--- /dev/null
+++ b/boost/compute/detail/sha1.hpp
@@ -0,0 +1,53 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_SHA1_HPP
+#define BOOST_COMPUTE_DETAIL_SHA1_HPP
+
+#include <sstream>
+#include <iomanip>
+#include <boost/uuid/sha1.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+// Accumulates SHA1 hash of the passed strings.
+class sha1 {
+ public:
+ sha1(const std::string &s = "") {
+ if (!s.empty()) this->process(s);
+ }
+
+ sha1& process(const std::string &s) {
+ h.process_bytes(s.c_str(), s.size());
+ return *this;
+ }
+
+ operator std::string() {
+ unsigned int digest[5];
+ h.get_digest(digest);
+
+ std::ostringstream buf;
+ for(int i = 0; i < 5; ++i)
+ buf << std::hex << std::setfill('0') << std::setw(8) << digest[i];
+
+ return buf.str();
+ }
+ private:
+ boost::uuids::detail::sha1 h;
+};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+
+#endif // BOOST_COMPUTE_DETAIL_SHA1_HPP
diff --git a/boost/compute/detail/variadic_macros.hpp b/boost/compute/detail/variadic_macros.hpp
new file mode 100644
index 0000000000..60f44bd1a8
--- /dev/null
+++ b/boost/compute/detail/variadic_macros.hpp
@@ -0,0 +1,35 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_VARIDAIC_MACROS_HPP
+#define BOOST_COMPUTE_DETAIL_VARIDAIC_MACROS_HPP
+
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/config/config.hpp>
+#include <boost/preprocessor/tuple/to_seq.hpp>
+
+#if BOOST_PP_VARIADICS == 1
+# include <boost/preprocessor/variadic/size.hpp>
+#endif
+
+#ifdef BOOST_PP_VARIADIC_SIZE
+# define BOOST_COMPUTE_PP_VARIADIC_SIZE BOOST_PP_VARIADIC_SIZE
+#else
+# define BOOST_COMPUTE_PP_VARIADIC_SIZE(...) BOOST_COMPUTE_PP_VARIADIC_SIZE_I(__VA_ARGS__, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 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,)
+# define BOOST_COMPUTE_PP_VARIADIC_SIZE_I(e0, 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, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63, size, ...) size
+#endif
+
+#define BOOST_COMPUTE_PP_TUPLE_SIZE(tuple) \
+ BOOST_COMPUTE_PP_VARIADIC_SIZE tuple
+
+#define BOOST_COMPUTE_PP_TUPLE_TO_SEQ(tuple) \
+ BOOST_PP_TUPLE_TO_SEQ(BOOST_COMPUTE_PP_TUPLE_SIZE(tuple), tuple)
+
+#endif // BOOST_COMPUTE_DETAIL_VARIDAIC_MACROS_HPP
diff --git a/boost/compute/detail/vendor.hpp b/boost/compute/detail/vendor.hpp
new file mode 100644
index 0000000000..0aa9c9c0d4
--- /dev/null
+++ b/boost/compute/detail/vendor.hpp
@@ -0,0 +1,38 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_VENDOR_HPP
+#define BOOST_COMPUTE_DETAIL_VENDOR_HPP
+
+#include <boost/compute/device.hpp>
+#include <boost/compute/platform.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+// returns true if the device is an nvidia gpu
+inline bool is_nvidia_device(const device &device)
+{
+ std::string nvidia("NVIDIA");
+ return device.vendor().compare(0, nvidia.size(), nvidia) == 0;
+}
+
+// returns true if the device is an amd cpu or gpu
+inline bool is_amd_device(const device &device)
+{
+ return device.platform().vendor() == "Advanced Micro Devices, Inc.";
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DETAIL_VENDOR_HPP
diff --git a/boost/compute/detail/work_size.hpp b/boost/compute/detail/work_size.hpp
new file mode 100644
index 0000000000..552d797b8b
--- /dev/null
+++ b/boost/compute/detail/work_size.hpp
@@ -0,0 +1,37 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DETAIL_WORK_SIZE_HPP
+#define BOOST_COMPUTE_DETAIL_WORK_SIZE_HPP
+
+#include <cmath>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+// Given a total number of values (count), a number of values to
+// process per thread (vtp), and a number of threads to execute per
+// block (tpb), this function returns the global work size to be
+// passed to clEnqueueNDRangeKernel() for a 1D algorithm.
+inline size_t calculate_work_size(size_t count, size_t vpt, size_t tpb)
+{
+ size_t work_size = static_cast<size_t>(std::ceil(float(count) / vpt));
+ if(work_size % tpb != 0){
+ work_size += tpb - work_size % tpb;
+ }
+ return work_size;
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DETAIL_WORK_SIZE_HPP
diff --git a/boost/compute/device.hpp b/boost/compute/device.hpp
new file mode 100644
index 0000000000..5cf2e8c931
--- /dev/null
+++ b/boost/compute/device.hpp
@@ -0,0 +1,584 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_DEVICE_HPP
+#define BOOST_COMPUTE_DEVICE_HPP
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/classification.hpp>
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/exception.hpp>
+#include <boost/compute/types/fundamental.hpp>
+#include <boost/compute/detail/get_object_info.hpp>
+#include <boost/compute/detail/assert_cl_success.hpp>
+
+namespace boost {
+namespace compute {
+
+class platform;
+
+/// \class device
+/// \brief A compute device.
+///
+/// Typical compute devices include GPUs and multi-core CPUs. A list
+/// of all compute devices available on a platform can be obtained
+/// via the platform::devices() method.
+///
+/// The default compute device for the system can be obtained with
+/// the system::default_device() method. For example:
+///
+/// \snippet test/test_device.cpp default_gpu
+///
+/// \see platform, context, command_queue
+class device
+{
+public:
+ enum type {
+ cpu = CL_DEVICE_TYPE_CPU,
+ gpu = CL_DEVICE_TYPE_GPU,
+ accelerator = CL_DEVICE_TYPE_ACCELERATOR
+ };
+
+ /// Creates a null device object.
+ device()
+ : m_id(0)
+ {
+ }
+
+ /// Creates a new device object for \p id. If \p retain is \c true,
+ /// the reference count for the device will be incremented.
+ explicit device(cl_device_id id, bool retain = true)
+ : m_id(id)
+ {
+ #ifdef CL_VERSION_1_2
+ if(m_id && retain && is_subdevice()){
+ clRetainDevice(m_id);
+ }
+ #else
+ (void) retain;
+ #endif
+ }
+
+ /// Creates a new device object as a copy of \p other.
+ device(const device &other)
+ : m_id(other.m_id)
+ {
+ #ifdef CL_VERSION_1_2
+ if(m_id && is_subdevice()){
+ clRetainDevice(m_id);
+ }
+ #endif
+ }
+
+ /// Copies the device from \p other to \c *this.
+ device& operator=(const device &other)
+ {
+ if(this != &other){
+ #ifdef CL_VERSION_1_2
+ if(m_id && is_subdevice()){
+ clReleaseDevice(m_id);
+ }
+ #endif
+
+ m_id = other.m_id;
+
+ #ifdef CL_VERSION_1_2
+ if(m_id && is_subdevice()){
+ clRetainDevice(m_id);
+ }
+ #endif
+ }
+
+ return *this;
+ }
+
+ #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+ /// Move-constructs a new device object from \p other.
+ device(device&& other) BOOST_NOEXCEPT
+ : m_id(other.m_id)
+ {
+ other.m_id = 0;
+ }
+
+ /// Move-assigns the device from \p other to \c *this.
+ device& operator=(device&& other) BOOST_NOEXCEPT
+ {
+ #ifdef CL_VERSION_1_2
+ if(m_id && is_subdevice()){
+ clReleaseDevice(m_id);
+ }
+ #endif
+
+ m_id = other.m_id;
+ other.m_id = 0;
+
+ return *this;
+ }
+ #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+ /// Destroys the device object.
+ ~device()
+ {
+ #ifdef CL_VERSION_1_2
+ if(m_id && is_subdevice()){
+ BOOST_COMPUTE_ASSERT_CL_SUCCESS(
+ clReleaseDevice(m_id)
+ );
+ }
+ #endif
+ }
+
+ /// Returns the ID of the device.
+ cl_device_id id() const
+ {
+ return m_id;
+ }
+
+ /// Returns a reference to the underlying OpenCL device id.
+ cl_device_id& get() const
+ {
+ return const_cast<cl_device_id&>(m_id);
+ }
+
+ /// Returns the type of the device.
+ cl_device_type type() const
+ {
+ return get_info<cl_device_type>(CL_DEVICE_TYPE);
+ }
+
+ #ifdef BOOST_COMPUTE_DOXYGEN_INVOKED
+ /// Returns the platform for the device.
+ platform platform() const;
+ #else
+ boost::compute::platform platform() const;
+ #endif
+
+ /// Returns the name of the device.
+ std::string name() const
+ {
+ return get_info<std::string>(CL_DEVICE_NAME);
+ }
+
+ /// Returns the name of the vendor for the device.
+ std::string vendor() const
+ {
+ return get_info<std::string>(CL_DEVICE_VENDOR);
+ }
+
+ /// Returns the device profile string.
+ std::string profile() const
+ {
+ return get_info<std::string>(CL_DEVICE_PROFILE);
+ }
+
+ /// Returns the device version string.
+ std::string version() const
+ {
+ return get_info<std::string>(CL_DEVICE_VERSION);
+ }
+
+ /// Returns the driver version string.
+ std::string driver_version() const
+ {
+ return get_info<std::string>(CL_DRIVER_VERSION);
+ }
+
+ /// Returns a list of extensions supported by the device.
+ std::vector<std::string> extensions() const
+ {
+ std::string extensions_string =
+ get_info<std::string>(CL_DEVICE_EXTENSIONS);
+ std::vector<std::string> extensions_vector;
+ boost::split(extensions_vector,
+ extensions_string,
+ boost::is_any_of("\t "),
+ boost::token_compress_on);
+ return extensions_vector;
+ }
+
+ /// Returns \c true if the device supports the extension with
+ /// \p name.
+ bool supports_extension(const std::string &name) const
+ {
+ const std::vector<std::string> extensions = this->extensions();
+
+ return std::find(
+ extensions.begin(), extensions.end(), name) != extensions.end();
+ }
+
+ /// Returns the number of address bits.
+ uint_ address_bits() const
+ {
+ return get_info<uint_>(CL_DEVICE_ADDRESS_BITS);
+ }
+
+ /// Returns the global memory size in bytes.
+ ulong_ global_memory_size() const
+ {
+ return get_info<ulong_>(CL_DEVICE_GLOBAL_MEM_SIZE);
+ }
+
+ /// Returns the local memory size in bytes.
+ ulong_ local_memory_size() const
+ {
+ return get_info<ulong_>(CL_DEVICE_LOCAL_MEM_SIZE);
+ }
+
+ /// Returns the clock frequency for the device's compute units.
+ uint_ clock_frequency() const
+ {
+ return get_info<uint_>(CL_DEVICE_MAX_CLOCK_FREQUENCY);
+ }
+
+ /// Returns the number of compute units in the device.
+ uint_ compute_units() const
+ {
+ return get_info<uint_>(CL_DEVICE_MAX_COMPUTE_UNITS);
+ }
+
+ /// \internal_
+ ulong_ max_memory_alloc_size() const
+ {
+ return get_info<ulong_>(CL_DEVICE_MAX_MEM_ALLOC_SIZE);
+ }
+
+ /// \internal_
+ size_t max_work_group_size() const
+ {
+ return get_info<size_t>(CL_DEVICE_MAX_WORK_GROUP_SIZE);
+ }
+
+ /// \internal_
+ uint_ max_work_item_dimensions() const
+ {
+ return get_info<uint_>(CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS);
+ }
+
+ /// Returns the preferred vector width for type \c T.
+ template<class T>
+ uint_ preferred_vector_width() const
+ {
+ return 0;
+ }
+
+ /// Returns the profiling timer resolution in nanoseconds.
+ size_t profiling_timer_resolution() const
+ {
+ return get_info<size_t>(CL_DEVICE_PROFILING_TIMER_RESOLUTION);
+ }
+
+ /// Returns \c true if the device is a sub-device.
+ bool is_subdevice() const
+ {
+ #if defined(CL_VERSION_1_2)
+ try {
+ return get_info<cl_device_id>(CL_DEVICE_PARENT_DEVICE) != 0;
+ }
+ catch(opencl_error&){
+ // the get_info() call above will throw if the device's opencl version
+ // is less than 1.2 (in which case it can't be a sub-device).
+ return false;
+ }
+ #else
+ return false;
+ #endif
+ }
+
+ /// Returns information about the device.
+ ///
+ /// For example, to get the number of compute units:
+ /// \code
+ /// device.get_info<cl_uint>(CL_DEVICE_MAX_COMPUTE_UNITS);
+ /// \endcode
+ ///
+ /// Alternatively, the template-specialized version can be used which
+ /// automatically determines the result type:
+ /// \code
+ /// device.get_info<CL_DEVICE_MAX_COMPUTE_UNITS>();
+ /// \endcode
+ ///
+ /// \see_opencl_ref{clGetDeviceInfo}
+ template<class T>
+ T get_info(cl_device_info info) const
+ {
+ return detail::get_object_info<T>(clGetDeviceInfo, m_id, info);
+ }
+
+ /// \overload
+ template<int Enum>
+ typename detail::get_object_info_type<device, Enum>::type
+ get_info() const;
+
+ #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ /// Partitions the device into multiple sub-devices according to
+ /// \p properties.
+ ///
+ /// \opencl_version_warning{1,2}
+ std::vector<device>
+ partition(const cl_device_partition_property *properties) const
+ {
+ // get sub-device count
+ uint_ count = 0;
+ int_ ret = clCreateSubDevices(m_id, properties, 0, 0, &count);
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ // get sub-device ids
+ std::vector<cl_device_id> ids(count);
+ ret = clCreateSubDevices(m_id, properties, count, &ids[0], 0);
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ // convert ids to device objects
+ std::vector<device> devices(count);
+ for(size_t i = 0; i < count; i++){
+ devices[i] = device(ids[i], false);
+ }
+
+ return devices;
+ }
+
+ /// \opencl_version_warning{1,2}
+ std::vector<device> partition_equally(size_t count) const
+ {
+ cl_device_partition_property properties[] = {
+ CL_DEVICE_PARTITION_EQUALLY,
+ static_cast<cl_device_partition_property>(count),
+ 0
+ };
+
+ return partition(properties);
+ }
+
+ /// \opencl_version_warning{1,2}
+ std::vector<device>
+ partition_by_counts(const std::vector<size_t> &counts) const
+ {
+ std::vector<cl_device_partition_property> properties;
+
+ properties.push_back(CL_DEVICE_PARTITION_BY_COUNTS);
+ for(size_t i = 0; i < counts.size(); i++){
+ properties.push_back(
+ static_cast<cl_device_partition_property>(counts[i]));
+ }
+ properties.push_back(CL_DEVICE_PARTITION_BY_COUNTS_LIST_END);
+ properties.push_back(0);
+
+ return partition(&properties[0]);
+ }
+
+ /// \opencl_version_warning{1,2}
+ std::vector<device>
+ partition_by_affinity_domain(cl_device_affinity_domain domain) const
+ {
+ cl_device_partition_property properties[] = {
+ CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN,
+ static_cast<cl_device_partition_property>(domain),
+ 0
+ };
+
+ return partition(properties);
+ }
+ #endif // CL_VERSION_1_2
+
+ /// Returns \c true if the device is the same at \p other.
+ bool operator==(const device &other) const
+ {
+ return m_id == other.m_id;
+ }
+
+ /// Returns \c true if the device is different from \p other.
+ bool operator!=(const device &other) const
+ {
+ return m_id != other.m_id;
+ }
+
+ /// \internal_
+ bool check_version(int major, int minor) const
+ {
+ std::stringstream stream;
+ stream << version();
+
+ int actual_major, actual_minor;
+ stream.ignore(7); // 'OpenCL '
+ stream >> actual_major;
+ stream.ignore(1); // '.'
+ stream >> actual_minor;
+
+ return actual_major > major ||
+ (actual_major == major && actual_minor >= minor);
+ }
+
+private:
+ cl_device_id m_id;
+};
+
+/// \internal_
+template<>
+inline uint_ device::preferred_vector_width<short_>() const
+{
+ return get_info<uint_>(CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT);
+}
+
+/// \internal_
+template<>
+inline uint_ device::preferred_vector_width<int_>() const
+{
+ return get_info<uint_>(CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT);
+}
+
+/// \internal_
+template<>
+inline uint_ device::preferred_vector_width<long_>() const
+{
+ return get_info<uint_>(CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG);
+}
+
+/// \internal_
+template<>
+inline uint_ device::preferred_vector_width<float_>() const
+{
+ return get_info<uint_>(CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT);
+}
+
+/// \internal_
+template<>
+inline uint_ device::preferred_vector_width<double_>() const
+{
+ return get_info<uint_>(CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE);
+}
+
+/// \internal_ define get_info() specializations for device
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device,
+ ((cl_uint, CL_DEVICE_ADDRESS_BITS))
+ ((bool, CL_DEVICE_AVAILABLE))
+ ((bool, CL_DEVICE_COMPILER_AVAILABLE))
+ ((bool, CL_DEVICE_ENDIAN_LITTLE))
+ ((bool, CL_DEVICE_ERROR_CORRECTION_SUPPORT))
+ ((cl_device_exec_capabilities, CL_DEVICE_EXECUTION_CAPABILITIES))
+ ((std::string, CL_DEVICE_EXTENSIONS))
+ ((cl_ulong, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE))
+ ((cl_device_mem_cache_type, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE))
+ ((cl_ulong, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE))
+ ((cl_ulong, CL_DEVICE_GLOBAL_MEM_SIZE))
+ ((bool, CL_DEVICE_IMAGE_SUPPORT))
+ ((size_t, CL_DEVICE_IMAGE2D_MAX_HEIGHT))
+ ((size_t, CL_DEVICE_IMAGE2D_MAX_WIDTH))
+ ((size_t, CL_DEVICE_IMAGE3D_MAX_DEPTH))
+ ((size_t, CL_DEVICE_IMAGE3D_MAX_HEIGHT))
+ ((size_t, CL_DEVICE_IMAGE3D_MAX_WIDTH))
+ ((cl_ulong, CL_DEVICE_LOCAL_MEM_SIZE))
+ ((cl_device_local_mem_type, CL_DEVICE_LOCAL_MEM_TYPE))
+ ((cl_uint, CL_DEVICE_MAX_CLOCK_FREQUENCY))
+ ((cl_uint, CL_DEVICE_MAX_COMPUTE_UNITS))
+ ((cl_uint, CL_DEVICE_MAX_CONSTANT_ARGS))
+ ((cl_ulong, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE))
+ ((cl_ulong, CL_DEVICE_MAX_MEM_ALLOC_SIZE))
+ ((size_t, CL_DEVICE_MAX_PARAMETER_SIZE))
+ ((cl_uint, CL_DEVICE_MAX_READ_IMAGE_ARGS))
+ ((cl_uint, CL_DEVICE_MAX_SAMPLERS))
+ ((size_t, CL_DEVICE_MAX_WORK_GROUP_SIZE))
+ ((cl_uint, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS))
+ ((std::vector<size_t>, CL_DEVICE_MAX_WORK_ITEM_SIZES))
+ ((cl_uint, CL_DEVICE_MAX_WRITE_IMAGE_ARGS))
+ ((cl_uint, CL_DEVICE_MEM_BASE_ADDR_ALIGN))
+ ((cl_uint, CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE))
+ ((std::string, CL_DEVICE_NAME))
+ ((cl_platform_id, CL_DEVICE_PLATFORM))
+ ((cl_uint, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR))
+ ((cl_uint, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT))
+ ((cl_uint, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT))
+ ((cl_uint, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG))
+ ((cl_uint, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT))
+ ((cl_uint, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE))
+ ((std::string, CL_DEVICE_PROFILE))
+ ((size_t, CL_DEVICE_PROFILING_TIMER_RESOLUTION))
+ ((cl_command_queue_properties, CL_DEVICE_QUEUE_PROPERTIES))
+ ((cl_device_fp_config, CL_DEVICE_SINGLE_FP_CONFIG))
+ ((cl_device_type, CL_DEVICE_TYPE))
+ ((std::string, CL_DEVICE_VENDOR))
+ ((cl_uint, CL_DEVICE_VENDOR_ID))
+ ((std::string, CL_DEVICE_VERSION))
+ ((std::string, CL_DRIVER_VERSION))
+)
+
+#ifdef CL_DEVICE_DOUBLE_FP_CONFIG
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device,
+ ((cl_device_fp_config, CL_DEVICE_DOUBLE_FP_CONFIG))
+)
+#endif
+
+#ifdef CL_DEVICE_HALF_FP_CONFIG
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device,
+ ((cl_device_fp_config, CL_DEVICE_HALF_FP_CONFIG))
+)
+#endif
+
+#ifdef CL_VERSION_1_1
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device,
+ ((bool, CL_DEVICE_HOST_UNIFIED_MEMORY))
+ ((cl_uint, CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR))
+ ((cl_uint, CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT))
+ ((cl_uint, CL_DEVICE_NATIVE_VECTOR_WIDTH_INT))
+ ((cl_uint, CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG))
+ ((cl_uint, CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT))
+ ((cl_uint, CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE))
+ ((std::string, CL_DEVICE_OPENCL_C_VERSION))
+)
+#endif // CL_VERSION_1_1
+
+#ifdef CL_VERSION_1_2
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device,
+ ((std::string, CL_DEVICE_BUILT_IN_KERNELS))
+ ((bool, CL_DEVICE_LINKER_AVAILABLE))
+ ((cl_device_id, CL_DEVICE_PARENT_DEVICE))
+ ((cl_uint, CL_DEVICE_PARTITION_MAX_SUB_DEVICES))
+ ((cl_device_partition_property, CL_DEVICE_PARTITION_PROPERTIES))
+ ((cl_device_affinity_domain, CL_DEVICE_PARTITION_AFFINITY_DOMAIN))
+ ((cl_device_partition_property, CL_DEVICE_PARTITION_TYPE))
+ ((size_t, CL_DEVICE_PRINTF_BUFFER_SIZE))
+ ((bool, CL_DEVICE_PREFERRED_INTEROP_USER_SYNC))
+ ((cl_uint, CL_DEVICE_REFERENCE_COUNT))
+)
+#endif // CL_VERSION_1_2
+
+#ifdef CL_VERSION_2_0
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device,
+ ((size_t, CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE))
+ ((size_t, CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE))
+ ((cl_uint, CL_DEVICE_MAX_ON_DEVICE_EVENTS))
+ ((cl_uint, CL_DEVICE_MAX_ON_DEVICE_QUEUES))
+ ((cl_uint, CL_DEVICE_MAX_PIPE_ARGS))
+ ((cl_uint, CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS))
+ ((cl_uint, CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS))
+ ((cl_uint, CL_DEVICE_PIPE_MAX_PACKET_SIZE))
+ ((cl_uint, CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT))
+ ((cl_uint, CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT))
+ ((cl_uint, CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT))
+ ((cl_uint, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE))
+ ((cl_uint, CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE))
+ ((cl_command_queue_properties, CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES))
+ ((cl_device_svm_capabilities, CL_DEVICE_SVM_CAPABILITIES))
+ ((cl_uint, CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT))
+ ((cl_uint, CL_DEVICE_IMAGE_PITCH_ALIGNMENT))
+)
+#endif // CL_VERSION_2_0
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_DEVICE_HPP
diff --git a/boost/compute/event.hpp b/boost/compute/event.hpp
new file mode 100644
index 0000000000..2f53d87650
--- /dev/null
+++ b/boost/compute/event.hpp
@@ -0,0 +1,338 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_EVENT_HPP
+#define BOOST_COMPUTE_EVENT_HPP
+
+#include <boost/function.hpp>
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/exception.hpp>
+#include <boost/compute/detail/duration.hpp>
+#include <boost/compute/detail/get_object_info.hpp>
+#include <boost/compute/detail/assert_cl_success.hpp>
+#include <boost/compute/types/fundamental.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class event
+/// \brief An event corresponding to an operation on a compute device
+///
+/// Event objects are used to track operations running on the device (such as
+/// kernel executions and memory transfers). Event objects are returned by the
+/// various \c enqueue_* methods of the command_queue class.
+///
+/// Events can be used to synchronize operations between the host and the
+/// device. The \c wait() method will block execution on the host until the
+/// operation corresponding to the event on the device has completed. The
+/// status of the operation can also be polled with the \c status() method.
+///
+/// Event objects can also be used for performance profiling. In order to use
+/// events for profiling, the command queue must be constructed with the
+/// \c CL_QUEUE_PROFILING_ENABLE flag. Then the \c duration() method can be
+/// used to retrieve the total duration of the operation on the device:
+/// \code
+/// std::cout << "time = " << e.duration<std::chrono::milliseconds>().count() << "ms\n";
+/// \endcode
+///
+/// \see \ref future "future<T>", wait_list
+class event
+{
+public:
+ /// \internal_
+ enum execution_status {
+ complete = CL_COMPLETE,
+ running = CL_RUNNING,
+ submitted = CL_SUBMITTED,
+ queued = CL_QUEUED
+ };
+
+ /// \internal_
+ enum command_type {
+ ndrange_kernel = CL_COMMAND_NDRANGE_KERNEL,
+ task = CL_COMMAND_TASK,
+ native_kernel = CL_COMMAND_NATIVE_KERNEL,
+ read_buffer = CL_COMMAND_READ_BUFFER,
+ write_buffer = CL_COMMAND_WRITE_BUFFER,
+ copy_buffer = CL_COMMAND_COPY_BUFFER,
+ read_image = CL_COMMAND_READ_IMAGE,
+ write_image = CL_COMMAND_WRITE_IMAGE,
+ copy_image = CL_COMMAND_COPY_IMAGE,
+ copy_image_to_buffer = CL_COMMAND_COPY_IMAGE_TO_BUFFER,
+ copy_buffer_to_image = CL_COMMAND_COPY_BUFFER_TO_IMAGE,
+ map_buffer = CL_COMMAND_MAP_BUFFER,
+ map_image = CL_COMMAND_MAP_IMAGE,
+ unmap_mem_object = CL_COMMAND_UNMAP_MEM_OBJECT,
+ marker = CL_COMMAND_MARKER,
+ aquire_gl_objects = CL_COMMAND_ACQUIRE_GL_OBJECTS,
+ release_gl_object = CL_COMMAND_RELEASE_GL_OBJECTS
+ #if defined(CL_VERSION_1_1)
+ ,
+ read_buffer_rect = CL_COMMAND_READ_BUFFER_RECT,
+ write_buffer_rect = CL_COMMAND_WRITE_BUFFER_RECT,
+ copy_buffer_rect = CL_COMMAND_COPY_BUFFER_RECT
+ #endif
+ };
+
+ /// \internal_
+ enum profiling_info {
+ profiling_command_queued = CL_PROFILING_COMMAND_QUEUED,
+ profiling_command_submit = CL_PROFILING_COMMAND_SUBMIT,
+ profiling_command_start = CL_PROFILING_COMMAND_START,
+ profiling_command_end = CL_PROFILING_COMMAND_END
+ };
+
+ /// Creates a null event object.
+ event()
+ : m_event(0)
+ {
+ }
+
+ explicit event(cl_event event, bool retain = true)
+ : m_event(event)
+ {
+ if(m_event && retain){
+ clRetainEvent(event);
+ }
+ }
+
+ /// Makes a new event as a copy of \p other.
+ event(const event &other)
+ : m_event(other.m_event)
+ {
+ if(m_event){
+ clRetainEvent(m_event);
+ }
+ }
+
+ /// Copies the event object from \p other to \c *this.
+ event& operator=(const event &other)
+ {
+ if(this != &other){
+ if(m_event){
+ clReleaseEvent(m_event);
+ }
+
+ m_event = other.m_event;
+
+ if(m_event){
+ clRetainEvent(m_event);
+ }
+ }
+
+ return *this;
+ }
+
+ #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+ /// Move-constructs a new event object from \p other.
+ event(event&& other) BOOST_NOEXCEPT
+ : m_event(other.m_event)
+ {
+ other.m_event = 0;
+ }
+
+ /// Move-assigns the event from \p other to \c *this.
+ event& operator=(event&& other) BOOST_NOEXCEPT
+ {
+ if(m_event){
+ clReleaseEvent(m_event);
+ }
+
+ m_event = other.m_event;
+ other.m_event = 0;
+
+ return *this;
+ }
+ #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+ /// Destroys the event object.
+ ~event()
+ {
+ if(m_event){
+ BOOST_COMPUTE_ASSERT_CL_SUCCESS(
+ clReleaseEvent(m_event)
+ );
+ }
+ }
+
+ /// Returns a reference to the underlying OpenCL event object.
+ cl_event& get() const
+ {
+ return const_cast<cl_event &>(m_event);
+ }
+
+ /// Returns the status of the event.
+ cl_int status() const
+ {
+ return get_info<cl_int>(CL_EVENT_COMMAND_EXECUTION_STATUS);
+ }
+
+ /// Returns the command type for the event.
+ cl_command_type get_command_type() const
+ {
+ return get_info<cl_command_type>(CL_EVENT_COMMAND_TYPE);
+ }
+
+ /// Returns information about the event.
+ ///
+ /// \see_opencl_ref{clGetEventInfo}
+ template<class T>
+ T get_info(cl_event_info info) const
+ {
+ return detail::get_object_info<T>(clGetEventInfo, m_event, info);
+ }
+
+ /// \overload
+ template<int Enum>
+ typename detail::get_object_info_type<event, Enum>::type
+ get_info() const;
+
+ /// Returns profiling information for the event.
+ ///
+ /// \see event::duration()
+ ///
+ /// \see_opencl_ref{clGetEventProfilingInfo}
+ template<class T>
+ T get_profiling_info(cl_profiling_info info) const
+ {
+ return detail::get_object_info<T>(clGetEventProfilingInfo,
+ m_event,
+ info);
+ }
+
+ /// Blocks until the actions corresponding to the event have
+ /// completed.
+ void wait() const
+ {
+ cl_int ret = clWaitForEvents(1, &m_event);
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+ }
+
+ #if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ /// Registers a function to be called when the event status changes to
+ /// \p status (by default CL_COMPLETE). The callback is passed the OpenCL
+ /// event object, the event status, and a pointer to arbitrary user data.
+ ///
+ /// \see_opencl_ref{clSetEventCallback}
+ ///
+ /// \opencl_version_warning{1,1}
+ void set_callback(void (BOOST_COMPUTE_CL_CALLBACK *callback)(
+ cl_event event, cl_int status, void *user_data
+ ),
+ cl_int status = CL_COMPLETE,
+ void *user_data = 0)
+ {
+ cl_int ret = clSetEventCallback(m_event, status, callback, user_data);
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+ }
+
+ /// Registers a generic function to be called when the event status
+ /// changes to \p status (by default \c CL_COMPLETE).
+ ///
+ /// The function specified by \p callback must be invokable with zero
+ /// arguments (e.g. \c callback()).
+ ///
+ /// \opencl_version_warning{1,1}
+ template<class Function>
+ void set_callback(Function callback, cl_int status = CL_COMPLETE)
+ {
+ set_callback(
+ event_callback_invoker,
+ status,
+ new boost::function<void()>(callback)
+ );
+ }
+ #endif // CL_VERSION_1_1
+
+ /// Returns the total duration of the event from \p start to \p end.
+ ///
+ /// For example, to print the number of milliseconds the event took to
+ /// execute:
+ /// \code
+ /// std::cout << event.duration<std::chrono::milliseconds>().count() << " ms" << std::endl;
+ /// \endcode
+ ///
+ /// \see event::get_profiling_info()
+ template<class Duration>
+ Duration duration(cl_profiling_info start = CL_PROFILING_COMMAND_START,
+ cl_profiling_info end = CL_PROFILING_COMMAND_END) const
+ {
+ const ulong_ nanoseconds =
+ get_profiling_info<ulong_>(end) - get_profiling_info<ulong_>(start);
+
+ return detail::make_duration_from_nanoseconds(Duration(), nanoseconds);
+ }
+
+ /// Returns \c true if the event is the same as \p other.
+ bool operator==(const event &other) const
+ {
+ return m_event == other.m_event;
+ }
+
+ /// Returns \c true if the event is different from \p other.
+ bool operator!=(const event &other) const
+ {
+ return m_event != other.m_event;
+ }
+
+ /// \internal_
+ operator cl_event() const
+ {
+ return m_event;
+ }
+
+ /// \internal_ (deprecated)
+ cl_int get_status() const
+ {
+ return status();
+ }
+
+private:
+ #ifdef CL_VERSION_1_1
+ /// \internal_
+ static void BOOST_COMPUTE_CL_CALLBACK
+ event_callback_invoker(cl_event, cl_int, void *user_data)
+ {
+ boost::function<void()> *callback =
+ static_cast<boost::function<void()> *>(user_data);
+
+ (*callback)();
+
+ delete callback;
+ }
+ #endif // CL_VERSION_1_1
+
+protected:
+ cl_event m_event;
+};
+
+/// \internal_ define get_info() specializations for event
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(event,
+ ((cl_command_queue, CL_EVENT_COMMAND_QUEUE))
+ ((cl_command_type, CL_EVENT_COMMAND_TYPE))
+ ((cl_int, CL_EVENT_COMMAND_EXECUTION_STATUS))
+ ((cl_uint, CL_EVENT_REFERENCE_COUNT))
+)
+
+#ifdef CL_VERSION_1_1
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(event,
+ ((cl_context, CL_EVENT_CONTEXT))
+)
+#endif
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_EVENT_HPP
diff --git a/boost/compute/exception.hpp b/boost/compute/exception.hpp
new file mode 100644
index 0000000000..10a271de03
--- /dev/null
+++ b/boost/compute/exception.hpp
@@ -0,0 +1,23 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_EXCEPTION_HPP
+#define BOOST_COMPUTE_EXCEPTION_HPP
+
+/// \file
+///
+/// Meta-header to include all Boost.Compute exception headers.
+
+#include <boost/compute/exception/context_error.hpp>
+#include <boost/compute/exception/no_device_found.hpp>
+#include <boost/compute/exception/opencl_error.hpp>
+#include <boost/compute/exception/unsupported_extension_error.hpp>
+
+#endif // BOOST_COMPUTE_EXCEPTION_HPP
diff --git a/boost/compute/exception/context_error.hpp b/boost/compute/exception/context_error.hpp
new file mode 100644
index 0000000000..eeb387d884
--- /dev/null
+++ b/boost/compute/exception/context_error.hpp
@@ -0,0 +1,88 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_EXCEPTION_CONTEXT_ERROR_HPP
+#define BOOST_COMPUTE_EXCEPTION_CONTEXT_ERROR_HPP
+
+#include <exception>
+
+namespace boost {
+namespace compute {
+
+class context;
+
+/// \class context_error
+/// \brief A run-time OpenCL context error.
+///
+/// The context_error exception is thrown when the OpenCL context encounters
+/// an error condition. Boost.Compute is notified of these error conditions by
+/// registering an error handler when creating context objects (via the
+/// \c pfn_notify argument to the \c clCreateContext() function).
+///
+/// This exception is different than the opencl_error exception which is thrown
+/// as a result of error caused when calling a single OpenCL API function.
+///
+/// \see opencl_error
+class context_error : public std::exception
+{
+public:
+ /// Creates a new context error exception object.
+ context_error(const context *context,
+ const char *errinfo,
+ const void *private_info,
+ size_t private_info_size) throw()
+ : m_context(context),
+ m_errinfo(errinfo),
+ m_private_info(private_info),
+ m_private_info_size(private_info_size)
+ {
+ }
+
+ /// Destroys the context error object.
+ ~context_error() throw()
+ {
+ }
+
+ /// Returns a string with a description of the error.
+ const char* what() const throw()
+ {
+ return m_errinfo;
+ }
+
+ /// Returns a pointer to the context object which generated the error
+ /// notification.
+ const context* get_context_ptr() const throw()
+ {
+ return m_context;
+ }
+
+ /// Returns a pointer to the private info memory block.
+ const void* get_private_info_ptr() const throw()
+ {
+ return m_private_info;
+ }
+
+ /// Returns the size of the private info memory block.
+ const size_t get_private_info_size() const throw()
+ {
+ return m_private_info_size;
+ }
+
+private:
+ const context *m_context;
+ const char *m_errinfo;
+ const void *m_private_info;
+ size_t m_private_info_size;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_EXCEPTION_CONTEXT_ERROR_HPP
diff --git a/boost/compute/exception/no_device_found.hpp b/boost/compute/exception/no_device_found.hpp
new file mode 100644
index 0000000000..fb73942e0c
--- /dev/null
+++ b/boost/compute/exception/no_device_found.hpp
@@ -0,0 +1,48 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_EXCEPTION_NO_DEVICE_FOUND_HPP
+#define BOOST_COMPUTE_EXCEPTION_NO_DEVICE_FOUND_HPP
+
+#include <exception>
+
+namespace boost {
+namespace compute {
+
+/// \class no_device_found
+/// \brief Exception thrown when no OpenCL device is found
+///
+/// This exception is thrown when no valid OpenCL device can be found.
+///
+/// \see opencl_error
+class no_device_found : public std::exception
+{
+public:
+ /// Creates a new no_device_found exception object.
+ no_device_found() throw()
+ {
+ }
+
+ /// Destroys the no_device_found exception object.
+ ~no_device_found() throw()
+ {
+ }
+
+ /// Returns a string containing a human-readable error message.
+ const char* what() const throw()
+ {
+ return "No OpenCL device found";
+ }
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_EXCEPTION_NO_DEVICE_FOUND_HPP
diff --git a/boost/compute/exception/opencl_error.hpp b/boost/compute/exception/opencl_error.hpp
new file mode 100644
index 0000000000..29a3a9d258
--- /dev/null
+++ b/boost/compute/exception/opencl_error.hpp
@@ -0,0 +1,158 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_EXCEPTION_OPENCL_ERROR_HPP
+#define BOOST_COMPUTE_EXCEPTION_OPENCL_ERROR_HPP
+
+#include <exception>
+#include <string>
+#include <sstream>
+
+#include <boost/compute/cl.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class opencl_error
+/// \brief A run-time OpenCL error.
+///
+/// The opencl_error class represents an error returned from an OpenCL
+/// function.
+///
+/// \see context_error
+class opencl_error : public std::exception
+{
+public:
+ /// Creates a new opencl_error exception object for \p error.
+ explicit opencl_error(cl_int error) throw()
+ : m_error(error),
+ m_error_string(to_string(error))
+ {
+ }
+
+ /// Destroys the opencl_error object.
+ ~opencl_error() throw()
+ {
+ }
+
+ /// Returns the numeric error code.
+ cl_int error_code() const throw()
+ {
+ return m_error;
+ }
+
+ /// Returns a string description of the error.
+ std::string error_string() const throw()
+ {
+ return m_error_string;
+ }
+
+ /// Returns a C-string description of the error.
+ const char* what() const throw()
+ {
+ return m_error_string.c_str();
+ }
+
+ /// Static function which converts the numeric OpenCL error code \p error
+ /// to a human-readable string.
+ ///
+ /// For example:
+ /// \code
+ /// std::cout << opencl_error::to_string(CL_INVALID_KERNEL_ARGS) << std::endl;
+ /// \endcode
+ ///
+ /// Will print "Invalid Kernel Arguments".
+ ///
+ /// If the error code is unknown (e.g. not a valid OpenCL error), a string
+ /// containing "Unknown OpenCL Error" along with the error number will be
+ /// returned.
+ static std::string to_string(cl_int error)
+ {
+ switch(error){
+ case CL_SUCCESS: return "Success";
+ case CL_DEVICE_NOT_FOUND: return "Device Not Found";
+ case CL_DEVICE_NOT_AVAILABLE: return "Device Not Available";
+ case CL_COMPILER_NOT_AVAILABLE: return "Compiler Not Available";
+ case CL_MEM_OBJECT_ALLOCATION_FAILURE: return "Memory Object Allocation Failure";
+ case CL_OUT_OF_RESOURCES: return "Out of Resources";
+ case CL_OUT_OF_HOST_MEMORY: return "Out of Host Memory";
+ case CL_PROFILING_INFO_NOT_AVAILABLE: return "Profiling Information Not Available";
+ case CL_MEM_COPY_OVERLAP: return "Memory Copy Overlap";
+ case CL_IMAGE_FORMAT_MISMATCH: return "Image Format Mismatch";
+ case CL_IMAGE_FORMAT_NOT_SUPPORTED: return "Image Format Not Supported";
+ case CL_BUILD_PROGRAM_FAILURE: return "Build Program Failure";
+ case CL_MAP_FAILURE: return "Map Failure";
+ case CL_INVALID_VALUE: return "Invalid Value";
+ case CL_INVALID_DEVICE_TYPE: return "Invalid Device Type";
+ case CL_INVALID_PLATFORM: return "Invalid Platform";
+ case CL_INVALID_DEVICE: return "Invalid Device";
+ case CL_INVALID_CONTEXT: return "Invalid Context";
+ case CL_INVALID_QUEUE_PROPERTIES: return "Invalid Queue Properties";
+ case CL_INVALID_COMMAND_QUEUE: return "Invalid Command Queue";
+ case CL_INVALID_HOST_PTR: return "Invalid Host Pointer";
+ case CL_INVALID_MEM_OBJECT: return "Invalid Memory Object";
+ case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR: return "Invalid Image Format Descriptor";
+ case CL_INVALID_IMAGE_SIZE: return "Invalid Image Size";
+ case CL_INVALID_SAMPLER: return "Invalid Sampler";
+ case CL_INVALID_BINARY: return "Invalid Binary";
+ case CL_INVALID_BUILD_OPTIONS: return "Invalid Build Options";
+ case CL_INVALID_PROGRAM: return "Invalid Program";
+ case CL_INVALID_PROGRAM_EXECUTABLE: return "Invalid Program Executable";
+ case CL_INVALID_KERNEL_NAME: return "Invalid Kernel Name";
+ case CL_INVALID_KERNEL_DEFINITION: return "Invalid Kernel Definition";
+ case CL_INVALID_KERNEL: return "Invalid Kernel";
+ case CL_INVALID_ARG_INDEX: return "Invalid Argument Index";
+ case CL_INVALID_ARG_VALUE: return "Invalid Argument Value";
+ case CL_INVALID_ARG_SIZE: return "Invalid Argument Size";
+ case CL_INVALID_KERNEL_ARGS: return "Invalid Kernel Arguments";
+ case CL_INVALID_WORK_DIMENSION: return "Invalid Work Dimension";
+ case CL_INVALID_WORK_GROUP_SIZE: return "Invalid Work Group Size";
+ case CL_INVALID_WORK_ITEM_SIZE: return "Invalid Work Item Size";
+ case CL_INVALID_GLOBAL_OFFSET: return "Invalid Global Offset";
+ case CL_INVALID_EVENT_WAIT_LIST: return "Invalid Event Wait List";
+ case CL_INVALID_EVENT: return "Invalid Event";
+ case CL_INVALID_OPERATION: return "Invalid Operation";
+ case CL_INVALID_GL_OBJECT: return "Invalid GL Object";
+ case CL_INVALID_BUFFER_SIZE: return "Invalid Buffer Size";
+ case CL_INVALID_MIP_LEVEL: return "Invalid MIP Level";
+ case CL_INVALID_GLOBAL_WORK_SIZE: return "Invalid Global Work Size";
+ #ifdef CL_VERSION_1_2
+ case CL_COMPILE_PROGRAM_FAILURE: return "Compile Program Failure";
+ case CL_LINKER_NOT_AVAILABLE: return "Linker Not Available";
+ case CL_LINK_PROGRAM_FAILURE: return "Link Program Failure";
+ case CL_DEVICE_PARTITION_FAILED: return "Device Partition Failed";
+ case CL_KERNEL_ARG_INFO_NOT_AVAILABLE: return "Kernel Argument Info Not Available";
+ case CL_INVALID_PROPERTY: return "Invalid Property";
+ case CL_INVALID_IMAGE_DESCRIPTOR: return "Invalid Image Descriptor";
+ case CL_INVALID_COMPILER_OPTIONS: return "Invalid Compiler Options";
+ case CL_INVALID_LINKER_OPTIONS: return "Invalid Linker Options";
+ case CL_INVALID_DEVICE_PARTITION_COUNT: return "Invalid Device Partition Count";
+ #endif // CL_VERSION_1_2
+ #ifdef CL_VERSION_2_0
+ case CL_INVALID_PIPE_SIZE: return "Invalid Pipe Size";
+ case CL_INVALID_DEVICE_QUEUE: return "Invalid Device Queue";
+ #endif
+ default: {
+ std::stringstream s;
+ s << "Unknown OpenCL Error (" << error << ")";
+ return s.str();
+ }
+ }
+ }
+
+private:
+ cl_int m_error;
+ std::string m_error_string;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_EXCEPTION_OPENCL_ERROR_HPP
diff --git a/boost/compute/exception/unsupported_extension_error.hpp b/boost/compute/exception/unsupported_extension_error.hpp
new file mode 100644
index 0000000000..c6f4de6c33
--- /dev/null
+++ b/boost/compute/exception/unsupported_extension_error.hpp
@@ -0,0 +1,71 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_EXCEPTION_UNSUPPORTED_EXTENSION_ERROR_HPP
+#define BOOST_COMPUTE_EXCEPTION_UNSUPPORTED_EXTENSION_ERROR_HPP
+
+#include <exception>
+#include <sstream>
+#include <string>
+
+namespace boost {
+namespace compute {
+
+/// \class unsupported_extension_error
+/// \brief Exception thrown when attempting to use an unsupported
+/// OpenCL extension.
+///
+/// This exception is thrown when the user attempts to use an OpenCL
+/// extension which is not supported on the platform and/or device.
+///
+/// An example of this is attempting to use CL-GL sharing on a non-GPU
+/// device.
+///
+/// \see opencl_error
+class unsupported_extension_error : public std::exception
+{
+public:
+ /// Creates a new unsupported extension error exception object indicating
+ /// that \p extension is not supported by the OpenCL platform or device.
+ explicit unsupported_extension_error(const char *extension) throw()
+ : m_extension(extension)
+ {
+ std::stringstream msg;
+ msg << "OpenCL extension " << extension << " not supported";
+ m_error_string = msg.str();
+ }
+
+ /// Destroys the unsupported extension error object.
+ ~unsupported_extension_error() throw()
+ {
+ }
+
+ /// Returns the name of the unsupported extension.
+ std::string extension_name() const throw()
+ {
+ return m_extension;
+ }
+
+ /// Returns a string containing a human-readable error message containing
+ /// the name of the unsupported exception.
+ const char* what() const throw()
+ {
+ return m_error_string.c_str();
+ }
+
+private:
+ std::string m_extension;
+ std::string m_error_string;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_EXCEPTION_UNSUPPORTED_EXTENSION_ERROR_HPP
diff --git a/boost/compute/experimental/clamp_range.hpp b/boost/compute/experimental/clamp_range.hpp
new file mode 100644
index 0000000000..0c2260498f
--- /dev/null
+++ b/boost/compute/experimental/clamp_range.hpp
@@ -0,0 +1,49 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_EXPERIMENTAL_CLAMP_RANGE_HPP
+#define BOOST_COMPUTE_EXPERIMENTAL_CLAMP_RANGE_HPP
+
+#include <iterator>
+
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+
+namespace boost {
+namespace compute {
+namespace experimental {
+
+template<class InputIterator, class OutputIterator>
+inline OutputIterator
+clamp_range(InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ typename std::iterator_traits<InputIterator>::value_type lo,
+ typename std::iterator_traits<InputIterator>::value_type hi,
+ command_queue &queue)
+{
+ using ::boost::compute::lambda::_1;
+ using ::boost::compute::lambda::_2;
+ using ::boost::compute::lambda::clamp;
+
+ return ::boost::compute::transform(
+ first,
+ last,
+ result,
+ clamp(_1, lo, hi),
+ queue
+ );
+}
+
+} // end experimental namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_EXPERIMENTAL_CLAMP_RANGE_HPP
diff --git a/boost/compute/experimental/malloc.hpp b/boost/compute/experimental/malloc.hpp
new file mode 100644
index 0000000000..ad96888743
--- /dev/null
+++ b/boost/compute/experimental/malloc.hpp
@@ -0,0 +1,51 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_EXPERIMENTAL_MALLOC_HPP
+#define BOOST_COMPUTE_EXPERIMENTAL_MALLOC_HPP
+
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/detail/device_ptr.hpp>
+
+namespace boost {
+namespace compute {
+namespace experimental {
+
+// bring device_ptr into the experimental namespace
+using detail::device_ptr;
+
+template<class T>
+inline device_ptr<T>
+malloc(std::size_t size, const context &context = system::default_context())
+{
+ buffer buf(context, size * sizeof(T));
+ clRetainMemObject(buf.get());
+ return device_ptr<T>(buf);
+}
+
+inline device_ptr<char>
+malloc(std::size_t size, const context &context = system::default_context())
+{
+ return malloc<char>(size, context);
+}
+
+template<class T>
+inline void free(device_ptr<T> &ptr)
+{
+ clReleaseMemObject(ptr.get_buffer().get());
+}
+
+} // end experimental namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_EXPERIMENTAL_MALLOC_HPP
diff --git a/boost/compute/experimental/sort_by_transform.hpp b/boost/compute/experimental/sort_by_transform.hpp
new file mode 100644
index 0000000000..3d84ba9810
--- /dev/null
+++ b/boost/compute/experimental/sort_by_transform.hpp
@@ -0,0 +1,66 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_EXPERIMENTAL_SORT_BY_TRANSFORM_HPP
+#define BOOST_COMPUTE_EXPERIMENTAL_SORT_BY_TRANSFORM_HPP
+
+#include <iterator>
+
+#include <boost/compute/algorithm/sort_by_key.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/type_traits/result_of.hpp>
+
+namespace boost {
+namespace compute {
+namespace experimental {
+
+template<class Iterator, class Transform, class Compare>
+inline void sort_by_transform(Iterator first,
+ Iterator last,
+ Transform transform,
+ Compare compare,
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<Iterator>::value_type value_type;
+ typedef typename boost::compute::result_of<Transform(value_type)>::type key_type;
+
+ size_t n = detail::iterator_range_size(first, last);
+ if(n < 2){
+ return;
+ }
+
+ const context &context = queue.get_context();
+
+ ::boost::compute::vector<key_type> keys(n, context);
+
+ ::boost::compute::transform(
+ first,
+ last,
+ keys.begin(),
+ transform,
+ queue
+ );
+
+ ::boost::compute::sort_by_key(
+ keys.begin(),
+ keys.end(),
+ first,
+ compare,
+ queue
+ );
+}
+
+} // end experimental namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_EXPERIMENTAL_SORT_BY_TRANSFORM_HPP
diff --git a/boost/compute/experimental/tabulate.hpp b/boost/compute/experimental/tabulate.hpp
new file mode 100644
index 0000000000..4f607e7961
--- /dev/null
+++ b/boost/compute/experimental/tabulate.hpp
@@ -0,0 +1,44 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_EXPERIMENTAL_TABULATE_HPP
+#define BOOST_COMPUTE_EXPERIMENTAL_TABULATE_HPP
+
+#include <iterator>
+
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/iterator/counting_iterator.hpp>
+
+namespace boost {
+namespace compute {
+namespace experimental {
+
+template<class Iterator, class UnaryFunction>
+inline void tabulate(Iterator first,
+ Iterator last,
+ UnaryFunction function,
+ command_queue &queue)
+{
+ size_t n = detail::iterator_range_size(first, last);
+
+ ::boost::compute::transform(
+ ::boost::compute::make_counting_iterator<int>(0),
+ ::boost::compute::make_counting_iterator<int>(n),
+ first,
+ function,
+ queue
+ );
+}
+
+} // end experimental namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_EXPERIMENTAL_TABULATE_HPP
diff --git a/boost/compute/function.hpp b/boost/compute/function.hpp
new file mode 100644
index 0000000000..e83f16808a
--- /dev/null
+++ b/boost/compute/function.hpp
@@ -0,0 +1,454 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTION_HPP
+#define BOOST_COMPUTE_FUNCTION_HPP
+
+#include <map>
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/function_types/parameter_types.hpp>
+#include <boost/preprocessor/repetition.hpp>
+#include <boost/mpl/for_each.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/transform.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/type_traits/add_pointer.hpp>
+#include <boost/type_traits/function_traits.hpp>
+
+#include <boost/compute/cl.hpp>
+#include <boost/compute/config.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class ResultType, class ArgTuple>
+class invoked_function
+{
+public:
+ typedef ResultType result_type;
+
+ BOOST_STATIC_CONSTANT(
+ size_t, arity = boost::tuples::length<ArgTuple>::value
+ );
+
+ invoked_function(const std::string &name,
+ const std::string &source)
+ : m_name(name),
+ m_source(source)
+ {
+ }
+
+ invoked_function(const std::string &name,
+ const std::string &source,
+ const std::map<std::string, std::string> &definitions)
+ : m_name(name),
+ m_source(source),
+ m_definitions(definitions)
+ {
+ }
+
+ invoked_function(const std::string &name,
+ const std::string &source,
+ const ArgTuple &args)
+ : m_name(name),
+ m_source(source),
+ m_args(args)
+ {
+ }
+
+ invoked_function(const std::string &name,
+ const std::string &source,
+ const std::map<std::string, std::string> &definitions,
+ const ArgTuple &args)
+ : m_name(name),
+ m_source(source),
+ m_definitions(definitions),
+ m_args(args)
+ {
+ }
+
+ std::string name() const
+ {
+ return m_name;
+ }
+
+ std::string source() const
+ {
+ return m_source;
+ }
+
+ const std::map<std::string, std::string>& definitions() const
+ {
+ return m_definitions;
+ }
+
+ const ArgTuple& args() const
+ {
+ return m_args;
+ }
+
+private:
+ std::string m_name;
+ std::string m_source;
+ std::map<std::string, std::string> m_definitions;
+ ArgTuple m_args;
+};
+
+} // end detail namespace
+
+/// \class function
+/// \brief A function object.
+template<class Signature>
+class function
+{
+public:
+ /// \internal_
+ typedef typename
+ boost::function_traits<Signature>::result_type result_type;
+
+ /// \internal_
+ BOOST_STATIC_CONSTANT(
+ size_t, arity = boost::function_traits<Signature>::arity
+ );
+
+ /// \internal_
+ typedef Signature signature;
+
+ /// Creates a new function object with \p name.
+ function(const std::string &name)
+ : m_name(name)
+ {
+ }
+
+ /// Destroys the function object.
+ ~function()
+ {
+ }
+
+ /// \internal_
+ std::string name() const
+ {
+ return m_name;
+ }
+
+ /// \internal_
+ void set_source(const std::string &source)
+ {
+ m_source = source;
+ }
+
+ /// \internal_
+ std::string source() const
+ {
+ return m_source;
+ }
+
+ /// \internal_
+ void define(std::string name, std::string value = std::string())
+ {
+ m_definitions[name] = value;
+ }
+
+ /// \internal_
+ detail::invoked_function<result_type, boost::tuple<> >
+ operator()() const
+ {
+ BOOST_STATIC_ASSERT_MSG(
+ arity == 0,
+ "Non-nullary function invoked with zero arguments"
+ );
+
+ return detail::invoked_function<result_type, boost::tuple<> >(
+ m_name, m_source, m_definitions
+ );
+ }
+
+ /// \internal_
+ template<class Arg1>
+ detail::invoked_function<result_type, boost::tuple<Arg1> >
+ operator()(const Arg1 &arg1) const
+ {
+ BOOST_STATIC_ASSERT_MSG(
+ arity == 1,
+ "Non-unary function invoked one argument"
+ );
+
+ return detail::invoked_function<result_type, boost::tuple<Arg1> >(
+ m_name, m_source, m_definitions, boost::make_tuple(arg1)
+ );
+ }
+
+ /// \internal_
+ template<class Arg1, class Arg2>
+ detail::invoked_function<result_type, boost::tuple<Arg1, Arg2> >
+ operator()(const Arg1 &arg1, const Arg2 &arg2) const
+ {
+ BOOST_STATIC_ASSERT_MSG(
+ arity == 2,
+ "Non-binary function invoked with two arguments"
+ );
+
+ return detail::invoked_function<result_type, boost::tuple<Arg1, Arg2> >(
+ m_name, m_source, m_definitions, boost::make_tuple(arg1, arg2)
+ );
+ }
+
+ /// \internal_
+ template<class Arg1, class Arg2, class Arg3>
+ detail::invoked_function<result_type, boost::tuple<Arg1, Arg2, Arg3> >
+ operator()(const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) const
+ {
+ BOOST_STATIC_ASSERT_MSG(
+ arity == 3,
+ "Non-ternary function invoked with two arguments"
+ );
+
+ return detail::invoked_function<result_type, boost::tuple<Arg1, Arg2, Arg3> >(
+ m_name, m_source, m_definitions, boost::make_tuple(arg1, arg2, arg3)
+ );
+ }
+
+private:
+ std::string m_name;
+ std::string m_source;
+ std::map<std::string, std::string> m_definitions;
+};
+
+/// Creates a function object given its \p name and \p source.
+///
+/// \param name The function name.
+/// \param source The function source code.
+///
+/// \see BOOST_COMPUTE_FUNCTION()
+template<class Signature>
+inline function<Signature>
+make_function_from_source(const std::string &name, const std::string &source)
+{
+ function<Signature> f(name);
+ f.set_source(source);
+ return f;
+}
+
+namespace detail {
+
+// given a string containing the arguments declaration for a function
+// like: "(int a, const float b)", returns a vector containing the name
+// of each argument (e.g. ["a", "b"]).
+inline std::vector<std::string> parse_argument_names(const char *arguments)
+{
+ BOOST_ASSERT_MSG(
+ arguments[0] == '(' && arguments[std::strlen(arguments)-1] == ')',
+ "Arguments should start and end with parentheses"
+ );
+
+ std::vector<std::string> args;
+
+ size_t last_space = 0;
+ size_t skip_comma = 0;
+ for(size_t i = 1; i < std::strlen(arguments) - 2; i++){
+ const char c = arguments[i];
+
+ if(c == ' '){
+ last_space = i;
+ }
+ else if(c == ',' && !skip_comma){
+ std::string name(
+ arguments + last_space + 1, i - last_space - 1
+ );
+ args.push_back(name);
+ }
+ else if(c == '<'){
+ skip_comma++;
+ }
+ else if(c == '>'){
+ skip_comma--;
+ }
+ }
+
+ std::string last_argument(
+ arguments + last_space + 1, std::strlen(arguments) - last_space - 2
+ );
+ args.push_back(last_argument);
+
+ return args;
+}
+
+struct signature_argument_inserter
+{
+ signature_argument_inserter(std::stringstream &s_, const char *arguments, size_t last)
+ : s(s_)
+ {
+ n = 0;
+ m_last = last;
+
+ m_argument_names = parse_argument_names(arguments);
+
+ BOOST_ASSERT_MSG(
+ m_argument_names.size() == last,
+ "Wrong number of arguments"
+ );
+ }
+
+ template<class T>
+ void operator()(const T*)
+ {
+ s << type_name<T>() << " " << m_argument_names[n];
+ if(n+1 < m_last){
+ s << ", ";
+ }
+ n++;
+ }
+
+ size_t n;
+ size_t m_last;
+ std::stringstream &s;
+ std::vector<std::string> m_argument_names;
+};
+
+template<class Signature>
+inline std::string make_function_declaration(const char *name, const char *arguments)
+{
+ typedef typename
+ boost::function_traits<Signature>::result_type result_type;
+ typedef typename
+ boost::function_types::parameter_types<Signature>::type parameter_types;
+ typedef typename
+ mpl::size<parameter_types>::type arity_type;
+
+ std::stringstream s;
+ s << "inline " << type_name<result_type>() << " " << name;
+ s << "(";
+
+ if(arity_type::value > 0){
+ signature_argument_inserter i(s, arguments, arity_type::value);
+ mpl::for_each<
+ typename mpl::transform<parameter_types, boost::add_pointer<mpl::_1>
+ >::type>(i);
+ }
+
+ s << ")";
+ return s.str();
+}
+
+struct argument_list_inserter
+{
+ argument_list_inserter(std::stringstream &s_, const char first, size_t last)
+ : s(s_)
+ {
+ n = 0;
+ m_last = last;
+ m_name = first;
+ }
+
+ template<class T>
+ void operator()(const T*)
+ {
+ s << type_name<T>() << " " << m_name++;
+ if(n+1 < m_last){
+ s << ", ";
+ }
+ n++;
+ }
+
+ size_t n;
+ size_t m_last;
+ char m_name;
+ std::stringstream &s;
+};
+
+template<class Signature>
+inline std::string generate_argument_list(const char first = 'a')
+{
+ typedef typename
+ boost::function_types::parameter_types<Signature>::type parameter_types;
+ typedef typename
+ mpl::size<parameter_types>::type arity_type;
+
+ std::stringstream s;
+ s << '(';
+
+ if(arity_type::value > 0){
+ argument_list_inserter i(s, first, arity_type::value);
+ mpl::for_each<
+ typename mpl::transform<parameter_types, boost::add_pointer<mpl::_1>
+ >::type>(i);
+ }
+
+ s << ')';
+ return s.str();
+}
+
+// used by the BOOST_COMPUTE_FUNCTION() macro to create a function
+// with the given signature, name, arguments, and source.
+template<class Signature>
+inline function<Signature>
+make_function_impl(const char *name, const char *arguments, const char *source)
+{
+ std::stringstream s;
+ s << make_function_declaration<Signature>(name, arguments);
+ s << source;
+
+ return make_function_from_source<Signature>(name, s.str());
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+/// Creates a function object with \p name and \p source.
+///
+/// \param return_type The return type for the function.
+/// \param name The name of the function.
+/// \param arguments A list of arguments for the function.
+/// \param source The OpenCL C source code for the function.
+///
+/// The function declaration and signature are automatically created using
+/// the \p return_type, \p name, and \p arguments macro parameters.
+///
+/// The source code for the function is interpreted as OpenCL C99 source code
+/// which is stringified and passed to the OpenCL compiler when the function
+/// is invoked.
+///
+/// For example, to create a function which squares a number:
+/// \code
+/// BOOST_COMPUTE_FUNCTION(float, square, (float x),
+/// {
+/// return x * x;
+/// });
+/// \endcode
+///
+/// And to create a function which sums two numbers:
+/// \code
+/// BOOST_COMPUTE_FUNCTION(int, sum_two, (int x, int y),
+/// {
+/// return x + y;
+/// });
+/// \endcode
+///
+/// \see BOOST_COMPUTE_CLOSURE()
+#ifdef BOOST_COMPUTE_DOXYGEN_INVOKED
+#define BOOST_COMPUTE_FUNCTION(return_type, name, arguments, source)
+#else
+#define BOOST_COMPUTE_FUNCTION(return_type, name, arguments, ...) \
+ ::boost::compute::function<return_type arguments> name = \
+ ::boost::compute::detail::make_function_impl<return_type arguments>( \
+ #name, #arguments, #__VA_ARGS__ \
+ )
+#endif
+
+#endif // BOOST_COMPUTE_FUNCTION_HPP
diff --git a/boost/compute/functional.hpp b/boost/compute/functional.hpp
new file mode 100644
index 0000000000..d2065216f4
--- /dev/null
+++ b/boost/compute/functional.hpp
@@ -0,0 +1,34 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_HPP
+
+/// \file
+///
+/// Meta-header to include all Boost.Compute functional headers.
+
+#include <boost/compute/functional/as.hpp>
+#include <boost/compute/functional/atomic.hpp>
+#include <boost/compute/functional/common.hpp>
+#include <boost/compute/functional/convert.hpp>
+#include <boost/compute/functional/field.hpp>
+#include <boost/compute/functional/geometry.hpp>
+#include <boost/compute/functional/get.hpp>
+#include <boost/compute/functional/hash.hpp>
+#include <boost/compute/functional/identity.hpp>
+#include <boost/compute/functional/integer.hpp>
+#include <boost/compute/functional/logical.hpp>
+#include <boost/compute/functional/math.hpp>
+#include <boost/compute/functional/operator.hpp>
+#include <boost/compute/functional/popcount.hpp>
+#include <boost/compute/functional/relational.hpp>
+
+#endif // BOOST_COMPUTE_FUNCTIONAL_HPP
diff --git a/boost/compute/functional/as.hpp b/boost/compute/functional/as.hpp
new file mode 100644
index 0000000000..584bd0f38a
--- /dev/null
+++ b/boost/compute/functional/as.hpp
@@ -0,0 +1,51 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_AS_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_AS_HPP
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class T, class Arg>
+struct invoked_as
+{
+ invoked_as(const Arg &arg)
+ : m_arg(arg)
+ {
+ }
+
+ Arg m_arg;
+};
+
+} // end detail namespace
+
+/// The \ref as function converts its argument to type \c T (similar to
+/// reinterpret_cast<T>).
+///
+/// \see \ref convert "convert<T>"
+template<class T>
+struct as
+{
+ typedef T result_type;
+
+ /// \internal_
+ template<class Arg>
+ detail::invoked_as<T, Arg> operator()(const Arg &arg) const
+ {
+ return detail::invoked_as<T, Arg>(arg);
+ }
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_FUNCTIONAL_AS_HPP
diff --git a/boost/compute/functional/atomic.hpp b/boost/compute/functional/atomic.hpp
new file mode 100644
index 0000000000..2701561bc3
--- /dev/null
+++ b/boost/compute/functional/atomic.hpp
@@ -0,0 +1,141 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_ATOMIC_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_ATOMIC_HPP
+
+#include <boost/compute/cl.hpp>
+#include <boost/compute/function.hpp>
+
+#ifndef BOOST_COMPUTE_DOXYGEN_INVOKED
+#ifdef CL_VERSION_1_1
+ #define BOOST_COMPUTE_DETAIL_ATOMIC_PREFIX "atomic_"
+#else
+ #define BOOST_COMPUTE_DETAIL_ATOMIC_PREFIX "atom_"
+#endif
+#endif // BOOST_COMPUTE_DOXYGEN_INVOKED
+
+namespace boost {
+namespace compute {
+
+template<class T>
+class atomic_add : public function<T (T*, T)>
+{
+public:
+ atomic_add()
+ : function<T (T*, T)>(BOOST_COMPUTE_DETAIL_ATOMIC_PREFIX "add")
+ {
+ }
+};
+
+template<class T>
+class atomic_sub : public function<T (T*, T)>
+{
+public:
+ atomic_sub()
+ : function<T (T*, T)>(BOOST_COMPUTE_DETAIL_ATOMIC_PREFIX "sub")
+ {
+ }
+};
+
+template<class T>
+class atomic_xchg : public function<T (T*, T)>
+{
+public:
+ atomic_xchg()
+ : function<T (T*, T)>(BOOST_COMPUTE_DETAIL_ATOMIC_PREFIX "xchg")
+ {
+ }
+};
+
+template<class T>
+class atomic_inc : public function<T (T*)>
+{
+public:
+ atomic_inc()
+ : function<T (T*)>(BOOST_COMPUTE_DETAIL_ATOMIC_PREFIX "inc")
+ {
+ }
+};
+
+template<class T>
+class atomic_dec : public function<T (T*)>
+{
+public:
+ atomic_dec()
+ : function<T (T*)>(BOOST_COMPUTE_DETAIL_ATOMIC_PREFIX "dec")
+ {
+ }
+};
+
+template<class T>
+class atomic_cmpxchg : public function<T (T*, T, T)>
+{
+public:
+ atomic_cmpxchg()
+ : function<T (T*, T, T)>(BOOST_COMPUTE_DETAIL_ATOMIC_PREFIX "cmpxchg")
+ {
+ }
+};
+
+template<class T>
+class atomic_max : public function<T (T*, T)>
+{
+public:
+ atomic_max()
+ : function<T (T*, T)>(BOOST_COMPUTE_DETAIL_ATOMIC_PREFIX "max")
+ {
+ }
+};
+
+template<class T>
+class atomic_min : public function<T (T*, T)>
+{
+public:
+ atomic_min()
+ : function<T (T*, T)>(BOOST_COMPUTE_DETAIL_ATOMIC_PREFIX "min")
+ {
+ }
+};
+
+template<class T>
+class atomic_and : public function<T (T*, T)>
+{
+public:
+ atomic_and()
+ : function<T (T*, T)>(BOOST_COMPUTE_DETAIL_ATOMIC_PREFIX "and")
+ {
+ }
+};
+
+template<class T>
+class atomic_or : public function<T (T*, T)>
+{
+public:
+ atomic_or()
+ : function<T (T*, T)>(BOOST_COMPUTE_DETAIL_ATOMIC_PREFIX "or")
+ {
+ }
+};
+
+template<class T>
+class atomic_xor : public function<T (T*, T)>
+{
+public:
+ atomic_xor()
+ : function<T (T*, T)>(BOOST_COMPUTE_DETAIL_ATOMIC_PREFIX "xor")
+ {
+ }
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_FUNCTIONAL_ATOMIC_HPP
diff --git a/boost/compute/functional/bind.hpp b/boost/compute/functional/bind.hpp
new file mode 100644
index 0000000000..0c5929f3b9
--- /dev/null
+++ b/boost/compute/functional/bind.hpp
@@ -0,0 +1,261 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_BIND_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_BIND_HPP
+
+#include <boost/mpl/int.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/type_traits/conditional.hpp>
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+
+namespace boost {
+namespace compute {
+namespace placeholders {
+
+/// \internal_
+template<int I>
+struct placeholder : boost::integral_constant<int, I>
+{
+ placeholder() { }
+};
+
+placeholder<0> const _1;
+placeholder<1> const _2;
+
+} // end placeholders namespace
+
+/// Meta-function returning \c true if \c T is a placeholder type.
+template<class T>
+struct is_placeholder : boost::false_type
+{
+};
+
+/// \internal_
+template<int I>
+struct is_placeholder<placeholders::placeholder<I> > : boost::true_type
+{
+};
+
+namespace detail {
+
+template<class Function, class BoundArgs, class Args>
+struct invoked_bound_function
+{
+ invoked_bound_function(Function f, BoundArgs bound_args, Args args)
+ : m_function(f),
+ m_bound_args(bound_args),
+ m_args(args)
+ {
+ }
+
+ // meta-function returning true if the N'th argument is a placeholder
+ template<int N>
+ struct is_placeholder_arg
+ {
+ typedef typename boost::tuples::element<N, BoundArgs>::type nth_bound_arg;
+
+ typedef typename is_placeholder<nth_bound_arg>::type type;
+ static const bool value = is_placeholder<nth_bound_arg>::value;
+ };
+
+ template<class Arg>
+ struct get_arg_type
+ {
+ typedef Arg type;
+ };
+
+ template<int I>
+ struct get_arg_type<placeholders::placeholder<I> >
+ {
+ typedef typename boost::tuples::element<I, Args>::type type;
+ };
+
+ // meta-function returning the type of the N'th argument when invoked
+ template<int N>
+ struct get_nth_arg_type
+ {
+ typedef typename boost::tuples::element<N, BoundArgs>::type nth_bound_arg;
+
+ typedef typename get_arg_type<nth_bound_arg>::type type;
+ };
+
+ template<int N>
+ typename get_nth_arg_type<N>::type get_nth_arg(
+ typename boost::enable_if_c<is_placeholder_arg<N>::value>::type* = 0
+ ) const
+ {
+ typedef typename boost::tuples::element<N, BoundArgs>::type nth_bound_arg;
+
+ return boost::get<nth_bound_arg::value>(m_args);
+ }
+
+ template<int N>
+ typename get_nth_arg_type<N>::type get_nth_arg(
+ typename boost::disable_if_c<is_placeholder_arg<N>::value>::type* = 0
+ ) const
+ {
+ return boost::get<N>(m_bound_args);
+ }
+
+ Function m_function;
+ BoundArgs m_bound_args;
+ Args m_args;
+};
+
+template<class Function, class BoundArgs, class Args>
+inline meta_kernel& apply_invoked_bound_function(
+ meta_kernel &k,
+ const invoked_bound_function<Function, BoundArgs, Args> &expr,
+ typename boost::enable_if_c<
+ boost::tuples::length<BoundArgs>::value == 1
+ >::type* = 0
+)
+{
+ return k << expr.m_function(expr.template get_nth_arg<0>());
+}
+
+template<class Function, class BoundArgs, class Args>
+inline meta_kernel& apply_invoked_bound_function(
+ meta_kernel &k,
+ const invoked_bound_function<Function, BoundArgs, Args> &expr,
+ typename boost::enable_if_c<
+ boost::tuples::length<BoundArgs>::value == 2
+ >::type* = 0
+)
+{
+ return k << expr.m_function(expr.template get_nth_arg<0>(),
+ expr.template get_nth_arg<1>());
+}
+
+template<class Function, class BoundArgs, class Args>
+inline meta_kernel& apply_invoked_bound_function(
+ meta_kernel &k,
+ const invoked_bound_function<Function, BoundArgs, Args> &expr,
+ typename boost::enable_if_c<
+ boost::tuples::length<BoundArgs>::value == 3
+ >::type* = 0
+)
+{
+ return k << expr.m_function(expr.template get_nth_arg<0>(),
+ expr.template get_nth_arg<1>(),
+ expr.template get_nth_arg<2>());
+}
+
+template<class Function, class BoundArgs, class Args>
+inline meta_kernel& operator<<(
+ meta_kernel &k,
+ const invoked_bound_function<Function, BoundArgs, Args> &expr
+)
+{
+ return apply_invoked_bound_function(k, expr);
+}
+
+template<class Function, class BoundArgs>
+struct bound_function
+{
+ typedef int result_type;
+
+ bound_function(Function f, BoundArgs args)
+ : m_function(f),
+ m_args(args)
+ {
+ }
+
+ template<class Arg1>
+ detail::invoked_bound_function<
+ Function,
+ BoundArgs,
+ boost::tuple<Arg1>
+ >
+ operator()(const Arg1 &arg1) const
+ {
+ return detail::invoked_bound_function<
+ Function,
+ BoundArgs,
+ boost::tuple<Arg1>
+ >(m_function, m_args, boost::make_tuple(arg1));
+ }
+
+ template<class Arg1, class Arg2>
+ detail::invoked_bound_function<
+ Function,
+ BoundArgs,
+ boost::tuple<Arg1, Arg2>
+ >
+ operator()(const Arg1 &arg1, const Arg2 &arg2) const
+ {
+ return detail::invoked_bound_function<
+ Function,
+ BoundArgs,
+ boost::tuple<Arg1, Arg2>
+ >(m_function, m_args, boost::make_tuple(arg1, arg2));
+ }
+
+ Function m_function;
+ BoundArgs m_args;
+};
+
+} // end detail namespace
+
+#if !defined(BOOST_COMPUTE_NO_VARIADIC_TEMPLATES) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+/// Returns a function wrapper which invokes \p f with \p args when called.
+///
+/// For example, to generate a unary function object which returns \c true
+/// when its argument is less than \c 7:
+/// \code
+/// using boost::compute::less;
+/// using boost::compute::placeholders::_1;
+///
+/// auto less_than_seven = boost::compute::bind(less<int>(), _1, 7);
+/// \endcode
+template<class F, class... Args>
+inline detail::bound_function<F, boost::tuple<Args...> >
+bind(F f, Args... args)
+{
+ typedef typename boost::tuple<Args...> ArgsTuple;
+
+ return detail::bound_function<F, ArgsTuple>(f, boost::make_tuple(args...));
+}
+#else
+template<class F, class A1>
+inline detail::bound_function<F, boost::tuple<A1> >
+bind(F f, A1 a1)
+{
+ typedef typename boost::tuple<A1> Args;
+
+ return detail::bound_function<F, Args>(f, boost::make_tuple(a1));
+}
+
+template<class F, class A1, class A2>
+inline detail::bound_function<F, boost::tuple<A1, A2> >
+bind(F f, A1 a1, A2 a2)
+{
+ typedef typename boost::tuple<A1, A2> Args;
+
+ return detail::bound_function<F, Args>(f, boost::make_tuple(a1, a2));
+}
+
+template<class F, class A1, class A2, class A3>
+inline detail::bound_function<F, boost::tuple<A1, A2, A3> >
+bind(F f, A1 a1, A2 a2, A3 a3)
+{
+ typedef typename boost::tuple<A1, A2, A3> Args;
+
+ return detail::bound_function<F, Args>(f, boost::make_tuple(a1, a2, a3));
+}
+#endif // BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_FUNCTIONAL_BIND_HPP
diff --git a/boost/compute/functional/common.hpp b/boost/compute/functional/common.hpp
new file mode 100644
index 0000000000..9ad8b43502
--- /dev/null
+++ b/boost/compute/functional/common.hpp
@@ -0,0 +1,29 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_COMMON_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_COMMON_HPP
+
+#include <boost/compute/functional/detail/macros.hpp>
+
+namespace boost {
+namespace compute {
+
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(clamp, T (T, T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(degrees, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(radians, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(sign, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(smoothstep, T (T, T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(step, T (T, T), class T)
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_FUNCTIONAL_COMMON_HPP
diff --git a/boost/compute/functional/convert.hpp b/boost/compute/functional/convert.hpp
new file mode 100644
index 0000000000..f182e8ec72
--- /dev/null
+++ b/boost/compute/functional/convert.hpp
@@ -0,0 +1,51 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_CONVERT_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_CONVERT_HPP
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class T, class Arg>
+struct invoked_convert
+{
+ invoked_convert(const Arg &arg)
+ : m_arg(arg)
+ {
+ }
+
+ Arg m_arg;
+};
+
+} // end detail namespace
+
+/// The \ref convert function converts its argument to type \c T (similar to
+/// static_cast<T>).
+///
+/// \see \ref as "as<T>"
+template<class T>
+struct convert
+{
+ typedef T result_type;
+
+ /// \internal_
+ template<class Arg>
+ detail::invoked_convert<T, Arg> operator()(const Arg &arg) const
+ {
+ return detail::invoked_convert<T, Arg>(arg);
+ }
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_FUNCTIONAL_CONVERT_HPP
diff --git a/boost/compute/functional/detail/macros.hpp b/boost/compute/functional/detail/macros.hpp
new file mode 100644
index 0000000000..71ae3722e5
--- /dev/null
+++ b/boost/compute/functional/detail/macros.hpp
@@ -0,0 +1,35 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_MACROS_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_MACROS_HPP
+
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/stringize.hpp>
+
+#include <boost/compute/function.hpp>
+
+#define BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(name, signature, template_args) \
+ template<template_args> \
+ class name : public function<signature> \
+ { \
+ public: \
+ (name)() : function<signature>(BOOST_PP_STRINGIZE(name)) { } \
+ };
+
+#define BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION_UNDERSCORE(name, signature, template_args) \
+ template<template_args> \
+ class BOOST_PP_CAT(name, _) : public function<signature> \
+ { \
+ public: \
+ BOOST_PP_CAT(name, _)() : function<signature>(BOOST_PP_STRINGIZE(name)) { } \
+ };
+
+#endif // BOOST_COMPUTE_FUNCTIONAL_MACROS_HPP
diff --git a/boost/compute/functional/detail/nvidia_ballot.hpp b/boost/compute/functional/detail/nvidia_ballot.hpp
new file mode 100644
index 0000000000..cf66828f1c
--- /dev/null
+++ b/boost/compute/functional/detail/nvidia_ballot.hpp
@@ -0,0 +1,48 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_DETAIL_NVIDIA_BALLOT_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_DETAIL_NVIDIA_BALLOT_HPP
+
+#include <boost/compute/function.hpp>
+#include <boost/compute/types/fundamental.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class T>
+class nvidia_ballot : public function<uint_(T)>
+{
+public:
+ nvidia_ballot()
+ : function<uint_(T)>("nvidia_ballot")
+ {
+ this->set_source(
+ "inline uint nvidia_ballot(const uint x)\n"
+ "{\n"
+ " uint result;\n"
+ " asm volatile(\n"
+ " \"setp.ne.u32 %%p1, %1, 0;\"\n"
+ " \"vote.ballot.b32 %0, %%p1;\"\n"
+ " : \"=r\"(result)\n"
+ " : \"r\"(x)\n"
+ " );\n"
+ " return result;\n"
+ "}\n"
+ );
+ }
+};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_FUNCTIONAL_DETAIL_NVIDIA_BALLOT_HPP
diff --git a/boost/compute/functional/detail/nvidia_popcount.hpp b/boost/compute/functional/detail/nvidia_popcount.hpp
new file mode 100644
index 0000000000..b042ea4ba9
--- /dev/null
+++ b/boost/compute/functional/detail/nvidia_popcount.hpp
@@ -0,0 +1,42 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_DETAIL_NVIDIA_POPCOUNT_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_DETAIL_NVIDIA_POPCOUNT_HPP
+
+#include <boost/compute/function.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class T>
+class nvidia_popcount : public function<T(T)>
+{
+public:
+ nvidia_popcount()
+ : function<T(T)>("nvidia_popcount")
+ {
+ this->set_source(
+ "inline uint nvidia_popcount(const uint x)\n"
+ "{\n"
+ " uint count;\n"
+ " asm(\"popc.b32 %0, %1;\" : \"=r\"(count) : \"r\"(x));\n"
+ " return count;\n"
+ "}\n"
+ );
+ }
+};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_FUNCTIONAL_DETAIL_NVIDIA_POPCOUNT_HPP
diff --git a/boost/compute/functional/detail/unpack.hpp b/boost/compute/functional/detail/unpack.hpp
new file mode 100644
index 0000000000..e64672f142
--- /dev/null
+++ b/boost/compute/functional/detail/unpack.hpp
@@ -0,0 +1,143 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_DETAIL_UNPACK_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_DETAIL_UNPACK_HPP
+
+#include <boost/compute/functional/get.hpp>
+#include <boost/compute/type_traits/is_vector_type.hpp>
+#include <boost/compute/type_traits/result_of.hpp>
+#include <boost/compute/type_traits/vector_size.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class Function, class Arg, size_t Arity>
+struct invoked_unpacked
+{
+ invoked_unpacked(const Function &f, const Arg &arg)
+ : m_function(f),
+ m_arg(arg)
+ {
+ }
+
+ Function m_function;
+ Arg m_arg;
+};
+
+template<class Function, class Arg, size_t Arity>
+inline meta_kernel& operator<<(meta_kernel &k, const invoked_unpacked<Function, Arg, Arity> &expr);
+
+template<class Function, class Arg>
+inline meta_kernel& operator<<(meta_kernel &k, const invoked_unpacked<Function, Arg, 1> &expr)
+{
+ return k << expr.m_function(get<0>()(expr.m_arg));
+}
+
+template<class Function, class Arg>
+inline meta_kernel& operator<<(meta_kernel &k, const invoked_unpacked<Function, Arg, 2> &expr)
+{
+ return k << expr.m_function(get<0>()(expr.m_arg), get<1>()(expr.m_arg));
+}
+
+template<class Function, class Arg>
+inline meta_kernel& operator<<(meta_kernel &k, const invoked_unpacked<Function, Arg, 3> &expr)
+{
+ return k << expr.m_function(get<0>()(expr.m_arg), get<1>()(expr.m_arg), get<2>()(expr.m_arg));
+}
+
+template<class Function>
+struct unpacked
+{
+ template<class T, class Enable = void>
+ struct aggregate_length
+ {
+ BOOST_STATIC_CONSTANT(size_t, value = boost::tuples::length<T>::value);
+ };
+
+ template<class T>
+ struct aggregate_length<T, typename enable_if<is_vector_type<T> >::type>
+ {
+ BOOST_STATIC_CONSTANT(size_t, value = vector_size<T>::value);
+ };
+
+ template<class TupleArg, size_t TupleSize>
+ struct result_impl {};
+
+ template<class TupleArg>
+ struct result_impl<TupleArg, 1>
+ {
+ typedef typename detail::get_result_type<0, TupleArg>::type T1;
+
+ typedef typename boost::compute::result_of<Function(T1)>::type type;
+ };
+
+ template<class TupleArg>
+ struct result_impl<TupleArg, 2>
+ {
+ typedef typename detail::get_result_type<0, TupleArg>::type T1;
+ typedef typename detail::get_result_type<1, TupleArg>::type T2;
+
+ typedef typename boost::compute::result_of<Function(T1, T2)>::type type;
+ };
+
+ template<class TupleArg>
+ struct result_impl<TupleArg, 3>
+ {
+ typedef typename detail::get_result_type<0, TupleArg>::type T1;
+ typedef typename detail::get_result_type<1, TupleArg>::type T2;
+ typedef typename detail::get_result_type<2, TupleArg>::type T3;
+
+ typedef typename boost::compute::result_of<Function(T1, T2, T3)>::type type;
+ };
+
+ template<class Signature>
+ struct result {};
+
+ template<class This, class Arg>
+ struct result<This(Arg)>
+ {
+ typedef typename result_impl<Arg, aggregate_length<Arg>::value>::type type;
+ };
+
+ unpacked(const Function &f)
+ : m_function(f)
+ {
+ }
+
+ template<class Arg>
+ detail::invoked_unpacked<
+ Function, Arg, aggregate_length<typename Arg::result_type>::value
+ >
+ operator()(const Arg &arg) const
+ {
+ return detail::invoked_unpacked<
+ Function,
+ Arg,
+ aggregate_length<typename Arg::result_type>::value
+ >(m_function, arg);
+ }
+
+ Function m_function;
+};
+
+template<class Function>
+inline unpacked<Function> unpack(const Function &f)
+{
+ return unpacked<Function>(f);
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_FUNCTIONAL_DETAIL_UNPACK_HPP
diff --git a/boost/compute/functional/field.hpp b/boost/compute/functional/field.hpp
new file mode 100644
index 0000000000..cd9d81541c
--- /dev/null
+++ b/boost/compute/functional/field.hpp
@@ -0,0 +1,86 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_FIELD_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_FIELD_HPP
+
+#include <string>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class T, class Arg>
+struct invoked_field
+{
+ typedef T result_type;
+
+ invoked_field(const Arg &arg, const std::string &field)
+ : m_arg(arg),
+ m_field(field)
+ {
+ }
+
+ Arg m_arg;
+ std::string m_field;
+};
+
+} // end detail namespace
+
+/// Returns the named field from a value.
+///
+/// The template-type \c T specifies the field's value type. Note
+/// that the value type must match the actual type of the field
+/// otherwise runtime compilation or logic errors may occur.
+///
+/// For example, to access the \c second field in a
+/// \c std::pair<int, float> object:
+/// \code
+/// field<float>("second");
+/// \endcode
+///
+/// This can also be used with vector types to access individual
+/// components as well as perform swizzle operations.
+///
+/// For example, to access the first and third components of an
+/// \c int vector type (e.g. \c int4):
+/// \code
+/// field<int2_>("xz");
+/// \endcode
+///
+/// \see \ref get "get<N>"
+template<class T>
+class field
+{
+public:
+ /// Result type.
+ typedef T result_type;
+
+ /// Creates a new field functor with \p field.
+ field(const std::string &field)
+ : m_field(field)
+ {
+ }
+
+ /// \internal_
+ template<class Arg>
+ detail::invoked_field<T, Arg> operator()(const Arg &arg) const
+ {
+ return detail::invoked_field<T, Arg>(arg, m_field);
+ }
+
+private:
+ std::string m_field;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_FUNCTIONAL_FIELD_HPP
diff --git a/boost/compute/functional/geometry.hpp b/boost/compute/functional/geometry.hpp
new file mode 100644
index 0000000000..ea37c02bfe
--- /dev/null
+++ b/boost/compute/functional/geometry.hpp
@@ -0,0 +1,32 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_GEOMETRY_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_GEOMETRY_HPP
+
+#include <boost/compute/type_traits.hpp>
+#include <boost/compute/functional/detail/macros.hpp>
+
+namespace boost {
+namespace compute {
+
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(cross, T (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(dot, typename scalar_type<T>::type (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(distance, typename scalar_type<T>::type (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(fast_distance, typename scalar_type<T>::type (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(length, typename scalar_type<T>::type (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(fast_length, typename scalar_type<T>::type (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(normalize, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(fast_normalize, T (T), class T)
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_FUNCTIONAL_GEOMETRY_HPP
diff --git a/boost/compute/functional/get.hpp b/boost/compute/functional/get.hpp
new file mode 100644
index 0000000000..2d3b7a489c
--- /dev/null
+++ b/boost/compute/functional/get.hpp
@@ -0,0 +1,76 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_GET_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_GET_HPP
+
+#include <cstddef>
+
+#include <boost/compute/types/fundamental.hpp>
+#include <boost/compute/type_traits/scalar_type.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+// meta-function returning the result type for get<N>()
+template<size_t N, class Arg>
+struct get_result_type
+{
+ typedef typename scalar_type<Arg>::type type;
+};
+
+template<size_t N, class Arg, class T>
+struct invoked_get
+{
+ typedef typename get_result_type<N, T>::type result_type;
+
+ invoked_get(const Arg &arg)
+ : m_arg(arg)
+ {
+ }
+
+ Arg m_arg;
+};
+
+} // end detail namespace
+
+/// Returns the \c N'th element of an aggregate type (e.g. scalarN,
+/// pair, tuple, etc.).
+///
+/// \see \ref field "field<T>"
+template<size_t N>
+struct get
+{
+ /// \internal_
+ template<class> struct result;
+
+ /// \internal_
+ template<class F, class Arg>
+ struct result<F(Arg)>
+ {
+ typedef typename detail::get_result_type<N, Arg>::type type;
+ };
+
+ template<class Arg>
+ detail::invoked_get<
+ N, Arg, typename boost::remove_cv<typename Arg::result_type>::type
+ > operator()(const Arg &arg) const
+ {
+ typedef typename boost::remove_cv<typename Arg::result_type>::type T;
+
+ return detail::invoked_get<N, Arg, T>(arg);
+ }
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_FUNCTIONAL_GET_HPP
diff --git a/boost/compute/functional/hash.hpp b/boost/compute/functional/hash.hpp
new file mode 100644
index 0000000000..830c422fdb
--- /dev/null
+++ b/boost/compute/functional/hash.hpp
@@ -0,0 +1,91 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_HASH_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_HASH_HPP
+
+#include <boost/compute/function.hpp>
+#include <boost/compute/types/fundamental.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class Key>
+std::string make_hash_function_name()
+{
+ return std::string("boost_hash_") + type_name<Key>();
+}
+
+template<class Key>
+inline std::string make_hash_function_source()
+{
+ std::stringstream source;
+ source << "inline ulong " << make_hash_function_name<Key>()
+ << "(const " << type_name<Key>() << " x)\n"
+ << "{\n"
+ // note we reinterpret the argument as a 32-bit uint and
+ // then promote it to a 64-bit ulong for the result type
+ << " ulong a = as_uint(x);\n"
+ << " a = (a ^ 61) ^ (a >> 16);\n"
+ << " a = a + (a << 3);\n"
+ << " a = a ^ (a >> 4);\n"
+ << " a = a * 0x27d4eb2d;\n"
+ << " a = a ^ (a >> 15);\n"
+ << " return a;\n"
+ << "}\n";
+ return source.str();
+}
+
+template<class Key>
+struct hash_impl
+{
+ typedef Key argument_type;
+ typedef ulong_ result_type;
+
+ hash_impl()
+ : m_function("")
+ {
+ m_function = make_function_from_source<result_type(argument_type)>(
+ make_hash_function_name<argument_type>(),
+ make_hash_function_source<argument_type>()
+ );
+ }
+
+ template<class Arg>
+ invoked_function<result_type, boost::tuple<Arg> >
+ operator()(const Arg &arg) const
+ {
+ return m_function(arg);
+ }
+
+ function<result_type(argument_type)> m_function;
+};
+
+} // end detail namespace
+
+/// The hash function returns a hash value for the input value.
+///
+/// The return type is \c ulong_ (the OpenCL unsigned long type).
+template<class Key> struct hash;
+
+/// \internal_
+template<> struct hash<int_> : detail::hash_impl<int_> { };
+
+/// \internal_
+template<> struct hash<uint_> : detail::hash_impl<uint_> { };
+
+/// \internal_
+template<> struct hash<float_> : detail::hash_impl<float_> { };
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_FUNCTIONAL_HASH_HPP
diff --git a/boost/compute/functional/identity.hpp b/boost/compute/functional/identity.hpp
new file mode 100644
index 0000000000..72740d9788
--- /dev/null
+++ b/boost/compute/functional/identity.hpp
@@ -0,0 +1,64 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_IDENTITY_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_IDENTITY_HPP
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class T, class Arg>
+struct invoked_identity
+{
+ typedef T result_type;
+
+ invoked_identity(const Arg &arg)
+ : m_arg(arg)
+ {
+ }
+
+ Arg m_arg;
+};
+
+} // end detail namespace
+
+/// Identity function which simply returns its input.
+///
+/// For example, to directly copy values using the transform() algorithm:
+/// \code
+/// transform(input.begin(), input.end(), output.begin(), identity<int>(), queue);
+/// \endcode
+///
+/// \see \ref as "as<T>", \ref convert "convert<T>"
+template<class T>
+class identity
+{
+public:
+ /// Identity function result type.
+ typedef T result_type;
+
+ /// Creates a new identity function.
+ identity()
+ {
+ }
+
+ /// \internal_
+ template<class Arg>
+ detail::invoked_identity<T, Arg> operator()(const Arg &arg) const
+ {
+ return detail::invoked_identity<T, Arg>(arg);
+ }
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_FUNCTIONAL_IDENTITY_HPP
diff --git a/boost/compute/functional/integer.hpp b/boost/compute/functional/integer.hpp
new file mode 100644
index 0000000000..8ff6c2bd4a
--- /dev/null
+++ b/boost/compute/functional/integer.hpp
@@ -0,0 +1,30 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_INTEGER_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_INTEGER_HPP
+
+#include <boost/compute/functional/detail/macros.hpp>
+
+namespace boost {
+namespace compute {
+
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(abs, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(abs_diff, T (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(add_sat, T (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(hadd, T (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(rhadd, T (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(max, T (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(min, T (T, T), class T)
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_FUNCTIONAL_INTEGER_HPP
diff --git a/boost/compute/functional/logical.hpp b/boost/compute/functional/logical.hpp
new file mode 100644
index 0000000000..2e2c7518b5
--- /dev/null
+++ b/boost/compute/functional/logical.hpp
@@ -0,0 +1,208 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_LOGICAL_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_LOGICAL_HPP
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class Predicate, class Expr>
+class invoked_unary_negate_function
+{
+public:
+ typedef int result_type;
+
+ invoked_unary_negate_function(const Predicate &pred,
+ const Expr &expr)
+ : m_pred(pred),
+ m_expr(expr)
+ {
+ }
+
+ Predicate pred() const
+ {
+ return m_pred;
+ }
+
+ Expr expr() const
+ {
+ return m_expr;
+ }
+
+private:
+ Predicate m_pred;
+ Expr m_expr;
+};
+
+template<class Predicate, class Expr1, class Expr2>
+class invoked_binary_negate_function
+{
+public:
+ typedef int result_type;
+
+ invoked_binary_negate_function(const Predicate &pred,
+ const Expr1 &expr1,
+ const Expr2 &expr2)
+ : m_pred(pred),
+ m_expr1(expr1),
+ m_expr2(expr2)
+ {
+ }
+
+ Predicate pred() const
+ {
+ return m_pred;
+ }
+
+ Expr1 expr1() const
+ {
+ return m_expr1;
+ }
+
+ Expr2 expr2() const
+ {
+ return m_expr2;
+ }
+
+private:
+ Predicate m_pred;
+ Expr1 m_expr1;
+ Expr2 m_expr2;
+};
+
+} // end detail namespace
+
+/// \internal_
+template<class Arg, class Result>
+struct unary_function
+{
+ typedef Arg argument_type;
+ typedef Result result_type;
+};
+
+/// \internal_
+template<class Arg1, class Arg2, class Result>
+struct binary_function
+{
+ typedef Arg1 first_argument_type;
+ typedef Arg2 second_argument_type;
+ typedef Result result_type;
+};
+
+/// \internal_
+template<class Arg1, class Arg2, class Arg3, class Result>
+struct ternary_function
+{
+ typedef Arg1 first_argument_type;
+ typedef Arg2 second_argument_type;
+ typedef Arg3 third_argument_type;
+ typedef Result result_type;
+};
+
+/// The unary_negate function adaptor negates a unary function.
+///
+/// \see not1()
+template<class Predicate>
+class unary_negate : public unary_function<void, int>
+{
+public:
+ explicit unary_negate(Predicate pred)
+ : m_pred(pred)
+ {
+ }
+
+ /// \internal_
+ template<class Arg>
+ detail::invoked_unary_negate_function<Predicate, Arg>
+ operator()(const Arg &arg) const
+ {
+ return detail::invoked_unary_negate_function<
+ Predicate,
+ Arg
+ >(m_pred, arg);
+ }
+
+private:
+ Predicate m_pred;
+};
+
+/// The binnary_negate function adaptor negates a binary function.
+///
+/// \see not2()
+template<class Predicate>
+class binary_negate : public binary_function<void, void, int>
+{
+public:
+ explicit binary_negate(Predicate pred)
+ : m_pred(pred)
+ {
+ }
+
+ /// \internal_
+ template<class Arg1, class Arg2>
+ detail::invoked_binary_negate_function<Predicate, Arg1, Arg2>
+ operator()(const Arg1 &arg1, const Arg2 &arg2) const
+ {
+ return detail::invoked_binary_negate_function<
+ Predicate,
+ Arg1,
+ Arg2
+ >(m_pred, arg1, arg2);
+ }
+
+private:
+ Predicate m_pred;
+};
+
+/// Returns a unary_negate adaptor around \p predicate.
+///
+/// \param predicate the unary function to wrap
+///
+/// \return a unary_negate wrapper around \p predicate
+template<class Predicate>
+inline unary_negate<Predicate> not1(const Predicate &predicate)
+{
+ return unary_negate<Predicate>(predicate);
+}
+
+/// Returns a binary_negate adaptor around \p predicate.
+///
+/// \param predicate the binary function to wrap
+///
+/// \return a binary_negate wrapper around \p predicate
+template<class Predicate>
+inline binary_negate<Predicate> not2(const Predicate &predicate)
+{
+ return binary_negate<Predicate>(predicate);
+}
+
+/// The logical_not function negates its argument and returns it.
+///
+/// \see not1(), not2()
+template<class T>
+struct logical_not : public unary_function<T, int>
+{
+ /// \internal_
+ template<class Expr>
+ detail::invoked_function<int, boost::tuple<Expr> >
+ operator()(const Expr &expr) const
+ {
+ return detail::invoked_function<int, boost::tuple<Expr> >(
+ "!", std::string(), boost::make_tuple(expr)
+ );
+ }
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_FUNCTIONAL_LOGICAL_HPP
diff --git a/boost/compute/functional/math.hpp b/boost/compute/functional/math.hpp
new file mode 100644
index 0000000000..6dea05f6f2
--- /dev/null
+++ b/boost/compute/functional/math.hpp
@@ -0,0 +1,80 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_MATH_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_MATH_HPP
+
+#include <boost/compute/functional/detail/macros.hpp>
+
+namespace boost {
+namespace compute {
+
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(acos, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(acosh, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(acospi, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(asin, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(asinh, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(asinpi, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(atan, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(atan2, T (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(atanh, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(atanpi, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(atan2pi, T (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(cbrt, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(ceil, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(copysign, T (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(cos, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(cosh, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(cospi, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(erf, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(erfc, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(exp, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(exp2, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(exp10, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(expm1, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(fabs, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(fdim, T (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(floor, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(fma, T (T, T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(fmax, T (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(fmin, T (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(fmod, T (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(hypot, T (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(ilogb, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(lgamma, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(log, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(log2, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(log10, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(log1p, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(logb, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(mad, T (T, T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(nextafter, T (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(pow, T (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(pown, T (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(powr, T (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(remainder, T (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(rint, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(rootn, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(round, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(rsqrt, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(sin, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(sinh, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(sinpi, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(sqrt, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(tan, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(tanh, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(tanpi, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(tgamma, T (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(trunc, T (T), class T)
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_FUNCTIONAL_MATH_HPP
diff --git a/boost/compute/functional/operator.hpp b/boost/compute/functional/operator.hpp
new file mode 100644
index 0000000000..908372a326
--- /dev/null
+++ b/boost/compute/functional/operator.hpp
@@ -0,0 +1,100 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_OPERATORS_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_OPERATORS_HPP
+
+#include <string>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class Expr1, class Expr2, class Result>
+struct invoked_binary_operator
+{
+ typedef Result result_type;
+
+ invoked_binary_operator(const std::string &op,
+ const Expr1 &arg1,
+ const Expr2 &arg2)
+ : m_op(op),
+ m_expr1(arg1),
+ m_expr2(arg2)
+ {
+ }
+
+ std::string op() const
+ {
+ return m_op;
+ }
+
+ Expr1 arg1() const
+ {
+ return m_expr1;
+ }
+
+ Expr2 arg2() const
+ {
+ return m_expr2;
+ }
+
+ std::string m_op;
+ Expr1 m_expr1;
+ Expr2 m_expr2;
+};
+
+} // end detail namespace
+
+/// \internal_
+#define BOOST_COMPUTE_DECLARE_BINARY_OPERATOR(name, op, return_type, arg_type) \
+ template<class arg_type> \
+ class name : public function<return_type (arg_type, arg_type)> \
+ { \
+ public: \
+ name() : function<return_type (arg_type, arg_type)>(BOOST_PP_STRINGIZE(name)) { } \
+ \
+ template<class Arg1, class Arg2> \
+ detail::invoked_binary_operator<Arg1, Arg2, T> \
+ operator()(const Arg1 &x, const Arg2 &y) const \
+ { \
+ return detail::invoked_binary_operator<Arg1, Arg2, T>(op, x, y); \
+ } \
+ };
+
+// arithmetic operations
+BOOST_COMPUTE_DECLARE_BINARY_OPERATOR(plus, "+", T, T)
+BOOST_COMPUTE_DECLARE_BINARY_OPERATOR(minus, "-", T, T)
+BOOST_COMPUTE_DECLARE_BINARY_OPERATOR(multiplies, "*", T, T)
+BOOST_COMPUTE_DECLARE_BINARY_OPERATOR(divides, "/", T, T)
+BOOST_COMPUTE_DECLARE_BINARY_OPERATOR(modulus, "%", T, T)
+
+// comparisons
+BOOST_COMPUTE_DECLARE_BINARY_OPERATOR(equal_to, "==", T, T)
+BOOST_COMPUTE_DECLARE_BINARY_OPERATOR(not_equal_to, "!=", T, T)
+BOOST_COMPUTE_DECLARE_BINARY_OPERATOR(greater, ">", T, T)
+BOOST_COMPUTE_DECLARE_BINARY_OPERATOR(less, "<", T, T)
+BOOST_COMPUTE_DECLARE_BINARY_OPERATOR(greater_equal, ">=", T, T)
+BOOST_COMPUTE_DECLARE_BINARY_OPERATOR(less_equal, "<=", T, T)
+
+// logical operators
+BOOST_COMPUTE_DECLARE_BINARY_OPERATOR(logical_and, "&&", T, T)
+BOOST_COMPUTE_DECLARE_BINARY_OPERATOR(logical_or, "||", T, T)
+
+// bitwise operations
+BOOST_COMPUTE_DECLARE_BINARY_OPERATOR(bit_and, "&", T, T)
+BOOST_COMPUTE_DECLARE_BINARY_OPERATOR(bit_or, "|", T, T)
+BOOST_COMPUTE_DECLARE_BINARY_OPERATOR(bit_xor, "^", T, T)
+BOOST_COMPUTE_DECLARE_BINARY_OPERATOR(shift_left, "<<", T, T)
+BOOST_COMPUTE_DECLARE_BINARY_OPERATOR(shift_right, ">>", T, T)
+
+} // end compute namespace
+} // end boost namespace
+#endif // BOOST_COMPUTE_FUNCTIONAL_OPERATORS_HPP
diff --git a/boost/compute/functional/popcount.hpp b/boost/compute/functional/popcount.hpp
new file mode 100644
index 0000000000..7326e7022f
--- /dev/null
+++ b/boost/compute/functional/popcount.hpp
@@ -0,0 +1,55 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_POPCOUNT_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_POPCOUNT_HPP
+
+#include <boost/compute/function.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns the number of non-zero bits in \p x.
+///
+/// \see_opencl_ref{popcount}
+template<class T>
+class popcount : public function<T(T)>
+{
+public:
+ popcount()
+ : function<T(T)>("boost_popcount")
+ {
+ std::stringstream s;
+ s << "inline " << type_name<T>() << " boost_popcount"
+ << "(const " << type_name<T>() << " x)\n"
+ << "{\n"
+ // use built-in popcount if opencl 1.2 is supported
+ << "#if __OPENCL_VERSION__ >= 120\n"
+ << " return popcount(x);\n"
+ // fallback to generic popcount() implementation
+ << "#else\n"
+ << " " << type_name<T>() << " count = 0;\n"
+ << " for(" << type_name<T>() << " i = 0; i < sizeof(i) * CHAR_BIT; i++){\n"
+ << " if(x & (" << type_name<T>() << ") 1 << i){\n"
+ << " count++;\n"
+ << " }\n"
+ << " }\n"
+ << " return count;\n"
+ << "#endif\n"
+ << "}\n";
+ this->set_source(s.str());
+ }
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_FUNCTIONAL_POPCOUNT_HPP
diff --git a/boost/compute/functional/relational.hpp b/boost/compute/functional/relational.hpp
new file mode 100644
index 0000000000..1a88052c05
--- /dev/null
+++ b/boost/compute/functional/relational.hpp
@@ -0,0 +1,39 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_FUNCTIONAL_RELATIONAL_HPP
+#define BOOST_COMPUTE_FUNCTIONAL_RELATIONAL_HPP
+
+#include <boost/compute/functional/detail/macros.hpp>
+
+namespace boost {
+namespace compute {
+
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION_UNDERSCORE(isequal, int (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION_UNDERSCORE(isnotequal, int (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION_UNDERSCORE(isgreater, int (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION_UNDERSCORE(isgreaterequal, int (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION_UNDERSCORE(isless, int (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION_UNDERSCORE(islessequal, int (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION_UNDERSCORE(islessgreater, int (T, T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION_UNDERSCORE(isfinite, int (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION_UNDERSCORE(isinf, int (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION_UNDERSCORE(isnan, int (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION_UNDERSCORE(isnormal, int (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION_UNDERSCORE(isordered, int (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION_UNDERSCORE(isunordered, int (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION_UNDERSCORE(signbit, int (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(any, int (T), class T)
+BOOST_COMPUTE_DECLARE_BUILTIN_FUNCTION(all, int (T), class T)
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_FUNCTIONAL_RELATIONAL_HPP
diff --git a/boost/compute/image.hpp b/boost/compute/image.hpp
new file mode 100644
index 0000000000..1a7b9ca061
--- /dev/null
+++ b/boost/compute/image.hpp
@@ -0,0 +1,25 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_IMAGE_HPP
+#define BOOST_COMPUTE_IMAGE_HPP
+
+/// \file
+///
+/// Meta-header to include all Boost.Compute image headers.
+
+#include <boost/compute/image/image1d.hpp>
+#include <boost/compute/image/image2d.hpp>
+#include <boost/compute/image/image3d.hpp>
+#include <boost/compute/image/image_format.hpp>
+#include <boost/compute/image/image_object.hpp>
+#include <boost/compute/image/image_sampler.hpp>
+
+#endif // BOOST_COMPUTE_IMAGE_HPP
diff --git a/boost/compute/image/image1d.hpp b/boost/compute/image/image1d.hpp
new file mode 100644
index 0000000000..2d71934ab4
--- /dev/null
+++ b/boost/compute/image/image1d.hpp
@@ -0,0 +1,204 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_IMAGE_IMAGE1D_HPP
+#define BOOST_COMPUTE_IMAGE_IMAGE1D_HPP
+
+#include <boost/throw_exception.hpp>
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/exception/opencl_error.hpp>
+#include <boost/compute/image/image_format.hpp>
+#include <boost/compute/image/image_object.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/utility/extents.hpp>
+
+namespace boost {
+namespace compute {
+
+// forward declarations
+class command_queue;
+
+/// \class image1d
+/// \brief An OpenCL 1D image object
+///
+/// \opencl_version_warning{1,2}
+///
+/// \see image_format, image2d
+class image1d : public image_object
+{
+public:
+ /// Creates a null image1d object.
+ image1d()
+ : image_object()
+ {
+ }
+
+ /// Creates a new image1d object.
+ ///
+ /// \see_opencl_ref{clCreateImage}
+ image1d(const context &context,
+ size_t image_width,
+ const image_format &format,
+ cl_mem_flags flags = read_write,
+ void *host_ptr = 0)
+ {
+ #ifdef CL_VERSION_1_2
+ cl_image_desc desc;
+ desc.image_type = CL_MEM_OBJECT_IMAGE1D;
+ desc.image_width = image_width;
+ desc.image_height = 1;
+ desc.image_depth = 1;
+ desc.image_array_size = 0;
+ desc.image_row_pitch = 0;
+ desc.image_slice_pitch = 0;
+ desc.num_mip_levels = 0;
+ desc.num_samples = 0;
+ #ifdef CL_VERSION_2_0
+ desc.mem_object = 0;
+ #else
+ desc.buffer = 0;
+ #endif
+
+ cl_int error = 0;
+
+ m_mem = clCreateImage(
+ context, flags, format.get_format_ptr(), &desc, host_ptr, &error
+ );
+
+ if(!m_mem){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+ #else
+ // image1d objects are only supported in OpenCL 1.2 and later
+ BOOST_THROW_EXCEPTION(opencl_error(CL_IMAGE_FORMAT_NOT_SUPPORTED));
+ #endif
+ }
+
+ /// Creates a new image1d as a copy of \p other.
+ image1d(const image1d &other)
+ : image_object(other)
+ {
+ }
+
+ /// Copies the image1d from \p other.
+ image1d& operator=(const image1d &other)
+ {
+ image_object::operator=(other);
+
+ return *this;
+ }
+
+ #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+ /// Move-constructs a new image object from \p other.
+ image1d(image1d&& other) BOOST_NOEXCEPT
+ : image_object(std::move(other))
+ {
+ }
+
+ /// Move-assigns the image from \p other to \c *this.
+ image1d& operator=(image1d&& other) BOOST_NOEXCEPT
+ {
+ image_object::operator=(std::move(other));
+
+ return *this;
+ }
+ #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+ /// Destroys the image1d object.
+ ~image1d()
+ {
+ }
+
+ /// Returns the size (width) of the image.
+ extents<1> size() const
+ {
+ extents<1> size;
+ size[0] = get_info<size_t>(CL_IMAGE_WIDTH);
+ return size;
+ }
+
+ /// Returns the origin of the image (\c 0).
+ extents<1> origin() const
+ {
+ return extents<1>();
+ }
+
+ /// Returns information about the image.
+ ///
+ /// \see_opencl_ref{clGetImageInfo}
+ template<class T>
+ T get_info(cl_image_info info) const
+ {
+ return get_image_info<T>(info);
+ }
+
+ /// \overload
+ template<int Enum>
+ typename detail::get_object_info_type<image1d, Enum>::type
+ get_info() const;
+
+ /// Returns the supported image formats for the context.
+ ///
+ /// \see_opencl_ref{clGetSupportedImageFormats}
+ static std::vector<image_format>
+ get_supported_formats(const context &context, cl_mem_flags flags = read_write)
+ {
+ #ifdef CL_VERSION_1_2
+ return image_object::get_supported_formats(context, CL_MEM_OBJECT_IMAGE1D, flags);
+ #else
+ return std::vector<image_format>();
+ #endif
+ }
+
+ /// Returns \c true if \p format is a supported 1D image format for
+ /// \p context.
+ static bool is_supported_format(const image_format &format,
+ const context &context,
+ cl_mem_flags flags = read_write)
+ {
+ #ifdef CL_VERSION_1_2
+ return image_object::is_supported_format(
+ format, context, CL_MEM_OBJECT_IMAGE1D, flags
+ );
+ #else
+ return false;
+ #endif
+ }
+
+ /// Creates a new image with a copy of the data in \c *this. Uses \p queue
+ /// to perform the copy operation.
+ image1d clone(command_queue &queue) const;
+};
+
+/// \internal_ define get_info() specializations for image1d
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(image1d,
+ ((cl_image_format, CL_IMAGE_FORMAT))
+ ((size_t, CL_IMAGE_ELEMENT_SIZE))
+ ((size_t, CL_IMAGE_ROW_PITCH))
+ ((size_t, CL_IMAGE_SLICE_PITCH))
+ ((size_t, CL_IMAGE_WIDTH))
+ ((size_t, CL_IMAGE_HEIGHT))
+ ((size_t, CL_IMAGE_DEPTH))
+)
+
+namespace detail {
+
+// set_kernel_arg() specialization for image1d
+template<>
+struct set_kernel_arg<image1d> : public set_kernel_arg<image_object> { };
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+BOOST_COMPUTE_TYPE_NAME(boost::compute::image1d, image1d_t)
+
+#endif // BOOST_COMPUTE_IMAGE_IMAGE1D_HPP
diff --git a/boost/compute/image/image2d.hpp b/boost/compute/image/image2d.hpp
new file mode 100644
index 0000000000..c203a9417f
--- /dev/null
+++ b/boost/compute/image/image2d.hpp
@@ -0,0 +1,262 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_IMAGE_IMAGE2D_HPP
+#define BOOST_COMPUTE_IMAGE_IMAGE2D_HPP
+
+#include <boost/throw_exception.hpp>
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/exception/opencl_error.hpp>
+#include <boost/compute/image/image_format.hpp>
+#include <boost/compute/image/image_object.hpp>
+#include <boost/compute/detail/get_object_info.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/utility/extents.hpp>
+
+namespace boost {
+namespace compute {
+
+// forward declarations
+class command_queue;
+
+/// \class image2d
+/// \brief An OpenCL 2D image object
+///
+/// For example, to create a 640x480 8-bit RGBA image:
+///
+/// \snippet test/test_image2d.cpp create_image
+///
+/// \see image_format, image3d
+class image2d : public image_object
+{
+public:
+ /// Creates a null image2d object.
+ image2d()
+ : image_object()
+ {
+ }
+
+ /// Creates a new image2d object.
+ ///
+ /// \see_opencl_ref{clCreateImage}
+ image2d(const context &context,
+ size_t image_width,
+ size_t image_height,
+ const image_format &format,
+ cl_mem_flags flags = read_write,
+ void *host_ptr = 0,
+ size_t image_row_pitch = 0)
+ {
+ cl_int error = 0;
+
+ #ifdef CL_VERSION_1_2
+ cl_image_desc desc;
+ desc.image_type = CL_MEM_OBJECT_IMAGE2D;
+ desc.image_width = image_width;
+ desc.image_height = image_height;
+ desc.image_depth = 1;
+ desc.image_array_size = 0;
+ desc.image_row_pitch = image_row_pitch;
+ desc.image_slice_pitch = 0;
+ desc.num_mip_levels = 0;
+ desc.num_samples = 0;
+ #ifdef CL_VERSION_2_0
+ desc.mem_object = 0;
+ #else
+ desc.buffer = 0;
+ #endif
+
+ m_mem = clCreateImage(context,
+ flags,
+ format.get_format_ptr(),
+ &desc,
+ host_ptr,
+ &error);
+ #else
+ m_mem = clCreateImage2D(context,
+ flags,
+ format.get_format_ptr(),
+ image_width,
+ image_height,
+ image_row_pitch,
+ host_ptr,
+ &error);
+ #endif
+
+ if(!m_mem){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+ }
+
+ /// \internal_ (deprecated)
+ image2d(const context &context,
+ cl_mem_flags flags,
+ const image_format &format,
+ size_t image_width,
+ size_t image_height,
+ size_t image_row_pitch = 0,
+ void *host_ptr = 0)
+ {
+ cl_int error = 0;
+
+ #ifdef CL_VERSION_1_2
+ cl_image_desc desc;
+ desc.image_type = CL_MEM_OBJECT_IMAGE2D;
+ desc.image_width = image_width;
+ desc.image_height = image_height;
+ desc.image_depth = 1;
+ desc.image_array_size = 0;
+ desc.image_row_pitch = image_row_pitch;
+ desc.image_slice_pitch = 0;
+ desc.num_mip_levels = 0;
+ desc.num_samples = 0;
+ #ifdef CL_VERSION_2_0
+ desc.mem_object = 0;
+ #else
+ desc.buffer = 0;
+ #endif
+
+ m_mem = clCreateImage(context,
+ flags,
+ format.get_format_ptr(),
+ &desc,
+ host_ptr,
+ &error);
+ #else
+ m_mem = clCreateImage2D(context,
+ flags,
+ format.get_format_ptr(),
+ image_width,
+ image_height,
+ image_row_pitch,
+ host_ptr,
+ &error);
+ #endif
+
+ if(!m_mem){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+ }
+
+ /// Creates a new image2d as a copy of \p other.
+ image2d(const image2d &other)
+ : image_object(other)
+ {
+ }
+
+ /// Copies the image2d from \p other.
+ image2d& operator=(const image2d &other)
+ {
+ image_object::operator=(other);
+
+ return *this;
+ }
+
+ #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+ /// Move-constructs a new image object from \p other.
+ image2d(image2d&& other) BOOST_NOEXCEPT
+ : image_object(std::move(other))
+ {
+ }
+
+ /// Move-assigns the image from \p other to \c *this.
+ image2d& operator=(image2d&& other) BOOST_NOEXCEPT
+ {
+ image_object::operator=(std::move(other));
+
+ return *this;
+ }
+ #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+ /// Destroys the image2d object.
+ ~image2d()
+ {
+ }
+
+ /// Returns the size (width, height) of the image.
+ extents<2> size() const
+ {
+ extents<2> size;
+ size[0] = get_info<size_t>(CL_IMAGE_WIDTH);
+ size[1] = get_info<size_t>(CL_IMAGE_HEIGHT);
+ return size;
+ }
+
+ /// Returns the origin of the image (\c 0, \c 0).
+ extents<2> origin() const
+ {
+ return extents<2>();
+ }
+
+ /// Returns information about the image.
+ ///
+ /// \see_opencl_ref{clGetImageInfo}
+ template<class T>
+ T get_info(cl_image_info info) const
+ {
+ return detail::get_object_info<T>(clGetImageInfo, m_mem, info);
+ }
+
+ /// \overload
+ template<int Enum>
+ typename detail::get_object_info_type<image2d, Enum>::type
+ get_info() const;
+
+ /// Returns the supported image formats for the context.
+ ///
+ /// \see_opencl_ref{clGetSupportedImageFormats}
+ static std::vector<image_format>
+ get_supported_formats(const context &context, cl_mem_flags flags = read_write)
+ {
+ return image_object::get_supported_formats(context, CL_MEM_OBJECT_IMAGE2D, flags);
+ }
+
+ /// Returns \c true if \p format is a supported 2D image format for
+ /// \p context.
+ static bool is_supported_format(const image_format &format,
+ const context &context,
+ cl_mem_flags flags = read_write)
+ {
+ return image_object::is_supported_format(
+ format, context, CL_MEM_OBJECT_IMAGE2D, flags
+ );
+ }
+
+ /// Creates a new image with a copy of the data in \c *this. Uses \p queue
+ /// to perform the copy operation.
+ image2d clone(command_queue &queue) const;
+};
+
+/// \internal_ define get_info() specializations for image2d
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(image2d,
+ ((cl_image_format, CL_IMAGE_FORMAT))
+ ((size_t, CL_IMAGE_ELEMENT_SIZE))
+ ((size_t, CL_IMAGE_ROW_PITCH))
+ ((size_t, CL_IMAGE_SLICE_PITCH))
+ ((size_t, CL_IMAGE_WIDTH))
+ ((size_t, CL_IMAGE_HEIGHT))
+ ((size_t, CL_IMAGE_DEPTH))
+)
+
+namespace detail {
+
+// set_kernel_arg() specialization for image2d
+template<>
+struct set_kernel_arg<image2d> : public set_kernel_arg<image_object> { };
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+BOOST_COMPUTE_TYPE_NAME(boost::compute::image2d, image2d_t)
+
+#endif // BOOST_COMPUTE_IMAGE_IMAGE2D_HPP
diff --git a/boost/compute/image/image3d.hpp b/boost/compute/image/image3d.hpp
new file mode 100644
index 0000000000..9463cfaa16
--- /dev/null
+++ b/boost/compute/image/image3d.hpp
@@ -0,0 +1,265 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_IMAGE_IMAGE3D_HPP
+#define BOOST_COMPUTE_IMAGE_IMAGE3D_HPP
+
+#include <boost/throw_exception.hpp>
+
+#include <boost/compute/detail/get_object_info.hpp>
+#include <boost/compute/exception/opencl_error.hpp>
+#include <boost/compute/image/image_format.hpp>
+#include <boost/compute/image/image_object.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/utility/extents.hpp>
+
+namespace boost {
+namespace compute {
+
+// forward declarations
+class command_queue;
+
+/// \class image3d
+/// \brief An OpenCL 3D image object
+///
+/// \see image_format, image2d
+class image3d : public image_object
+{
+public:
+ /// Creates a null image3d object.
+ image3d()
+ : image_object()
+ {
+ }
+
+ /// Creates a new image3d object.
+ ///
+ /// \see_opencl_ref{clCreateImage}
+ image3d(const context &context,
+ size_t image_width,
+ size_t image_height,
+ size_t image_depth,
+ const image_format &format,
+ cl_mem_flags flags = read_write,
+ void *host_ptr = 0,
+ size_t image_row_pitch = 0,
+ size_t image_slice_pitch = 0)
+ {
+ cl_int error = 0;
+
+ #ifdef CL_VERSION_1_2
+ cl_image_desc desc;
+ desc.image_type = CL_MEM_OBJECT_IMAGE3D;
+ desc.image_width = image_width;
+ desc.image_height = image_height;
+ desc.image_depth = image_depth;
+ desc.image_array_size = 0;
+ desc.image_row_pitch = image_row_pitch;
+ desc.image_slice_pitch = image_slice_pitch;
+ desc.num_mip_levels = 0;
+ desc.num_samples = 0;
+ #ifdef CL_VERSION_2_0
+ desc.mem_object = 0;
+ #else
+ desc.buffer = 0;
+ #endif
+
+ m_mem = clCreateImage(context,
+ flags,
+ format.get_format_ptr(),
+ &desc,
+ host_ptr,
+ &error);
+ #else
+ m_mem = clCreateImage3D(context,
+ flags,
+ format.get_format_ptr(),
+ image_width,
+ image_height,
+ image_depth,
+ image_row_pitch,
+ image_slice_pitch,
+ host_ptr,
+ &error);
+ #endif
+
+ if(!m_mem){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+ }
+
+ /// \internal_ (deprecated)
+ image3d(const context &context,
+ cl_mem_flags flags,
+ const image_format &format,
+ size_t image_width,
+ size_t image_height,
+ size_t image_depth,
+ size_t image_row_pitch,
+ size_t image_slice_pitch = 0,
+ void *host_ptr = 0)
+ {
+ cl_int error = 0;
+
+ #ifdef CL_VERSION_1_2
+ cl_image_desc desc;
+ desc.image_type = CL_MEM_OBJECT_IMAGE3D;
+ desc.image_width = image_width;
+ desc.image_height = image_height;
+ desc.image_depth = image_depth;
+ desc.image_array_size = 0;
+ desc.image_row_pitch = image_row_pitch;
+ desc.image_slice_pitch = image_slice_pitch;
+ desc.num_mip_levels = 0;
+ desc.num_samples = 0;
+ #ifdef CL_VERSION_2_0
+ desc.mem_object = 0;
+ #else
+ desc.buffer = 0;
+ #endif
+
+ m_mem = clCreateImage(context,
+ flags,
+ format.get_format_ptr(),
+ &desc,
+ host_ptr,
+ &error);
+ #else
+ m_mem = clCreateImage3D(context,
+ flags,
+ format.get_format_ptr(),
+ image_width,
+ image_height,
+ image_depth,
+ image_row_pitch,
+ image_slice_pitch,
+ host_ptr,
+ &error);
+ #endif
+
+ if(!m_mem){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+ }
+
+ /// Creates a new image3d as a copy of \p other.
+ image3d(const image3d &other)
+ : image_object(other)
+ {
+ }
+
+ /// Copies the image3d from \p other.
+ image3d& operator=(const image3d &other)
+ {
+ image_object::operator=(other);
+
+ return *this;
+ }
+
+ #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+ /// Move-constructs a new image object from \p other.
+ image3d(image3d&& other) BOOST_NOEXCEPT
+ : image_object(std::move(other))
+ {
+ }
+
+ /// Move-assigns the image from \p other to \c *this.
+ image3d& operator=(image3d&& other) BOOST_NOEXCEPT
+ {
+ image_object::operator=(std::move(other));
+
+ return *this;
+ }
+ #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+ /// Destroys the image3d object.
+ ~image3d()
+ {
+ }
+
+ /// Returns the size (width, height, depth) of the image.
+ extents<3> size() const
+ {
+ extents<3> size;
+ size[0] = get_info<size_t>(CL_IMAGE_WIDTH);
+ size[1] = get_info<size_t>(CL_IMAGE_HEIGHT);
+ size[2] = get_info<size_t>(CL_IMAGE_DEPTH);
+ return size;
+ }
+
+ /// Returns the origin of the image (\c 0, \c 0, \c 0).
+ extents<3> origin() const
+ {
+ return extents<3>();
+ }
+
+ /// Returns information about the image.
+ ///
+ /// \see_opencl_ref{clGetImageInfo}
+ template<class T>
+ T get_info(cl_image_info info) const
+ {
+ return detail::get_object_info<T>(clGetImageInfo, m_mem, info);
+ }
+
+ /// \overload
+ template<int Enum>
+ typename detail::get_object_info_type<image3d, Enum>::type
+ get_info() const;
+
+ /// Returns the supported 3D image formats for the context.
+ ///
+ /// \see_opencl_ref{clGetSupportedImageFormats}
+ static std::vector<image_format>
+ get_supported_formats(const context &context, cl_mem_flags flags = read_write)
+ {
+ return image_object::get_supported_formats(context, CL_MEM_OBJECT_IMAGE3D, flags);
+ }
+
+ /// Returns \c true if \p format is a supported 3D image format for
+ /// \p context.
+ static bool is_supported_format(const image_format &format,
+ const context &context,
+ cl_mem_flags flags = read_write)
+ {
+ return image_object::is_supported_format(
+ format, context, CL_MEM_OBJECT_IMAGE3D, flags
+ );
+ }
+
+ /// Creates a new image with a copy of the data in \c *this. Uses \p queue
+ /// to perform the copy operation.
+ image3d clone(command_queue &queue) const;
+};
+
+/// \internal_ define get_info() specializations for image3d
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(image3d,
+ ((cl_image_format, CL_IMAGE_FORMAT))
+ ((size_t, CL_IMAGE_ELEMENT_SIZE))
+ ((size_t, CL_IMAGE_ROW_PITCH))
+ ((size_t, CL_IMAGE_SLICE_PITCH))
+ ((size_t, CL_IMAGE_WIDTH))
+ ((size_t, CL_IMAGE_HEIGHT))
+ ((size_t, CL_IMAGE_DEPTH))
+)
+
+namespace detail {
+
+// set_kernel_arg() specialization for image3d
+template<>
+struct set_kernel_arg<image3d> : public set_kernel_arg<image_object> { };
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+BOOST_COMPUTE_TYPE_NAME(boost::compute::image3d, image3d_t)
+
+#endif // BOOST_COMPUTE_IMAGE_IMAGE3D_HPP
diff --git a/boost/compute/image/image_format.hpp b/boost/compute/image/image_format.hpp
new file mode 100644
index 0000000000..a6ecf83ef6
--- /dev/null
+++ b/boost/compute/image/image_format.hpp
@@ -0,0 +1,135 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_IMAGE_IMAGE_FORMAT_HPP
+#define BOOST_COMPUTE_IMAGE_IMAGE_FORMAT_HPP
+
+#include <boost/compute/cl.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class image_format
+/// \brief A OpenCL image format
+///
+/// For example, to create a format for a 8-bit RGBA image:
+/// \code
+/// boost::compute::image_format rgba8(CL_RGBA, CL_UNSIGNED_INT8);
+/// \endcode
+///
+/// After being constructed, image_format objects are usually passed to the
+/// constructor of the various image classes (e.g. \ref image2d, \ref image3d)
+/// to create an image object on a compute device.
+///
+/// Image formats supported by a context can be queried with the static
+/// get_supported_formats() in each image class. For example:
+/// \code
+/// std::vector<image_format> formats = image2d::get_supported_formats(ctx);
+/// \endcode
+///
+/// \see image2d
+class image_format
+{
+public:
+ enum channel_order {
+ r = CL_R,
+ a = CL_A,
+ intensity = CL_INTENSITY,
+ luminance = CL_LUMINANCE,
+ rg = CL_RG,
+ ra = CL_RA,
+ rgb = CL_RGB,
+ rgba = CL_RGBA,
+ argb = CL_ARGB,
+ bgra = CL_BGRA
+ };
+
+ enum channel_data_type {
+ snorm_int8 = CL_SNORM_INT8,
+ snorm_int16 = CL_SNORM_INT16,
+ unorm_int8 = CL_UNORM_INT8,
+ unorm_int16 = CL_UNORM_INT16,
+ unorm_short_565 = CL_UNORM_SHORT_565,
+ unorm_short_555 = CL_UNORM_SHORT_555,
+ unorm_int_101010 = CL_UNORM_INT_101010,
+ signed_int8 = CL_SIGNED_INT8,
+ signed_int16 = CL_SIGNED_INT16,
+ signed_int32 = CL_SIGNED_INT32,
+ unsigned_int8 = CL_UNSIGNED_INT8,
+ unsigned_int16 = CL_UNSIGNED_INT16,
+ unsigned_int32 = CL_UNSIGNED_INT32,
+ float16 = CL_HALF_FLOAT,
+ float32 = CL_FLOAT
+ };
+
+ /// Creates a new image format object with \p order and \p type.
+ explicit image_format(cl_channel_order order, cl_channel_type type)
+ {
+ m_format.image_channel_order = order;
+ m_format.image_channel_data_type = type;
+ }
+
+ /// Creates a new image format object from \p format.
+ explicit image_format(const cl_image_format &format)
+ {
+ m_format.image_channel_order = format.image_channel_order;
+ m_format.image_channel_data_type = format.image_channel_data_type;
+ }
+
+ /// Creates a new image format object as a copy of \p other.
+ image_format(const image_format &other)
+ : m_format(other.m_format)
+ {
+ }
+
+ /// Copies the format from \p other to \c *this.
+ image_format& operator=(const image_format &other)
+ {
+ if(this != &other){
+ m_format = other.m_format;
+ }
+
+ return *this;
+ }
+
+ /// Destroys the image format object.
+ ~image_format()
+ {
+ }
+
+ /// Returns a pointer to the \c cl_image_format object.
+ const cl_image_format* get_format_ptr() const
+ {
+ return &m_format;
+ }
+
+ /// Returns \c true if \c *this is the same as \p other.
+ bool operator==(const image_format &other) const
+ {
+ return m_format.image_channel_order ==
+ other.m_format.image_channel_order &&
+ m_format.image_channel_data_type ==
+ other.m_format.image_channel_data_type;
+ }
+
+ /// Returns \c true if \c *this is not the same as \p other.
+ bool operator!=(const image_format &other) const
+ {
+ return !(*this == other);
+ }
+
+private:
+ cl_image_format m_format;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_IMAGE_IMAGE_FORMAT_HPP
diff --git a/boost/compute/image/image_object.hpp b/boost/compute/image/image_object.hpp
new file mode 100644
index 0000000000..451c68568f
--- /dev/null
+++ b/boost/compute/image/image_object.hpp
@@ -0,0 +1,170 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_IMAGE_IMAGE_OBJECT_HPP
+#define BOOST_COMPUTE_IMAGE_IMAGE_OBJECT_HPP
+
+#include <algorithm>
+#include <vector>
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/memory_object.hpp>
+#include <boost/compute/detail/get_object_info.hpp>
+#include <boost/compute/image/image_format.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class image_object
+/// \brief Base-class for image objects.
+///
+/// The image_object class is the base-class for image objects on compute
+/// devices.
+///
+/// \see image1d, image2d, image3d
+class image_object : public memory_object
+{
+public:
+ image_object()
+ : memory_object()
+ {
+ }
+
+ explicit image_object(cl_mem mem, bool retain = true)
+ : memory_object(mem, retain)
+ {
+ }
+
+ image_object(const image_object &other)
+ : memory_object(other)
+ {
+ }
+
+ image_object& operator=(const image_object &other)
+ {
+ if(this != &other){
+ memory_object::operator=(other);
+ }
+
+ return *this;
+ }
+
+ #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+ image_object(image_object&& other) BOOST_NOEXCEPT
+ : memory_object(std::move(other))
+ {
+ }
+
+ /// \internal_
+ image_object& operator=(image_object&& other) BOOST_NOEXCEPT
+ {
+ memory_object::operator=(std::move(other));
+
+ return *this;
+ }
+ #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+ /// Destroys the image object.
+ ~image_object()
+ {
+ }
+
+ /// Returns information about the image object.
+ ///
+ /// \see_opencl_ref{clGetImageInfo}
+ template<class T>
+ T get_image_info(cl_mem_info info) const
+ {
+ return detail::get_object_info<T>(clGetImageInfo, m_mem, info);
+ }
+
+ /// Returns the format for the image.
+ image_format format() const
+ {
+ return image_format(get_image_info<cl_image_format>(CL_IMAGE_FORMAT));
+ }
+
+ /// \internal_ (deprecated)
+ image_format get_format() const
+ {
+ return format();
+ }
+
+ /// Returns the width of the image.
+ size_t width() const
+ {
+ return get_image_info<size_t>(CL_IMAGE_WIDTH);
+ }
+
+ /// Returns the height of the image.
+ ///
+ /// For 1D images, this function will return \c 1.
+ size_t height() const
+ {
+ return get_image_info<size_t>(CL_IMAGE_HEIGHT);
+ }
+
+ /// Returns the depth of the image.
+ ///
+ /// For 1D and 2D images, this function will return \c 1.
+ size_t depth() const
+ {
+ return get_image_info<size_t>(CL_IMAGE_DEPTH);
+ }
+
+ /// Returns the supported image formats for the \p type in \p context.
+ ///
+ /// \see_opencl_ref{clGetSupportedImageFormats}
+ static std::vector<image_format>
+ get_supported_formats(const context &context,
+ cl_mem_object_type type,
+ cl_mem_flags flags = read_write)
+ {
+ cl_uint count = 0;
+ clGetSupportedImageFormats(context, flags, type, 0, 0, &count);
+
+ std::vector<cl_image_format> cl_formats(count);
+ clGetSupportedImageFormats(context, flags, type, count, &cl_formats[0], 0);
+
+ std::vector<image_format> formats;
+ formats.reserve(count);
+
+ for(cl_uint i = 0; i < count; i++){
+ formats.push_back(image_format(cl_formats[i]));
+ }
+
+ return formats;
+ }
+
+ /// Returns \c true if \p format is a supported image format for
+ /// \p type in \p context with \p flags.
+ static bool is_supported_format(const image_format &format,
+ const context &context,
+ cl_mem_object_type type,
+ cl_mem_flags flags = read_write)
+ {
+ const std::vector<image_format> formats =
+ get_supported_formats(context, type, flags);
+
+ return std::find(formats.begin(), formats.end(), format) != formats.end();
+ }
+};
+
+namespace detail {
+
+// set_kernel_arg() specialization for image_object
+template<>
+struct set_kernel_arg<image_object> : public set_kernel_arg<memory_object> { };
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_IMAGE_IMAGE_OBJECT_HPP
diff --git a/boost/compute/image/image_sampler.hpp b/boost/compute/image/image_sampler.hpp
new file mode 100644
index 0000000000..4f1bfe9b86
--- /dev/null
+++ b/boost/compute/image/image_sampler.hpp
@@ -0,0 +1,221 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_IMAGE_IMAGE_SAMPLER_HPP
+#define BOOST_COMPUTE_IMAGE_IMAGE_SAMPLER_HPP
+
+#include <boost/throw_exception.hpp>
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/detail/get_object_info.hpp>
+#include <boost/compute/detail/assert_cl_success.hpp>
+#include <boost/compute/exception/opencl_error.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class image_sampler
+/// \brief An OpenCL image sampler object
+///
+/// \see image2d, image_format
+class image_sampler
+{
+public:
+ enum addressing_mode {
+ none = CL_ADDRESS_NONE,
+ clamp_to_edge = CL_ADDRESS_CLAMP_TO_EDGE,
+ clamp = CL_ADDRESS_CLAMP,
+ repeat = CL_ADDRESS_REPEAT
+ };
+
+ enum filter_mode {
+ nearest = CL_FILTER_NEAREST,
+ linear = CL_FILTER_LINEAR
+ };
+
+ image_sampler()
+ : m_sampler(0)
+ {
+ }
+
+ image_sampler(const context &context,
+ bool normalized_coords,
+ cl_addressing_mode addressing_mode,
+ cl_filter_mode filter_mode)
+ {
+ cl_int error = 0;
+
+ #ifdef CL_VERSION_2_0
+ std::vector<cl_sampler_properties> sampler_properties;
+ sampler_properties.push_back(CL_SAMPLER_NORMALIZED_COORDS);
+ sampler_properties.push_back(cl_sampler_properties(normalized_coords));
+ sampler_properties.push_back(CL_SAMPLER_ADDRESSING_MODE);
+ sampler_properties.push_back(cl_sampler_properties(addressing_mode));
+ sampler_properties.push_back(CL_SAMPLER_FILTER_MODE);
+ sampler_properties.push_back(cl_sampler_properties(filter_mode));
+ sampler_properties.push_back(cl_sampler_properties(0));
+
+ m_sampler = clCreateSamplerWithProperties(
+ context, &sampler_properties[0], &error
+ );
+ #else
+ m_sampler = clCreateSampler(
+ context, normalized_coords, addressing_mode, filter_mode, &error
+ );
+ #endif
+
+ if(!m_sampler){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+ }
+
+ explicit image_sampler(cl_sampler sampler, bool retain = true)
+ : m_sampler(sampler)
+ {
+ if(m_sampler && retain){
+ clRetainSampler(m_sampler);
+ }
+ }
+
+ /// Creates a new image sampler object as a copy of \p other.
+ image_sampler(const image_sampler &other)
+ : m_sampler(other.m_sampler)
+ {
+ if(m_sampler){
+ clRetainSampler(m_sampler);
+ }
+ }
+
+ /// Copies the image sampler object from \p other to \c *this.
+ image_sampler& operator=(const image_sampler &other)
+ {
+ if(this != &other){
+ if(m_sampler){
+ clReleaseSampler(m_sampler);
+ }
+
+ m_sampler = other.m_sampler;
+
+ if(m_sampler){
+ clRetainSampler(m_sampler);
+ }
+ }
+
+ return *this;
+ }
+
+ #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+ image_sampler(image_sampler&& other) BOOST_NOEXCEPT
+ : m_sampler(other.m_sampler)
+ {
+ other.m_sampler = 0;
+ }
+
+ image_sampler& operator=(image_sampler&& other) BOOST_NOEXCEPT
+ {
+ if(m_sampler){
+ clReleaseSampler(m_sampler);
+ }
+
+ m_sampler = other.m_sampler;
+ other.m_sampler = 0;
+
+ return *this;
+ }
+ #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+ /// Destroys the image sampler object.
+ ~image_sampler()
+ {
+ if(m_sampler){
+ BOOST_COMPUTE_ASSERT_CL_SUCCESS(
+ clReleaseSampler(m_sampler)
+ );
+ }
+ }
+
+ /// Returns the underlying \c cl_sampler object.
+ cl_sampler& get() const
+ {
+ return const_cast<cl_sampler &>(m_sampler);
+ }
+
+ /// Returns the context for the image sampler object.
+ context get_context() const
+ {
+ return context(get_info<cl_context>(CL_SAMPLER_CONTEXT));
+ }
+
+ /// Returns information about the sampler.
+ ///
+ /// \see_opencl_ref{clGetSamplerInfo}
+ template<class T>
+ T get_info(cl_sampler_info info) const
+ {
+ return detail::get_object_info<T>(clGetSamplerInfo, m_sampler, info);
+ }
+
+ /// \overload
+ template<int Enum>
+ typename detail::get_object_info_type<image_sampler, Enum>::type
+ get_info() const;
+
+ /// Returns \c true if the sampler is the same at \p other.
+ bool operator==(const image_sampler &other) const
+ {
+ return m_sampler == other.m_sampler;
+ }
+
+ /// Returns \c true if the sampler is different from \p other.
+ bool operator!=(const image_sampler &other) const
+ {
+ return m_sampler != other.m_sampler;
+ }
+
+ operator cl_sampler() const
+ {
+ return m_sampler;
+ }
+
+private:
+ cl_sampler m_sampler;
+};
+
+/// \internal_ define get_info() specializations for image_sampler
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(image_sampler,
+ ((cl_uint, CL_SAMPLER_REFERENCE_COUNT))
+ ((cl_context, CL_SAMPLER_CONTEXT))
+ ((cl_addressing_mode, CL_SAMPLER_ADDRESSING_MODE))
+ ((cl_filter_mode, CL_SAMPLER_FILTER_MODE))
+ ((bool, CL_SAMPLER_NORMALIZED_COORDS))
+)
+
+namespace detail {
+
+// set_kernel_arg specialization for image samplers
+template<>
+struct set_kernel_arg<image_sampler>
+{
+ void operator()(kernel &kernel_, size_t index, const image_sampler &sampler)
+ {
+ kernel_.set_arg(index, sampler.get());
+ }
+};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+BOOST_COMPUTE_TYPE_NAME(boost::compute::image_sampler, sampler_t)
+
+#endif // BOOST_COMPUTE_IMAGE_IMAGE_SAMPLER_HPP
diff --git a/boost/compute/image2d.hpp b/boost/compute/image2d.hpp
new file mode 100644
index 0000000000..68460813da
--- /dev/null
+++ b/boost/compute/image2d.hpp
@@ -0,0 +1,12 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+// deprecated, use <boost/compute/image/image2d.hpp> instead
+#include <boost/compute/image/image2d.hpp>
diff --git a/boost/compute/image3d.hpp b/boost/compute/image3d.hpp
new file mode 100644
index 0000000000..ab7467c4f3
--- /dev/null
+++ b/boost/compute/image3d.hpp
@@ -0,0 +1,12 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+// deprecated, use <boost/compute/image/image3d.hpp> instead
+#include <boost/compute/image/image3d.hpp>
diff --git a/boost/compute/image_format.hpp b/boost/compute/image_format.hpp
new file mode 100644
index 0000000000..1ee50014aa
--- /dev/null
+++ b/boost/compute/image_format.hpp
@@ -0,0 +1,12 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+// deprecated, use <boost/compute/image/image_format.hpp> instead
+#include <boost/compute/image/image_format.hpp>
diff --git a/boost/compute/image_sampler.hpp b/boost/compute/image_sampler.hpp
new file mode 100644
index 0000000000..1cd11608b9
--- /dev/null
+++ b/boost/compute/image_sampler.hpp
@@ -0,0 +1,12 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+// deprecated, use <boost/compute/image/image_sampler.hpp> instead
+#include <boost/compute/image/image_sampler.hpp>
diff --git a/boost/compute/interop/eigen.hpp b/boost/compute/interop/eigen.hpp
new file mode 100644
index 0000000000..f616911417
--- /dev/null
+++ b/boost/compute/interop/eigen.hpp
@@ -0,0 +1,16 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_EIGEN_HPP
+#define BOOST_COMPUTE_INTEROP_EIGEN_HPP
+
+#include <boost/compute/interop/eigen/core.hpp>
+
+#endif // BOOST_COMPUTE_INTEROP_EIGEN_HPP
diff --git a/boost/compute/interop/eigen/core.hpp b/boost/compute/interop/eigen/core.hpp
new file mode 100644
index 0000000000..aa047efd32
--- /dev/null
+++ b/boost/compute/interop/eigen/core.hpp
@@ -0,0 +1,72 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_EIGEN_EIGEN_HPP
+#define BOOST_COMPUTE_INTEROP_EIGEN_EIGEN_HPP
+
+#include <Eigen/Core>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Copies \p matrix to \p buffer.
+template<class Derived>
+inline void eigen_copy_matrix_to_buffer(const Eigen::PlainObjectBase<Derived> &matrix,
+ buffer_iterator<typename Derived::Scalar> buffer,
+ command_queue &queue = system::default_queue())
+{
+ ::boost::compute::copy_n(matrix.data(), matrix.size(), buffer, queue);
+}
+
+/// Copies \p buffer to \p matrix.
+template<class Derived>
+inline void eigen_copy_buffer_to_matrix(const buffer_iterator<typename Derived::Scalar> buffer,
+ Eigen::PlainObjectBase<Derived> &matrix,
+ command_queue &queue = system::default_queue())
+{
+ ::boost::compute::copy_n(buffer, matrix.size(), matrix.data(), queue);
+}
+
+/// Converts an \c Eigen::Matrix4f to a \c float16_.
+inline float16_ eigen_matrix4f_to_float16(const Eigen::Matrix4f &matrix)
+{
+ float16_ result;
+ std::memcpy(&result, matrix.data(), 16 * sizeof(float));
+ return result;
+}
+
+/// Converts an \c Eigen::Matrix4d to a \c double16_.
+inline double16_ eigen_matrix4d_to_double16(const Eigen::Matrix4d &matrix)
+{
+ double16_ result;
+ std::memcpy(&result, matrix.data(), 16 * sizeof(double));
+ return result;
+}
+
+} // end compute namespace
+} // end boost namespace
+
+BOOST_COMPUTE_TYPE_NAME(Eigen::Vector2i, int2)
+BOOST_COMPUTE_TYPE_NAME(Eigen::Vector4i, int4)
+BOOST_COMPUTE_TYPE_NAME(Eigen::Vector2f, float2)
+BOOST_COMPUTE_TYPE_NAME(Eigen::Vector4f, float4)
+BOOST_COMPUTE_TYPE_NAME(Eigen::Matrix2f, float8)
+BOOST_COMPUTE_TYPE_NAME(Eigen::Matrix4f, float16)
+BOOST_COMPUTE_TYPE_NAME(Eigen::Vector2d, double2)
+BOOST_COMPUTE_TYPE_NAME(Eigen::Vector4d, double4)
+BOOST_COMPUTE_TYPE_NAME(Eigen::Matrix2d, double8)
+BOOST_COMPUTE_TYPE_NAME(Eigen::Matrix4d, double16)
+
+#endif // BOOST_COMPUTE_INTEROP_EIGEN_EIGEN_HPP
diff --git a/boost/compute/interop/opencv.hpp b/boost/compute/interop/opencv.hpp
new file mode 100644
index 0000000000..8cfa3a1c8a
--- /dev/null
+++ b/boost/compute/interop/opencv.hpp
@@ -0,0 +1,17 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_OPENCV_HPP
+#define BOOST_COMPUTE_INTEROP_OPENCV_HPP
+
+#include <boost/compute/interop/opencv/core.hpp>
+#include <boost/compute/interop/opencv/highgui.hpp>
+
+#endif // BOOST_COMPUTE_INTEROP_OPENCV_HPP
diff --git a/boost/compute/interop/opencv/core.hpp b/boost/compute/interop/opencv/core.hpp
new file mode 100644
index 0000000000..e3c7bf6dda
--- /dev/null
+++ b/boost/compute/interop/opencv/core.hpp
@@ -0,0 +1,141 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_OPENCV_CORE_HPP
+#define BOOST_COMPUTE_INTEROP_OPENCV_CORE_HPP
+
+#include <opencv2/core/core.hpp>
+
+#include <boost/throw_exception.hpp>
+
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/exception/opencl_error.hpp>
+#include <boost/compute/image/image2d.hpp>
+#include <boost/compute/image/image_format.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+
+namespace boost {
+namespace compute {
+
+template<class T>
+inline void opencv_copy_mat_to_buffer(const cv::Mat &mat,
+ buffer_iterator<T> buffer,
+ command_queue &queue = system::default_queue())
+{
+ BOOST_ASSERT(mat.isContinuous());
+
+ ::boost::compute::copy_n(
+ reinterpret_cast<T *>(mat.data), mat.rows * mat.cols, buffer, queue
+ );
+}
+
+template<class T>
+inline void opencv_copy_buffer_to_mat(const buffer_iterator<T> buffer,
+ cv::Mat &mat,
+ command_queue &queue = system::default_queue())
+{
+ BOOST_ASSERT(mat.isContinuous());
+
+ ::boost::compute::copy_n(
+ buffer, mat.cols * mat.rows, reinterpret_cast<T *>(mat.data), queue
+ );
+}
+
+inline void opencv_copy_mat_to_image(const cv::Mat &mat,
+ image2d &image,
+ command_queue &queue = system::default_queue())
+{
+ BOOST_ASSERT(mat.data != 0);
+ BOOST_ASSERT(mat.isContinuous());
+ BOOST_ASSERT(image.get_context() == queue.get_context());
+
+ queue.enqueue_write_image(image, image.origin(), image.size(), mat.data);
+}
+
+inline void opencv_copy_image_to_mat(const image2d &image,
+ cv::Mat &mat,
+ command_queue &queue = system::default_queue())
+{
+ BOOST_ASSERT(mat.isContinuous());
+ BOOST_ASSERT(image.get_context() == queue.get_context());
+
+ queue.enqueue_read_image(image, image.origin(), image.size(), mat.data);
+}
+
+inline image_format opencv_get_mat_image_format(const cv::Mat &mat)
+{
+ switch(mat.type()){
+ case CV_8UC4:
+ return image_format(CL_BGRA, CL_UNORM_INT8);
+ case CV_16UC4:
+ return image_format(CL_BGRA, CL_UNORM_INT16);
+ case CV_32F:
+ return image_format(CL_INTENSITY, CL_FLOAT);
+ case CV_32FC4:
+ return image_format(CL_RGBA, CL_FLOAT);
+ case CV_8UC1:
+ return image_format(CL_INTENSITY, CL_UNORM_INT8);
+ }
+
+ BOOST_THROW_EXCEPTION(opencl_error(CL_IMAGE_FORMAT_NOT_SUPPORTED));
+}
+
+inline cv::Mat opencv_create_mat_with_image2d(const image2d &image,
+ command_queue &queue = system::default_queue())
+{
+ BOOST_ASSERT(image.get_context() == queue.get_context());
+
+ cv::Mat mat;
+ image_format format = image.get_format();
+ const cl_image_format *cl_image_format = format.get_format_ptr();
+
+ if(cl_image_format->image_channel_data_type == CL_UNORM_INT8 &&
+ cl_image_format->image_channel_order == CL_BGRA)
+ {
+ mat = cv::Mat(image.height(), image.width(), CV_8UC4);
+ }
+ else if(cl_image_format->image_channel_data_type == CL_UNORM_INT16 &&
+ cl_image_format->image_channel_order == CL_BGRA)
+ {
+ mat = cv::Mat(image.height(), image.width(), CV_16UC4);
+ }
+ else if(cl_image_format->image_channel_data_type == CL_FLOAT &&
+ cl_image_format->image_channel_order == CL_INTENSITY)
+ {
+ mat = cv::Mat(image.height(), image.width(), CV_32FC1);
+ }
+ else
+ {
+ mat = cv::Mat(image.height(), image.width(), CV_8UC1);
+ }
+
+ opencv_copy_image_to_mat(image, mat, queue);
+
+ return mat;
+}
+
+inline image2d opencv_create_image2d_with_mat(const cv::Mat &mat,
+ cl_mem_flags flags,
+ command_queue &queue = system::default_queue())
+{
+ const context &context = queue.get_context();
+ const image_format format = opencv_get_mat_image_format(mat);
+
+ image2d image(context, mat.cols, mat.rows, format, flags);
+
+ opencv_copy_mat_to_image(mat, image, queue);
+
+ return image;
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_INTEROP_OPENCV_CORE_HPP
diff --git a/boost/compute/interop/opencv/highgui.hpp b/boost/compute/interop/opencv/highgui.hpp
new file mode 100644
index 0000000000..66baa728f6
--- /dev/null
+++ b/boost/compute/interop/opencv/highgui.hpp
@@ -0,0 +1,33 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_OPENCV_HIGHGUI_HPP
+#define BOOST_COMPUTE_INTEROP_OPENCV_HIGHGUI_HPP
+
+#include <opencv2/highgui/highgui.hpp>
+
+#include <boost/compute/interop/opencv/core.hpp>
+
+namespace boost {
+namespace compute {
+
+inline void opencv_imshow(const std::string &winname,
+ const image2d &image,
+ command_queue &queue = system::default_queue())
+{
+ const cv::Mat mat = opencv_create_mat_with_image2d(image, queue);
+
+ cv::imshow(winname, mat);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_INTEROP_OPENCV_HIGHGUI_HPP
diff --git a/boost/compute/interop/opencv/ocl.hpp b/boost/compute/interop/opencv/ocl.hpp
new file mode 100644
index 0000000000..23d8ac2273
--- /dev/null
+++ b/boost/compute/interop/opencv/ocl.hpp
@@ -0,0 +1,51 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_OPENCV_OCL_HPP
+#define BOOST_COMPUTE_INTEROP_OPENCV_OCL_HPP
+
+#include <opencv2/ocl/ocl.hpp>
+
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/command_queue.hpp>
+
+namespace boost {
+namespace compute {
+
+context opencv_ocl_get_context()
+{
+ void *ocl_context = cv::ocl::getoclContext();
+ if(!ocl_context){
+ return context();
+ }
+
+ return context(*(static_cast<cl_context *>(ocl_context)));
+}
+
+command_queue opencv_ocl_get_command_queue()
+{
+ void *ocl_queue = cv::ocl::getoclCommandQueue();
+ if(!ocl_queue){
+ return command_queue();
+ }
+
+ return command_queue(*(static_cast<cl_command_queue *>(ocl_queue)));
+}
+
+buffer opencv_ocl_get_buffer(const cv::ocl::oclMat &mat)
+{
+ return buffer(reinterpret_cast<cl_mem>(mat.data));
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_INTEROP_OPENCV_OCL_HPP
diff --git a/boost/compute/interop/opengl.hpp b/boost/compute/interop/opengl.hpp
new file mode 100644
index 0000000000..7ae12617ac
--- /dev/null
+++ b/boost/compute/interop/opengl.hpp
@@ -0,0 +1,24 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_OPENGL_HPP
+#define BOOST_COMPUTE_INTEROP_OPENGL_HPP
+
+/// \file
+///
+/// Meta-header to include all Boost.Compute OpenGL interop headers.
+
+#include <boost/compute/interop/opengl/acquire.hpp>
+#include <boost/compute/interop/opengl/context.hpp>
+#include <boost/compute/interop/opengl/opengl_buffer.hpp>
+#include <boost/compute/interop/opengl/opengl_renderbuffer.hpp>
+#include <boost/compute/interop/opengl/opengl_texture.hpp>
+
+#endif // BOOST_COMPUTE_INTEROP_OPENGL_HPP
diff --git a/boost/compute/interop/opengl/acquire.hpp b/boost/compute/interop/opengl/acquire.hpp
new file mode 100644
index 0000000000..10af4338fb
--- /dev/null
+++ b/boost/compute/interop/opengl/acquire.hpp
@@ -0,0 +1,99 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_OPENGL_ACQUIRE_HPP
+#define BOOST_COMPUTE_INTEROP_OPENGL_ACQUIRE_HPP
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/interop/opengl/cl_gl.hpp>
+#include <boost/compute/interop/opengl/opengl_buffer.hpp>
+#include <boost/compute/utility/wait_list.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Enqueues a command to acquire the specified OpenGL memory objects.
+///
+/// \see_opencl_ref{clEnqueueAcquireGLObjects}
+inline event opengl_enqueue_acquire_gl_objects(size_t num_objects,
+ const cl_mem *mem_objects,
+ command_queue &queue,
+ const wait_list &events = wait_list())
+{
+ BOOST_ASSERT(queue != 0);
+
+ event event_;
+
+ cl_int ret = clEnqueueAcquireGLObjects(queue.get(),
+ num_objects,
+ mem_objects,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get());
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+}
+
+/// Enqueues a command to release the specified OpenGL memory objects.
+///
+/// \see_opencl_ref{clEnqueueReleaseGLObjects}
+inline event opengl_enqueue_release_gl_objects(size_t num_objects,
+ const cl_mem *mem_objects,
+ command_queue &queue,
+ const wait_list &events = wait_list())
+{
+ BOOST_ASSERT(queue != 0);
+
+ event event_;
+
+ cl_int ret = clEnqueueReleaseGLObjects(queue.get(),
+ num_objects,
+ mem_objects,
+ events.size(),
+ events.get_event_ptr(),
+ &event_.get());
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return event_;
+}
+
+/// Enqueues a command to acquire the specified OpenGL buffer.
+///
+/// \see_opencl_ref{clEnqueueAcquireGLObjects}
+inline event opengl_enqueue_acquire_buffer(const opengl_buffer &buffer,
+ command_queue &queue,
+ const wait_list &events = wait_list())
+{
+ BOOST_ASSERT(buffer.get_context() == queue.get_context());
+
+ return opengl_enqueue_acquire_gl_objects(1, &buffer.get(), queue, events);
+}
+
+/// Enqueues a command to release the specified OpenGL buffer.
+///
+/// \see_opencl_ref{clEnqueueReleaseGLObjects}
+inline event opengl_enqueue_release_buffer(const opengl_buffer &buffer,
+ command_queue &queue,
+ const wait_list &events = wait_list())
+{
+ BOOST_ASSERT(buffer.get_context() == queue.get_context());
+
+ return opengl_enqueue_release_gl_objects(1, &buffer.get(), queue, events);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_INTEROP_OPENGL_ACQUIRE_HPP
diff --git a/boost/compute/interop/opengl/cl_gl.hpp b/boost/compute/interop/opengl/cl_gl.hpp
new file mode 100644
index 0000000000..de82dbd9ab
--- /dev/null
+++ b/boost/compute/interop/opengl/cl_gl.hpp
@@ -0,0 +1,20 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_OPENGL_CL_GL_HPP
+#define BOOST_COMPUTE_INTEROP_OPENGL_CL_GL_HPP
+
+#if defined(__APPLE__)
+#include <OpenCL/cl_gl.h>
+#else
+#include <CL/cl_gl.h>
+#endif
+
+#endif // BOOST_COMPUTE_INTEROP_OPENGL_CL_GL_HPP
diff --git a/boost/compute/interop/opengl/cl_gl_ext.hpp b/boost/compute/interop/opengl/cl_gl_ext.hpp
new file mode 100644
index 0000000000..3392b051e0
--- /dev/null
+++ b/boost/compute/interop/opengl/cl_gl_ext.hpp
@@ -0,0 +1,20 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_OPENGL_CL_GL_EXT_HPP
+#define BOOST_COMPUTE_INTEROP_OPENGL_CL_GL_EXT_HPP
+
+#if defined(__APPLE__)
+#include <OpenCL/cl_gl_ext.h>
+#else
+#include <CL/cl_gl_ext.h>
+#endif
+
+#endif // BOOST_COMPUTE_INTEROP_OPENGL_CL_GL_EXT_HPP
diff --git a/boost/compute/interop/opengl/context.hpp b/boost/compute/interop/opengl/context.hpp
new file mode 100644
index 0000000000..754dca2236
--- /dev/null
+++ b/boost/compute/interop/opengl/context.hpp
@@ -0,0 +1,135 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_OPENGL_CONTEXT_HPP
+#define BOOST_COMPUTE_INTEROP_OPENGL_CONTEXT_HPP
+
+#include <boost/throw_exception.hpp>
+
+#include <boost/compute/device.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/exception/unsupported_extension_error.hpp>
+#include <boost/compute/interop/opengl/cl_gl.hpp>
+
+#ifdef __APPLE__
+#include <OpenCL/cl_gl_ext.h>
+#include <OpenGL/OpenGL.h>
+#endif
+
+#ifdef __linux__
+#include <GL/glx.h>
+#endif
+
+namespace boost {
+namespace compute {
+
+/// Creates a shared OpenCL/OpenGL context for the currently active
+/// OpenGL context.
+///
+/// Once created, the shared context can be used to create OpenCL memory
+/// objects which can interact with OpenGL memory objects (e.g. VBOs).
+///
+/// \throws unsupported_extension_error if no CL-GL sharing capable devices
+/// are found.
+inline context opengl_create_shared_context()
+{
+ // name of the OpenGL sharing extension for the system
+#if defined(__APPLE__)
+ const char *cl_gl_sharing_extension = "cl_APPLE_gl_sharing";
+#else
+ const char *cl_gl_sharing_extension = "cl_khr_gl_sharing";
+#endif
+
+#if defined(__APPLE__)
+ // get OpenGL share group
+ CGLContextObj cgl_current_context = CGLGetCurrentContext();
+ CGLShareGroupObj cgl_share_group = CGLGetShareGroup(cgl_current_context);
+
+ cl_context_properties properties[] = {
+ CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE,
+ (cl_context_properties) cgl_share_group,
+ 0
+ };
+
+ cl_int error = 0;
+ cl_context cl_gl_context = clCreateContext(properties, 0, 0, 0, 0, &error);
+ if(!cl_gl_context){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+
+ return context(cl_gl_context, false);
+#else
+ typedef cl_int(*GetGLContextInfoKHRFunction)(
+ const cl_context_properties*, cl_gl_context_info, size_t, void *, size_t *
+ );
+
+ std::vector<platform> platforms = system::platforms();
+ for(size_t i = 0; i < platforms.size(); i++){
+ const platform &platform = platforms[i];
+
+ // load clGetGLContextInfoKHR() extension function
+ GetGLContextInfoKHRFunction GetGLContextInfoKHR =
+ reinterpret_cast<GetGLContextInfoKHRFunction>(
+ reinterpret_cast<unsigned long>(
+ platform.get_extension_function_address("clGetGLContextInfoKHR")
+ )
+ );
+ if(!GetGLContextInfoKHR){
+ continue;
+ }
+
+ // create context properties listing the platform and current OpenGL display
+ cl_context_properties properties[] = {
+ CL_CONTEXT_PLATFORM, (cl_context_properties) platform.id(),
+ #if defined(__linux__)
+ CL_GL_CONTEXT_KHR, (cl_context_properties) glXGetCurrentContext(),
+ CL_GLX_DISPLAY_KHR, (cl_context_properties) glXGetCurrentDisplay(),
+ #elif defined(WIN32)
+ CL_GL_CONTEXT_KHR, (cl_context_properties) wglGetCurrentContext(),
+ CL_WGL_HDC_KHR, (cl_context_properties) wglGetCurrentDC(),
+ #endif
+ 0
+ };
+
+ // lookup current OpenCL device for current OpenGL context
+ cl_device_id gpu_id;
+ cl_int ret = GetGLContextInfoKHR(
+ properties,
+ CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR,
+ sizeof(cl_device_id),
+ &gpu_id,
+ 0
+ );
+ if(ret != CL_SUCCESS){
+ continue;
+ }
+
+ // create device object for the GPU and ensure it supports CL-GL sharing
+ device gpu(gpu_id, false);
+ if(!gpu.supports_extension(cl_gl_sharing_extension)){
+ continue;
+ }
+
+ // return CL-GL sharing context
+ return context(gpu, properties);
+ }
+#endif
+
+ // no CL-GL sharing capable devices found
+ BOOST_THROW_EXCEPTION(
+ unsupported_extension_error(cl_gl_sharing_extension)
+ );
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_INTEROP_OPENGL_CONTEXT_HPP
diff --git a/boost/compute/interop/opengl/gl.hpp b/boost/compute/interop/opengl/gl.hpp
new file mode 100644
index 0000000000..a05c944075
--- /dev/null
+++ b/boost/compute/interop/opengl/gl.hpp
@@ -0,0 +1,20 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_OPENGL_GL_HPP
+#define BOOST_COMPUTE_INTEROP_OPENGL_GL_HPP
+
+#if defined(__APPLE__)
+#include <OpenGL/gl.h>
+#else
+#include <GL/gl.h>
+#endif
+
+#endif // BOOST_COMPUTE_INTEROP_OPENGL_GL_HPP
diff --git a/boost/compute/interop/opengl/opengl_buffer.hpp b/boost/compute/interop/opengl/opengl_buffer.hpp
new file mode 100644
index 0000000000..c27347d0d9
--- /dev/null
+++ b/boost/compute/interop/opengl/opengl_buffer.hpp
@@ -0,0 +1,106 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_OPENGL_OPENGL_BUFFER_HPP
+#define BOOST_COMPUTE_INTEROP_OPENGL_OPENGL_BUFFER_HPP
+
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/interop/opengl/gl.hpp>
+#include <boost/compute/interop/opengl/cl_gl.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class opengl_buffer
+///
+/// A OpenCL buffer for accessing an OpenGL memory object.
+class opengl_buffer : public buffer
+{
+public:
+ /// Creates a null OpenGL buffer object.
+ opengl_buffer()
+ : buffer()
+ {
+ }
+
+ /// Creates a new OpenGL buffer object for \p mem.
+ explicit opengl_buffer(cl_mem mem, bool retain = true)
+ : buffer(mem, retain)
+ {
+ }
+
+ /// Creates a new OpenGL buffer object in \p context for \p bufobj
+ /// with \p flags.
+ ///
+ /// \see_opencl_ref{clCreateFromGLBuffer}
+ opengl_buffer(const context &context,
+ GLuint bufobj,
+ cl_mem_flags flags = read_write)
+ {
+ cl_int error = 0;
+ m_mem = clCreateFromGLBuffer(context, flags, bufobj, &error);
+ if(!m_mem){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+ }
+
+ /// Creates a new OpenGL buffer object as a copy of \p other.
+ opengl_buffer(const opengl_buffer &other)
+ : buffer(other)
+ {
+ }
+
+ /// Copies the OpenGL buffer object from \p other.
+ opengl_buffer& operator=(const opengl_buffer &other)
+ {
+ if(this != &other){
+ buffer::operator=(other);
+ }
+
+ return *this;
+ }
+
+ /// Destroys the OpenGL buffer object.
+ ~opengl_buffer()
+ {
+ }
+
+ /// Returns the OpenGL memory object ID.
+ ///
+ /// \see_opencl_ref{clGetGLObjectInfo}
+ GLuint get_opengl_object() const
+ {
+ GLuint object = 0;
+ clGetGLObjectInfo(m_mem, 0, &object);
+ return object;
+ }
+
+ /// Returns the OpenGL memory object type.
+ ///
+ /// \see_opencl_ref{clGetGLObjectInfo}
+ cl_gl_object_type get_opengl_type() const
+ {
+ cl_gl_object_type type;
+ clGetGLObjectInfo(m_mem, &type, 0);
+ return type;
+ }
+};
+
+namespace detail {
+
+// set_kernel_arg specialization for opengl_buffer
+template<>
+struct set_kernel_arg<opengl_buffer> : set_kernel_arg<memory_object> { };
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_INTEROP_OPENGL_OPENGL_BUFFER_HPP
diff --git a/boost/compute/interop/opengl/opengl_renderbuffer.hpp b/boost/compute/interop/opengl/opengl_renderbuffer.hpp
new file mode 100644
index 0000000000..fd4759d0ee
--- /dev/null
+++ b/boost/compute/interop/opengl/opengl_renderbuffer.hpp
@@ -0,0 +1,129 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_OPENGL_OPENGL_RENDERBUFFER_HPP
+#define BOOST_COMPUTE_INTEROP_OPENGL_OPENGL_RENDERBUFFER_HPP
+
+#include <boost/compute/image/image_object.hpp>
+#include <boost/compute/interop/opengl/gl.hpp>
+#include <boost/compute/interop/opengl/cl_gl.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/utility/extents.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class opengl_renderbuffer
+///
+/// A OpenCL buffer for accessing an OpenGL renderbuffer object.
+class opengl_renderbuffer : public image_object
+{
+public:
+ /// Creates a null OpenGL renderbuffer object.
+ opengl_renderbuffer()
+ : image_object()
+ {
+ }
+
+ /// Creates a new OpenGL renderbuffer object for \p mem.
+ explicit opengl_renderbuffer(cl_mem mem, bool retain = true)
+ : image_object(mem, retain)
+ {
+ }
+
+ /// Creates a new OpenGL renderbuffer object in \p context for
+ /// \p renderbuffer with \p flags.
+ ///
+ /// \see_opencl_ref{clCreateFromGLRenderbuffer}
+ opengl_renderbuffer(const context &context,
+ GLuint renderbuffer,
+ cl_mem_flags flags = read_write)
+ {
+ cl_int error = 0;
+
+ m_mem = clCreateFromGLRenderbuffer(
+ context, flags, renderbuffer, &error
+ );
+
+ if(!m_mem){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+ }
+
+ /// Creates a new OpenGL renderbuffer object as a copy of \p other.
+ opengl_renderbuffer(const opengl_renderbuffer &other)
+ : image_object(other)
+ {
+ }
+
+ /// Copies the OpenGL renderbuffer object from \p other.
+ opengl_renderbuffer& operator=(const opengl_renderbuffer &other)
+ {
+ if(this != &other){
+ image_object::operator=(other);
+ }
+
+ return *this;
+ }
+
+ /// Destroys the OpenGL buffer object.
+ ~opengl_renderbuffer()
+ {
+ }
+
+ /// Returns the size (width, height) of the renderbuffer.
+ extents<2> size() const
+ {
+ extents<2> size;
+ size[0] = get_image_info<size_t>(CL_IMAGE_WIDTH);
+ size[1] = get_image_info<size_t>(CL_IMAGE_HEIGHT);
+ return size;
+ }
+
+ /// Returns the origin of the renderbuffer (\c 0, \c 0).
+ extents<2> origin() const
+ {
+ return extents<2>();
+ }
+
+ /// Returns the OpenGL memory object ID.
+ ///
+ /// \see_opencl_ref{clGetGLObjectInfo}
+ GLuint get_opengl_object() const
+ {
+ GLuint object = 0;
+ clGetGLObjectInfo(m_mem, 0, &object);
+ return object;
+ }
+
+ /// Returns the OpenGL memory object type.
+ ///
+ /// \see_opencl_ref{clGetGLObjectInfo}
+ cl_gl_object_type get_opengl_type() const
+ {
+ cl_gl_object_type type;
+ clGetGLObjectInfo(m_mem, &type, 0);
+ return type;
+ }
+};
+
+namespace detail {
+
+// set_kernel_arg() specialization for opengl_renderbuffer
+template<>
+struct set_kernel_arg<opengl_renderbuffer> : public set_kernel_arg<image_object> { };
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+BOOST_COMPUTE_TYPE_NAME(boost::compute::opengl_renderbuffer, image2d_t)
+
+#endif // BOOST_COMPUTE_INTEROP_OPENGL_OPENGL_RENDERBUFFER_HPP
diff --git a/boost/compute/interop/opengl/opengl_texture.hpp b/boost/compute/interop/opengl/opengl_texture.hpp
new file mode 100644
index 0000000000..c1f3f4f441
--- /dev/null
+++ b/boost/compute/interop/opengl/opengl_texture.hpp
@@ -0,0 +1,133 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_OPENGL_OPENGL_TEXTURE_HPP
+#define BOOST_COMPUTE_INTEROP_OPENGL_OPENGL_TEXTURE_HPP
+
+#include <boost/compute/image/image_object.hpp>
+#include <boost/compute/interop/opengl/gl.hpp>
+#include <boost/compute/interop/opengl/cl_gl.hpp>
+#include <boost/compute/detail/get_object_info.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/utility/extents.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class opengl_texture
+///
+/// A OpenCL image2d for accessing an OpenGL texture object.
+class opengl_texture : public image_object
+{
+public:
+ /// Creates a null OpenGL texture object.
+ opengl_texture()
+ : image_object()
+ {
+ }
+
+ /// Creates a new OpenGL texture object for \p mem.
+ explicit opengl_texture(cl_mem mem, bool retain = true)
+ : image_object(mem, retain)
+ {
+ }
+
+ /// Creates a new OpenGL texture object in \p context for \p texture
+ /// with \p flags.
+ ///
+ /// \see_opencl_ref{clCreateFromGLTexture}
+ opengl_texture(const context &context,
+ GLenum texture_target,
+ GLint miplevel,
+ GLuint texture,
+ cl_mem_flags flags = read_write)
+ {
+ cl_int error = 0;
+
+ #ifdef CL_VERSION_1_2
+ m_mem = clCreateFromGLTexture(context,
+ flags,
+ texture_target,
+ miplevel,
+ texture,
+ &error);
+ #else
+ m_mem = clCreateFromGLTexture2D(context,
+ flags,
+ texture_target,
+ miplevel,
+ texture,
+ &error);
+ #endif
+
+ if(!m_mem){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+ }
+
+ /// Creates a new OpenGL texture object as a copy of \p other.
+ opengl_texture(const opengl_texture &other)
+ : image_object(other)
+ {
+ }
+
+ /// Copies the OpenGL texture object from \p other.
+ opengl_texture& operator=(const opengl_texture &other)
+ {
+ if(this != &other){
+ image_object::operator=(other);
+ }
+
+ return *this;
+ }
+
+ /// Destroys the texture object.
+ ~opengl_texture()
+ {
+ }
+
+ /// Returns the size (width, height) of the texture.
+ extents<2> size() const
+ {
+ extents<2> size;
+ size[0] = get_image_info<size_t>(CL_IMAGE_WIDTH);
+ size[1] = get_image_info<size_t>(CL_IMAGE_HEIGHT);
+ return size;
+ }
+
+ /// Returns the origin of the texture (\c 0, \c 0).
+ extents<2> origin() const
+ {
+ return extents<2>();
+ }
+
+ /// Returns information about the texture.
+ ///
+ /// \see_opencl_ref{clGetGLTextureInfo}
+ template<class T>
+ T get_texture_info(cl_gl_texture_info info) const
+ {
+ return detail::get_object_info<T>(clGetGLTextureInfo, m_mem, info);
+ }
+};
+
+namespace detail {
+
+// set_kernel_arg() specialization for opengl_texture
+template<>
+struct set_kernel_arg<opengl_texture> : public set_kernel_arg<image_object> { };
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+BOOST_COMPUTE_TYPE_NAME(boost::compute::opengl_texture, image2d_t)
+
+#endif // BOOST_COMPUTE_INTEROP_OPENGL_OPENGL_TEXTURE_HPP
diff --git a/boost/compute/interop/qt.hpp b/boost/compute/interop/qt.hpp
new file mode 100644
index 0000000000..f53691cc34
--- /dev/null
+++ b/boost/compute/interop/qt.hpp
@@ -0,0 +1,17 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_QT_HPP
+#define BOOST_COMPUTE_INTEROP_QT_HPP
+
+#include <boost/compute/interop/qt/qtcore.hpp>
+#include <boost/compute/interop/qt/qtgui.hpp>
+
+#endif // BOOST_COMPUTE_INTEROP_QT_HPP
diff --git a/boost/compute/interop/qt/qimage.hpp b/boost/compute/interop/qt/qimage.hpp
new file mode 100644
index 0000000000..faa6f98cc8
--- /dev/null
+++ b/boost/compute/interop/qt/qimage.hpp
@@ -0,0 +1,69 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_QT_QIMAGE_HPP
+#define BOOST_COMPUTE_INTEROP_QT_QIMAGE_HPP
+
+#include <boost/throw_exception.hpp>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/exception/opencl_error.hpp>
+#include <boost/compute/image/image2d.hpp>
+#include <boost/compute/image/image_format.hpp>
+#include <boost/compute/utility/dim.hpp>
+
+#include <QImage>
+
+namespace boost {
+namespace compute {
+
+inline image_format qt_qimage_format_to_image_format(const QImage::Format &format)
+{
+ if(format == QImage::Format_RGB32){
+ return image_format(image_format::bgra, image_format::unorm_int8);
+ }
+
+ BOOST_THROW_EXCEPTION(opencl_error(CL_IMAGE_FORMAT_NOT_SUPPORTED));
+}
+
+inline QImage::Format qt_image_format_to_qimage_format(const image_format &format)
+{
+ if(format == image_format(image_format::bgra, image_format::unorm_int8)){
+ return QImage::Format_RGB32;
+ }
+
+ return QImage::Format_Invalid;
+}
+
+inline image_format qt_qimage_get_format(const QImage &image)
+{
+ return qt_qimage_format_to_image_format(image.format());
+}
+
+inline void qt_copy_qimage_to_image2d(const QImage &qimage,
+ image2d &image,
+ command_queue &queue)
+{
+ queue.enqueue_write_image(image, image.origin(), image.size(), qimage.constBits());
+}
+
+inline void qt_copy_image2d_to_qimage(const image2d &image,
+ QImage &qimage,
+ command_queue &queue)
+{
+ queue.enqueue_read_image(
+ image, dim(0, 0), dim(qimage.width(), qimage.height()), qimage.bits()
+ );
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_INTEROP_QT_QIMAGE_HPP
diff --git a/boost/compute/interop/qt/qpoint.hpp b/boost/compute/interop/qt/qpoint.hpp
new file mode 100644
index 0000000000..d867fc7a43
--- /dev/null
+++ b/boost/compute/interop/qt/qpoint.hpp
@@ -0,0 +1,20 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_QT_QPOINT_HPP
+#define BOOST_COMPUTE_INTEROP_QT_QPOINT_HPP
+
+#include <QPoint>
+
+#include <boost/compute/type_traits/type_name.hpp>
+
+BOOST_COMPUTE_TYPE_NAME(QPoint, "int2")
+
+#endif // BOOST_COMPUTE_INTEROP_QT_QPOINT_HPP
diff --git a/boost/compute/interop/qt/qpointf.hpp b/boost/compute/interop/qt/qpointf.hpp
new file mode 100644
index 0000000000..fd7392a804
--- /dev/null
+++ b/boost/compute/interop/qt/qpointf.hpp
@@ -0,0 +1,20 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_QT_QPOINTF_HPP
+#define BOOST_COMPUTE_INTEROP_QT_QPOINTF_HPP
+
+#include <QPointF>
+
+#include <boost/compute/type_traits/type_name.hpp>
+
+BOOST_COMPUTE_TYPE_NAME(QPointF, "float2")
+
+#endif // BOOST_COMPUTE_INTEROP_QT_QPOINTF_HPP
diff --git a/boost/compute/interop/qt/qtcore.hpp b/boost/compute/interop/qt/qtcore.hpp
new file mode 100644
index 0000000000..b8978180e0
--- /dev/null
+++ b/boost/compute/interop/qt/qtcore.hpp
@@ -0,0 +1,18 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_QT_QTCORE_HPP
+#define BOOST_COMPUTE_INTEROP_QT_QTCORE_HPP
+
+#include <boost/compute/interop/qt/qpoint.hpp>
+#include <boost/compute/interop/qt/qpointf.hpp>
+#include <boost/compute/interop/qt/qvector.hpp>
+
+#endif // BOOST_COMPUTE_INTEROP_QT_QTCORE_HPP
diff --git a/boost/compute/interop/qt/qtgui.hpp b/boost/compute/interop/qt/qtgui.hpp
new file mode 100644
index 0000000000..f1078f48b9
--- /dev/null
+++ b/boost/compute/interop/qt/qtgui.hpp
@@ -0,0 +1,16 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_QT_QTGUI_HPP
+#define BOOST_COMPUTE_INTEROP_QT_QTGUI_HPP
+
+#include <boost/compute/interop/qt/qimage.hpp>
+
+#endif // BOOST_COMPUTE_INTEROP_QT_QTGUI_HPP
diff --git a/boost/compute/interop/qt/qvector.hpp b/boost/compute/interop/qt/qvector.hpp
new file mode 100644
index 0000000000..3ac93d2aaa
--- /dev/null
+++ b/boost/compute/interop/qt/qvector.hpp
@@ -0,0 +1,48 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_QT_QVECTOR_HPP
+#define BOOST_COMPUTE_INTEROP_QT_QVECTOR_HPP
+
+#include <boost/compute/detail/is_contiguous_iterator.hpp>
+
+#include <QVector>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class Iterator>
+struct _is_contiguous_iterator<
+ Iterator,
+ typename boost::enable_if<
+ typename boost::is_same<
+ Iterator,
+ typename QVector<typename Iterator::value_type>::iterator
+ >::type
+ >::type
+> : public boost::true_type {};
+
+template<class Iterator>
+struct _is_contiguous_iterator<
+ Iterator,
+ typename boost::enable_if<
+ typename boost::is_same<
+ Iterator,
+ typename QVector<typename Iterator::value_type>::const_iterator
+ >::type
+ >::type
+> : public boost::true_type {};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_INTEROP_QT_QVECTOR_HPP
diff --git a/boost/compute/interop/vtk.hpp b/boost/compute/interop/vtk.hpp
new file mode 100644
index 0000000000..3f866e5f8f
--- /dev/null
+++ b/boost/compute/interop/vtk.hpp
@@ -0,0 +1,19 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_VTK_HPP
+#define BOOST_COMPUTE_INTEROP_VTK_HPP
+
+#include <boost/compute/interop/vtk/bounds.hpp>
+#include <boost/compute/interop/vtk/data_array.hpp>
+#include <boost/compute/interop/vtk/matrix4x4.hpp>
+#include <boost/compute/interop/vtk/points.hpp>
+
+#endif // BOOST_COMPUTE_INTEROP_VTK_HPP
diff --git a/boost/compute/interop/vtk/bounds.hpp b/boost/compute/interop/vtk/bounds.hpp
new file mode 100644
index 0000000000..360a9061f9
--- /dev/null
+++ b/boost/compute/interop/vtk/bounds.hpp
@@ -0,0 +1,59 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_VTK_BOUNDS_HPP
+#define BOOST_COMPUTE_INTEROP_VTK_BOUNDS_HPP
+
+#include <vector>
+#include <iterator>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/algorithm/reduce.hpp>
+#include <boost/compute/container/array.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Calculates the bounds for the points in the range [\p first, \p last) and
+/// stores the result in \p bounds.
+///
+/// For example, this can be used to implement the GetBounds() method for a
+/// vtkMapper subclass.
+template<class PointIterator>
+inline void vtk_compute_bounds(PointIterator first,
+ PointIterator last,
+ double bounds[6],
+ command_queue &queue = system::default_queue())
+{
+ typedef typename std::iterator_traits<PointIterator>::value_type T;
+
+ const context &context = queue.get_context();
+
+ // compute min and max point
+ array<T, 2> extrema(context);
+ reduce(first, last, extrema.begin() + 0, min<T>(), queue);
+ reduce(first, last, extrema.begin() + 1, max<T>(), queue);
+
+ // copy results to host buffer
+ std::vector<T> buffer(2);
+ copy_n(extrema.begin(), 2, buffer.begin(), queue);
+
+ // copy to vtk-style bounds
+ bounds[0] = buffer[0][0]; bounds[1] = buffer[1][0];
+ bounds[2] = buffer[0][1]; bounds[3] = buffer[1][1];
+ bounds[4] = buffer[0][2]; bounds[5] = buffer[1][2];
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_INTEROP_VTK_BOUNDS_HPP
diff --git a/boost/compute/interop/vtk/data_array.hpp b/boost/compute/interop/vtk/data_array.hpp
new file mode 100644
index 0000000000..7b909b1a3f
--- /dev/null
+++ b/boost/compute/interop/vtk/data_array.hpp
@@ -0,0 +1,65 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_VTK_DATA_ARRAY_HPP
+#define BOOST_COMPUTE_INTEROP_VTK_DATA_ARRAY_HPP
+
+#include <vtkDataArray.h>
+#include <vtkDataArrayTemplate.h>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Copies the values in \p data to \p buffer.
+template<class T>
+inline void vtk_copy_data_array_to_buffer(const vtkDataArray *data,
+ buffer_iterator<T> buffer,
+ command_queue &queue = system::default_queue());
+
+/// \internal_
+template<class T>
+inline void vtk_copy_data_array_to_buffer(const vtkDataArrayTemplate<T> *data,
+ buffer_iterator<T> buffer,
+ command_queue &queue = system::default_queue())
+{
+ vtkDataArrayTemplate<T> *data_ = const_cast<vtkDataArrayTemplate<T> *>(data);
+ const T *data_ptr = static_cast<const T *>(data_->GetVoidPointer(0));
+ size_t data_size = data_->GetNumberOfComponents() * data_->GetNumberOfTuples();
+ ::boost::compute::copy_n(data_ptr, data_size, buffer, queue);
+}
+
+/// Copies the values in the range [\p first, \p last) to \p data.
+template<class T>
+inline void vtk_copy_buffer_to_data_array(buffer_iterator<T> first,
+ buffer_iterator<T> last,
+ vtkDataArray *data,
+ command_queue &queue = system::default_queue());
+
+/// \internal_
+template<class T>
+inline void vtk_copy_buffer_to_data_array(buffer_iterator<T> first,
+ buffer_iterator<T> last,
+ vtkDataArrayTemplate<T> *data,
+ command_queue &queue = system::default_queue())
+{
+ T *data_ptr = static_cast<T *>(data->GetVoidPointer(0));
+ ::boost::compute::copy(first, last, data_ptr, queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_INTEROP_VTK_DATA_ARRAY_HPP
diff --git a/boost/compute/interop/vtk/matrix4x4.hpp b/boost/compute/interop/vtk/matrix4x4.hpp
new file mode 100644
index 0000000000..550c49f19f
--- /dev/null
+++ b/boost/compute/interop/vtk/matrix4x4.hpp
@@ -0,0 +1,46 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_VTK_MATRIX4X4_HPP
+#define BOOST_COMPUTE_INTEROP_VTK_MATRIX4X4_HPP
+
+#include <vtkMatrix4x4.h>
+
+#include <boost/compute/types/fundamental.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Converts a \c vtkMatrix4x4 to a \c float16_.
+inline float16_ vtk_matrix4x4_to_float16(const vtkMatrix4x4 *matrix)
+{
+ float16_ result;
+
+ for(int i = 0; i < 4; i++){
+ for(int j = 0; j < 4; j++){
+ result[i*4+j] = matrix->GetElement(i, j);
+ }
+ }
+
+ return result;
+}
+
+/// Converts a \c vtkMatrix4x4 to a \c double16_;
+inline double16_ vtk_matrix4x4_to_double16(const vtkMatrix4x4 *matrix)
+{
+ double16_ result;
+ std::memcpy(&result, matrix->Element, 16 * sizeof(double));
+ return result;
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_INTEROP_VTK_MATRIX4X4_HPP
diff --git a/boost/compute/interop/vtk/points.hpp b/boost/compute/interop/vtk/points.hpp
new file mode 100644
index 0000000000..fefbbb9874
--- /dev/null
+++ b/boost/compute/interop/vtk/points.hpp
@@ -0,0 +1,55 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_INTEROP_VTK_POINTS_HPP
+#define BOOST_COMPUTE_INTEROP_VTK_POINTS_HPP
+
+#include <vector>
+
+#include <vtkPoints.h>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Copies \p points to \p buffer.
+///
+/// For example, to copy from a \c vtkPoints object to a \c vector<float4_>:
+/// \code
+/// vtkPoints *points = ...
+/// vector<float4_> vector(points->GetNumberOfPoints(), context);
+/// vtk_copy_points_to_buffer(points, vector.begin(), queue);
+/// \endcode
+template<class PointType>
+inline void vtk_copy_points_to_buffer(const vtkPoints *points,
+ buffer_iterator<PointType> buffer,
+ command_queue &queue = system::default_queue())
+{
+ vtkPoints *points_ = const_cast<vtkPoints *>(points);
+
+ // copy points to aligned buffer
+ std::vector<PointType> tmp(points_->GetNumberOfPoints());
+ for(vtkIdType i = 0; i < points_->GetNumberOfPoints(); i++){
+ double *p = points_->GetPoint(i);
+ tmp[i] = PointType(p[0], p[1], p[2], 1);
+ }
+
+ // copy data to device
+ copy(tmp.begin(), tmp.end(), buffer, queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_INTEROP_VTK_POINTS_HPP
diff --git a/boost/compute/iterator.hpp b/boost/compute/iterator.hpp
new file mode 100644
index 0000000000..59442b1599
--- /dev/null
+++ b/boost/compute/iterator.hpp
@@ -0,0 +1,28 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ITERATOR_HPP
+#define BOOST_COMPUTE_ITERATOR_HPP
+
+/// \file
+///
+/// Meta-header to include all Boost.Compute iterator headers.
+
+#include <boost/compute/iterator/buffer_iterator.hpp>
+#include <boost/compute/iterator/constant_iterator.hpp>
+#include <boost/compute/iterator/constant_buffer_iterator.hpp>
+#include <boost/compute/iterator/counting_iterator.hpp>
+#include <boost/compute/iterator/discard_iterator.hpp>
+#include <boost/compute/iterator/function_input_iterator.hpp>
+#include <boost/compute/iterator/permutation_iterator.hpp>
+#include <boost/compute/iterator/transform_iterator.hpp>
+#include <boost/compute/iterator/zip_iterator.hpp>
+
+#endif // BOOST_COMPUTE_ITERATOR_HPP
diff --git a/boost/compute/iterator/buffer_iterator.hpp b/boost/compute/iterator/buffer_iterator.hpp
new file mode 100644
index 0000000000..cd68058f64
--- /dev/null
+++ b/boost/compute/iterator/buffer_iterator.hpp
@@ -0,0 +1,280 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ITERATOR_BUFFER_ITERATOR_HPP
+#define BOOST_COMPUTE_ITERATOR_BUFFER_ITERATOR_HPP
+
+#include <cstddef>
+#include <iterator>
+
+#include <boost/config.hpp>
+#include <boost/type_traits.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/detail/buffer_value.hpp>
+#include <boost/compute/detail/is_buffer_iterator.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/read_write_single_value.hpp>
+#include <boost/compute/type_traits/is_device_iterator.hpp>
+
+namespace boost {
+namespace compute {
+
+// forward declaration for buffer_iterator<T>
+template<class T> class buffer_iterator;
+
+namespace detail {
+
+// helper class which defines the iterator_facade super-class
+// type for buffer_iterator<T>
+template<class T>
+class buffer_iterator_base
+{
+public:
+ typedef ::boost::iterator_facade<
+ ::boost::compute::buffer_iterator<T>,
+ T,
+ ::std::random_access_iterator_tag,
+ ::boost::compute::detail::buffer_value<T>
+ > type;
+};
+
+template<class T, class IndexExpr>
+struct buffer_iterator_index_expr
+{
+ typedef T result_type;
+
+ buffer_iterator_index_expr(const buffer &buffer,
+ size_t index,
+ const memory_object::address_space address_space,
+ const IndexExpr &expr)
+ : m_buffer(buffer),
+ m_index(index),
+ m_address_space(address_space),
+ m_expr(expr)
+ {
+ }
+
+ operator T() const
+ {
+ BOOST_STATIC_ASSERT_MSG(boost::is_integral<IndexExpr>::value,
+ "Index expression must be integral");
+
+ return buffer_value<T>(m_buffer, size_t(m_expr) * sizeof(T));
+ }
+
+ const buffer &m_buffer;
+ size_t m_index;
+ memory_object::address_space m_address_space;
+ IndexExpr m_expr;
+};
+
+template<class T, class IndexExpr>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const buffer_iterator_index_expr<T, IndexExpr> &expr)
+{
+ if(expr.m_index == 0){
+ return kernel <<
+ kernel.get_buffer_identifier<T>(expr.m_buffer, expr.m_address_space) <<
+ '[' << expr.m_expr << ']';
+ }
+ else {
+ return kernel <<
+ kernel.get_buffer_identifier<T>(expr.m_buffer, expr.m_address_space) <<
+ '[' << uint_(expr.m_index) << "+(" << expr.m_expr << ")]";
+ }
+}
+
+} // end detail namespace
+
+/// \class buffer_iterator
+/// \brief An iterator for values in a buffer.
+///
+/// The buffer_iterator class iterates over values in a memory buffer on a
+/// compute device. It is the most commonly used iterator in Boost.Compute
+/// and is used by the \ref vector "vector<T>" and \ref array "array<T, N>"
+/// container classes.
+///
+/// Buffer iterators store a reference to a memory buffer along with an index
+/// into that memory buffer.
+///
+/// The buffer_iterator class allows for arbitrary OpenCL memory objects
+/// (including those created outside of Boost.Compute) to be used with the
+/// Boost.Compute algorithms (such as transform() and sort()). For example,
+/// to reverse the contents of an OpenCL memory buffer containing a set of
+/// integers:
+///
+/// \snippet test/test_buffer_iterator.cpp reverse_external_buffer
+///
+/// \see buffer, make_buffer_iterator()
+template<class T>
+class buffer_iterator : public detail::buffer_iterator_base<T>::type
+{
+public:
+ typedef typename detail::buffer_iterator_base<T>::type super_type;
+ typedef typename super_type::reference reference;
+ typedef typename super_type::difference_type difference_type;
+
+ buffer_iterator()
+ : m_index(0)
+ {
+ }
+
+ buffer_iterator(const buffer &buffer, size_t index)
+ : m_buffer(buffer.get(), false),
+ m_index(index)
+ {
+ }
+
+ buffer_iterator(const buffer_iterator<T> &other)
+ : m_buffer(other.m_buffer.get(), false),
+ m_index(other.m_index)
+ {
+ }
+
+ buffer_iterator<T>& operator=(const buffer_iterator<T> &other)
+ {
+ if(this != &other){
+ m_buffer.get() = other.m_buffer.get();
+ m_index = other.m_index;
+ }
+
+ return *this;
+ }
+
+ ~buffer_iterator()
+ {
+ // set buffer to null so that its reference count will
+ // not be decremented when its destructor is called
+ m_buffer.get() = 0;
+ }
+
+ const buffer& get_buffer() const
+ {
+ return m_buffer;
+ }
+
+ size_t get_index() const
+ {
+ return m_index;
+ }
+
+ T read(command_queue &queue) const
+ {
+ BOOST_ASSERT(m_buffer.get());
+ BOOST_ASSERT(m_index < m_buffer.size() / sizeof(T));
+
+ return detail::read_single_value<T>(m_buffer, m_index, queue);
+ }
+
+ void write(const T &value, command_queue &queue)
+ {
+ BOOST_ASSERT(m_buffer.get());
+ BOOST_ASSERT(m_index < m_buffer.size() / sizeof(T));
+
+ detail::write_single_value<T>(value, m_buffer, m_index, queue);
+ }
+
+ /// \internal_
+ template<class Expr>
+ detail::buffer_iterator_index_expr<T, Expr>
+ operator[](const Expr &expr) const
+ {
+ BOOST_ASSERT(m_buffer.get());
+
+ return detail::buffer_iterator_index_expr<T, Expr>(
+ m_buffer, m_index, memory_object::global_memory, expr
+ );
+ }
+
+private:
+ friend class ::boost::iterator_core_access;
+
+ /// \internal_
+ reference dereference() const
+ {
+ return detail::buffer_value<T>(m_buffer, m_index * sizeof(T));
+ }
+
+ /// \internal_
+ bool equal(const buffer_iterator<T> &other) const
+ {
+ return m_buffer.get() == other.m_buffer.get() &&
+ m_index == other.m_index;
+ }
+
+ /// \internal_
+ void increment()
+ {
+ m_index++;
+ }
+
+ /// \internal_
+ void decrement()
+ {
+ m_index--;
+ }
+
+ /// \internal_
+ void advance(difference_type n)
+ {
+ m_index = static_cast<size_t>(static_cast<difference_type>(m_index) + n);
+ }
+
+ /// \internal_
+ difference_type distance_to(const buffer_iterator<T> &other) const
+ {
+ return static_cast<difference_type>(other.m_index - m_index);
+ }
+
+private:
+ const buffer m_buffer;
+ size_t m_index;
+};
+
+/// Creates a new \ref buffer_iterator for \p buffer at \p index.
+///
+/// \param buffer the \ref buffer object
+/// \param index the index in the buffer
+///
+/// \return a \c buffer_iterator for \p buffer at \p index
+template<class T>
+inline buffer_iterator<T>
+make_buffer_iterator(const buffer &buffer, size_t index = 0)
+{
+ return buffer_iterator<T>(buffer, index);
+}
+
+/// \internal_ (is_device_iterator specialization for buffer_iterator)
+template<class T>
+struct is_device_iterator<buffer_iterator<T> > : boost::true_type {};
+
+namespace detail {
+
+// is_buffer_iterator specialization for buffer_iterator
+template<class Iterator>
+struct is_buffer_iterator<
+ Iterator,
+ typename boost::enable_if<
+ boost::is_same<
+ buffer_iterator<typename Iterator::value_type>,
+ typename boost::remove_const<Iterator>::type
+ >
+ >::type
+> : public boost::true_type {};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ITERATOR_BUFFER_ITERATOR_HPP
diff --git a/boost/compute/iterator/constant_buffer_iterator.hpp b/boost/compute/iterator/constant_buffer_iterator.hpp
new file mode 100644
index 0000000000..ef9a2ac959
--- /dev/null
+++ b/boost/compute/iterator/constant_buffer_iterator.hpp
@@ -0,0 +1,209 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ITERATOR_CONSTANT_BUFFER_ITERATOR_HPP
+#define BOOST_COMPUTE_ITERATOR_CONSTANT_BUFFER_ITERATOR_HPP
+
+#include <cstddef>
+#include <iterator>
+
+#include <boost/iterator/iterator_facade.hpp>
+
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+#include <boost/compute/type_traits/is_device_iterator.hpp>
+
+namespace boost {
+namespace compute {
+
+// forward declaration for constant_buffer_iterator<T>
+template<class T> class constant_buffer_iterator;
+
+namespace detail {
+
+// helper class which defines the iterator_facade super-class
+// type for constant_buffer_iterator<T>
+template<class T>
+class constant_buffer_iterator_base
+{
+public:
+ typedef ::boost::iterator_facade<
+ ::boost::compute::constant_buffer_iterator<T>,
+ T,
+ ::std::random_access_iterator_tag,
+ ::boost::compute::detail::buffer_value<T>
+ > type;
+};
+
+} // end detail namespace
+
+/// \class constant_buffer_iterator
+/// \brief An iterator for a buffer in the \c constant memory space.
+///
+/// The constant_buffer_iterator class provides an iterator for values in a
+/// buffer in the \c constant memory space.
+///
+/// For iterating over values in the \c global memory space (the most common
+/// case), use the buffer_iterator class.
+///
+/// \see buffer_iterator
+template<class T>
+class constant_buffer_iterator :
+ public detail::constant_buffer_iterator_base<T>::type
+{
+public:
+ typedef typename detail::constant_buffer_iterator_base<T>::type super_type;
+ typedef typename super_type::reference reference;
+ typedef typename super_type::difference_type difference_type;
+
+ constant_buffer_iterator()
+ : m_buffer(0),
+ m_index(0)
+ {
+ }
+
+ constant_buffer_iterator(const buffer &buffer, size_t index)
+ : m_buffer(&buffer),
+ m_index(index)
+ {
+ }
+
+ constant_buffer_iterator(const constant_buffer_iterator<T> &other)
+ : m_buffer(other.m_buffer),
+ m_index(other.m_index)
+ {
+ }
+
+ constant_buffer_iterator<T>& operator=(const constant_buffer_iterator<T> &other)
+ {
+ if(this != &other){
+ m_buffer = other.m_buffer;
+ m_index = other.m_index;
+ }
+
+ return *this;
+ }
+
+ ~constant_buffer_iterator()
+ {
+ }
+
+ const buffer& get_buffer() const
+ {
+ return *m_buffer;
+ }
+
+ size_t get_index() const
+ {
+ return m_index;
+ }
+
+ T read(command_queue &queue) const
+ {
+ BOOST_ASSERT(m_buffer && m_buffer->get());
+ BOOST_ASSERT(m_index < m_buffer->size() / sizeof(T));
+
+ return detail::read_single_value<T>(m_buffer, m_index, queue);
+ }
+
+ void write(const T &value, command_queue &queue)
+ {
+ BOOST_ASSERT(m_buffer && m_buffer->get());
+ BOOST_ASSERT(m_index < m_buffer->size() / sizeof(T));
+
+ detail::write_single_value<T>(m_buffer, m_index, queue);
+ }
+
+ template<class Expr>
+ detail::buffer_iterator_index_expr<T, Expr>
+ operator[](const Expr &expr) const
+ {
+ BOOST_ASSERT(m_buffer);
+ BOOST_ASSERT(m_buffer->get());
+
+ return detail::buffer_iterator_index_expr<T, Expr>(
+ *m_buffer, m_index, memory_object::constant_memory, expr
+ );
+ }
+
+private:
+ friend class ::boost::iterator_core_access;
+
+ reference dereference() const
+ {
+ return detail::buffer_value<T>(*m_buffer, m_index);
+ }
+
+ bool equal(const constant_buffer_iterator<T> &other) const
+ {
+ return m_buffer == other.m_buffer && m_index == other.m_index;
+ }
+
+ void increment()
+ {
+ m_index++;
+ }
+
+ void decrement()
+ {
+ m_index--;
+ }
+
+ void advance(difference_type n)
+ {
+ m_index = static_cast<size_t>(static_cast<difference_type>(m_index) + n);
+ }
+
+ difference_type distance_to(const constant_buffer_iterator<T> &other) const
+ {
+ return static_cast<difference_type>(other.m_index - m_index);
+ }
+
+private:
+ const buffer *m_buffer;
+ size_t m_index;
+};
+
+/// Creates a new constant_buffer_iterator for \p buffer at \p index.
+///
+/// \param buffer the \ref buffer object
+/// \param index the index in the buffer
+///
+/// \return a \c constant_buffer_iterator for \p buffer at \p index
+template<class T>
+inline constant_buffer_iterator<T>
+make_constant_buffer_iterator(const buffer &buffer, size_t index = 0)
+{
+ return constant_buffer_iterator<T>(buffer, index);
+}
+
+/// \internal_ (is_device_iterator specialization for constant_buffer_iterator)
+template<class T>
+struct is_device_iterator<constant_buffer_iterator<T> > : boost::true_type {};
+
+namespace detail {
+
+// is_buffer_iterator specialization for constant_buffer_iterator
+template<class Iterator>
+struct is_buffer_iterator<
+ Iterator,
+ typename boost::enable_if<
+ boost::is_same<
+ constant_buffer_iterator<typename Iterator::value_type>,
+ typename boost::remove_const<Iterator>::type
+ >
+ >::type
+> : public boost::true_type {};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ITERATOR_CONSTANT_BUFFER_ITERATOR_HPP
diff --git a/boost/compute/iterator/constant_iterator.hpp b/boost/compute/iterator/constant_iterator.hpp
new file mode 100644
index 0000000000..f0d45c02c0
--- /dev/null
+++ b/boost/compute/iterator/constant_iterator.hpp
@@ -0,0 +1,171 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ITERATOR_CONSTANT_ITERATOR_HPP
+#define BOOST_COMPUTE_ITERATOR_CONSTANT_ITERATOR_HPP
+
+#include <string>
+#include <cstddef>
+#include <iterator>
+
+#include <boost/config.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/type_traits/is_device_iterator.hpp>
+
+namespace boost {
+namespace compute {
+
+// forward declaration for constant_iterator<T>
+template<class T> class constant_iterator;
+
+namespace detail {
+
+// helper class which defines the iterator_facade super-class
+// type for constant_iterator<T>
+template<class T>
+class constant_iterator_base
+{
+public:
+ typedef ::boost::iterator_facade<
+ ::boost::compute::constant_iterator<T>,
+ T,
+ ::std::random_access_iterator_tag
+ > type;
+};
+
+} // end detail namespace
+
+/// \class constant_iterator
+/// \brief An iterator with a constant value.
+///
+/// The constant_iterator class provides an iterator which returns a constant
+/// value when dereferenced.
+///
+/// For example, this could be used to implement the fill() algorithm in terms
+/// of the copy() algorithm by copying from a range of constant iterators:
+///
+/// \snippet test/test_constant_iterator.cpp fill_with_copy
+///
+/// \see make_constant_iterator()
+template<class T>
+class constant_iterator : public detail::constant_iterator_base<T>::type
+{
+public:
+ typedef typename detail::constant_iterator_base<T>::type super_type;
+ typedef typename super_type::reference reference;
+ typedef typename super_type::difference_type difference_type;
+
+ constant_iterator(const T &value, size_t index = 0)
+ : m_value(value),
+ m_index(index)
+ {
+ }
+
+ constant_iterator(const constant_iterator<T> &other)
+ : m_value(other.m_value),
+ m_index(other.m_index)
+ {
+ }
+
+ constant_iterator<T>& operator=(const constant_iterator<T> &other)
+ {
+ if(this != &other){
+ m_value = other.m_value;
+ m_index = other.m_index;
+ }
+
+ return *this;
+ }
+
+ ~constant_iterator()
+ {
+ }
+
+ size_t get_index() const
+ {
+ return m_index;
+ }
+
+ /// \internal_
+ template<class Expr>
+ detail::meta_kernel_literal<T> operator[](const Expr &expr) const
+ {
+ (void) expr;
+
+ return detail::meta_kernel::make_lit<T>(m_value);
+ }
+
+private:
+ friend class ::boost::iterator_core_access;
+
+ /// \internal_
+ reference dereference() const
+ {
+ return m_value;
+ }
+
+ /// \internal_
+ bool equal(const constant_iterator<T> &other) const
+ {
+ return m_value == other.m_value && m_index == other.m_index;
+ }
+
+ /// \internal_
+ void increment()
+ {
+ m_index++;
+ }
+
+ /// \internal_
+ void decrement()
+ {
+ m_index--;
+ }
+
+ /// \internal_
+ void advance(difference_type n)
+ {
+ m_index = static_cast<size_t>(static_cast<difference_type>(m_index) + n);
+ }
+
+ /// \internal_
+ difference_type distance_to(const constant_iterator<T> &other) const
+ {
+ return static_cast<difference_type>(other.m_index - m_index);
+ }
+
+private:
+ T m_value;
+ size_t m_index;
+};
+
+/// Returns a new constant_iterator with \p value at \p index.
+///
+/// \param value the constant value
+/// \param index the iterators index
+///
+/// \return a \c constant_iterator with \p value
+template<class T>
+inline constant_iterator<T>
+make_constant_iterator(const T &value, size_t index = 0)
+{
+ return constant_iterator<T>(value, index);
+}
+
+/// \internal_ (is_device_iterator specialization for constant_iterator)
+template<class T>
+struct is_device_iterator<constant_iterator<T> > : boost::true_type {};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ITERATOR_CONSTANT_ITERATOR_HPP
diff --git a/boost/compute/iterator/counting_iterator.hpp b/boost/compute/iterator/counting_iterator.hpp
new file mode 100644
index 0000000000..304c1e05cf
--- /dev/null
+++ b/boost/compute/iterator/counting_iterator.hpp
@@ -0,0 +1,185 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ITERATOR_COUNTING_ITERATOR_HPP
+#define BOOST_COMPUTE_ITERATOR_COUNTING_ITERATOR_HPP
+
+#include <string>
+#include <cstddef>
+#include <iterator>
+
+#include <boost/config.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/type_traits/is_device_iterator.hpp>
+
+namespace boost {
+namespace compute {
+
+// forward declaration for counting_iterator<T>
+template<class T> class counting_iterator;
+
+namespace detail {
+
+// helper class which defines the iterator_facade super-class
+// type for counting_iterator<T>
+template<class T>
+class counting_iterator_base
+{
+public:
+ typedef ::boost::iterator_facade<
+ ::boost::compute::counting_iterator<T>,
+ T,
+ ::std::random_access_iterator_tag
+ > type;
+};
+
+template<class T, class IndexExpr>
+struct counting_iterator_index_expr
+{
+ typedef T result_type;
+
+ counting_iterator_index_expr(const T &init, const IndexExpr &expr)
+ : m_init(init),
+ m_expr(expr)
+ {
+ }
+
+ const T &m_init;
+ IndexExpr m_expr;
+};
+
+template<class T, class IndexExpr>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const counting_iterator_index_expr<T, IndexExpr> &expr)
+{
+ return kernel << '(' << expr.m_init << '+' << expr.m_expr << ')';
+}
+
+} // end detail namespace
+
+/// \class counting_iterator
+/// \brief The counting_iterator class implements a counting iterator.
+///
+/// A counting iterator returns an internal value (initialized with \p init)
+/// which is incremented each time the iterator is incremented.
+///
+/// For example, this could be used to implement the iota() algorithm in terms
+/// of the copy() algorithm by copying from a range of counting iterators:
+///
+/// \snippet test/test_counting_iterator.cpp iota_with_copy
+///
+/// \see make_counting_iterator()
+template<class T>
+class counting_iterator : public detail::counting_iterator_base<T>::type
+{
+public:
+ typedef typename detail::counting_iterator_base<T>::type super_type;
+ typedef typename super_type::reference reference;
+ typedef typename super_type::difference_type difference_type;
+
+ counting_iterator(const T &init)
+ : m_init(init)
+ {
+ }
+
+ counting_iterator(const counting_iterator<T> &other)
+ : m_init(other.m_init)
+ {
+ }
+
+ counting_iterator<T>& operator=(const counting_iterator<T> &other)
+ {
+ if(this != &other){
+ m_init = other.m_init;
+ }
+
+ return *this;
+ }
+
+ ~counting_iterator()
+ {
+ }
+
+ size_t get_index() const
+ {
+ return 0;
+ }
+
+ template<class Expr>
+ detail::counting_iterator_index_expr<T, Expr>
+ operator[](const Expr &expr) const
+ {
+ return detail::counting_iterator_index_expr<T, Expr>(m_init, expr);
+ }
+
+private:
+ friend class ::boost::iterator_core_access;
+
+ reference dereference() const
+ {
+ return m_init;
+ }
+
+ bool equal(const counting_iterator<T> &other) const
+ {
+ return m_init == other.m_init;
+ }
+
+ void increment()
+ {
+ m_init++;
+ }
+
+ void decrement()
+ {
+ m_init--;
+ }
+
+ void advance(difference_type n)
+ {
+ m_init += static_cast<T>(n);
+ }
+
+ difference_type distance_to(const counting_iterator<T> &other) const
+ {
+ return difference_type(other.m_init) - difference_type(m_init);
+ }
+
+private:
+ T m_init;
+};
+
+/// Returns a new counting_iterator starting at \p init.
+///
+/// \param init the initial value
+///
+/// \return a counting_iterator with \p init.
+///
+/// For example, to create a counting iterator which returns unsigned integers
+/// and increments from one:
+/// \code
+/// auto iter = make_counting_iterator<uint_>(1);
+/// \endcode
+template<class T>
+inline counting_iterator<T> make_counting_iterator(const T &init)
+{
+ return counting_iterator<T>(init);
+}
+
+/// \internal_ (is_device_iterator specialization for counting_iterator)
+template<class T>
+struct is_device_iterator<counting_iterator<T> > : boost::true_type {};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ITERATOR_COUNTING_ITERATOR_HPP
diff --git a/boost/compute/iterator/detail/get_base_iterator_buffer.hpp b/boost/compute/iterator/detail/get_base_iterator_buffer.hpp
new file mode 100644
index 0000000000..3d14355115
--- /dev/null
+++ b/boost/compute/iterator/detail/get_base_iterator_buffer.hpp
@@ -0,0 +1,52 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ITERATOR_DETAIL_GET_BASE_ITERATOR_BUFFER_HPP
+#define BOOST_COMPUTE_ITERATOR_DETAIL_GET_BASE_ITERATOR_BUFFER_HPP
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+// returns the buffer for an iterator adaptor's base iterator if
+// it exists, otherwise returns a null buffer object.
+template<class Iterator>
+inline const buffer&
+get_base_iterator_buffer(const Iterator &iter,
+ typename boost::enable_if<
+ is_buffer_iterator<
+ typename Iterator::base_type
+ >
+ >::type* = 0)
+{
+ return iter.base().get_buffer();
+}
+
+template<class Iterator>
+inline const buffer&
+get_base_iterator_buffer(const Iterator &iter,
+ typename boost::disable_if<
+ is_buffer_iterator<
+ typename Iterator::base_type
+ >
+ >::type* = 0)
+{
+ (void) iter;
+
+ static buffer null_buffer;
+
+ return null_buffer;
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ITERATOR_DETAIL_GET_BASE_ITERATOR_BUFFER_HPP
diff --git a/boost/compute/iterator/detail/swizzle_iterator.hpp b/boost/compute/iterator/detail/swizzle_iterator.hpp
new file mode 100644
index 0000000000..c7c3c45340
--- /dev/null
+++ b/boost/compute/iterator/detail/swizzle_iterator.hpp
@@ -0,0 +1,188 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ITERATOR_DETAIL_SWIZZLE_ITERATOR_HPP
+#define BOOST_COMPUTE_ITERATOR_DETAIL_SWIZZLE_ITERATOR_HPP
+
+#include <string>
+#include <cstddef>
+#include <iterator>
+
+#include <boost/config.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+
+#include <boost/compute/functional.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/type_traits/make_vector_type.hpp>
+#include <boost/compute/detail/is_buffer_iterator.hpp>
+#include <boost/compute/detail/read_write_single_value.hpp>
+#include <boost/compute/iterator/detail/get_base_iterator_buffer.hpp>
+#include <boost/compute/type_traits/is_device_iterator.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+// forward declaration for swizzle_iterator
+template<class InputIterator, size_t Size>
+class swizzle_iterator;
+
+// meta-function returing the value_type for a swizzle_iterator
+template<class InputIterator, size_t Size>
+struct make_swizzle_iterator_value_type
+{
+ typedef
+ typename make_vector_type<
+ typename scalar_type<
+ typename std::iterator_traits<InputIterator>::value_type
+ >::type,
+ Size
+ >::type type;
+};
+
+// helper class which defines the iterator_adaptor super-class
+// type for swizzle_iterator
+template<class InputIterator, size_t Size>
+class swizzle_iterator_base
+{
+public:
+ typedef ::boost::iterator_adaptor<
+ swizzle_iterator<InputIterator, Size>,
+ InputIterator,
+ typename make_swizzle_iterator_value_type<InputIterator, Size>::type,
+ typename std::iterator_traits<InputIterator>::iterator_category,
+ typename make_swizzle_iterator_value_type<InputIterator, Size>::type
+ > type;
+};
+
+template<class InputIterator, size_t Size, class IndexExpr>
+struct swizzle_iterator_index_expr
+{
+ typedef typename make_swizzle_iterator_value_type<InputIterator, Size>::type result_type;
+
+ swizzle_iterator_index_expr(const InputIterator &input_iter,
+ const IndexExpr &index_expr,
+ const std::string &components)
+ : m_input_iter(input_iter),
+ m_index_expr(index_expr),
+ m_components(components)
+ {
+ }
+
+ InputIterator m_input_iter;
+ IndexExpr m_index_expr;
+ std::string m_components;
+};
+
+template<class InputIterator, size_t Size, class IndexExpr>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const swizzle_iterator_index_expr<InputIterator,
+ Size,
+ IndexExpr> &expr)
+{
+ return kernel << expr.m_input_iter[expr.m_index_expr]
+ << "." << expr.m_components;
+}
+
+template<class InputIterator, size_t Size>
+class swizzle_iterator :
+ public swizzle_iterator_base<InputIterator, Size>::type
+{
+public:
+ typedef typename
+ swizzle_iterator_base<InputIterator, Size>::type
+ super_type;
+ typedef typename super_type::value_type value_type;
+ typedef typename super_type::reference reference;
+ typedef typename super_type::base_type base_type;
+ typedef typename super_type::difference_type difference_type;
+
+ BOOST_STATIC_CONSTANT(size_t, vector_size = Size);
+
+ swizzle_iterator(InputIterator iterator, const std::string &components)
+ : super_type(iterator),
+ m_components(components)
+ {
+ BOOST_ASSERT(components.size() == Size);
+ }
+
+ swizzle_iterator(const swizzle_iterator<InputIterator, Size> &other)
+ : super_type(other.base()),
+ m_components(other.m_components)
+ {
+ BOOST_ASSERT(m_components.size() == Size);
+ }
+
+ swizzle_iterator<InputIterator, Size>&
+ operator=(const swizzle_iterator<InputIterator, Size> &other)
+ {
+ if(this != &other){
+ super_type::operator=(other);
+
+ m_components = other.m_components;
+ }
+
+ return *this;
+ }
+
+ ~swizzle_iterator()
+ {
+ }
+
+ size_t get_index() const
+ {
+ return super_type::base().get_index();
+ }
+
+ const buffer& get_buffer() const
+ {
+ return get_base_iterator_buffer(*this);
+ }
+
+ template<class IndexExpression>
+ swizzle_iterator_index_expr<InputIterator, Size, IndexExpression>
+ operator[](const IndexExpression &expr) const
+ {
+ return swizzle_iterator_index_expr<InputIterator,
+ Size,
+ IndexExpression>(super_type::base(),
+ expr,
+ m_components);
+ }
+
+private:
+ friend class ::boost::iterator_core_access;
+
+ reference dereference() const
+ {
+ return reference();
+ }
+
+private:
+ std::string m_components;
+};
+
+template<size_t Size, class InputIterator>
+inline swizzle_iterator<InputIterator, Size>
+make_swizzle_iterator(InputIterator iterator, const std::string &components)
+{
+ return swizzle_iterator<InputIterator, Size>(iterator, components);
+}
+
+} // end detail namespace
+
+// is_device_iterator specialization for swizzle_iterator
+template<size_t Size, class InputIterator>
+struct is_device_iterator<detail::swizzle_iterator<InputIterator, Size> > : boost::true_type {};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ITERATOR_SWIZZLE_ITERATOR_HPP
diff --git a/boost/compute/iterator/discard_iterator.hpp b/boost/compute/iterator/discard_iterator.hpp
new file mode 100644
index 0000000000..e002cf2ac2
--- /dev/null
+++ b/boost/compute/iterator/discard_iterator.hpp
@@ -0,0 +1,170 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ITERATOR_DISCARD_ITERATOR_HPP
+#define BOOST_COMPUTE_ITERATOR_DISCARD_ITERATOR_HPP
+
+#include <string>
+#include <cstddef>
+#include <iterator>
+
+#include <boost/config.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/type_traits/is_device_iterator.hpp>
+
+namespace boost {
+namespace compute {
+
+// forward declaration for discard_iterator
+class discard_iterator;
+
+namespace detail {
+
+// helper class which defines the iterator_facade super-class
+// type for discard_iterator
+struct discard_iterator_base
+{
+ typedef ::boost::iterator_facade<
+ ::boost::compute::discard_iterator,
+ void,
+ ::std::random_access_iterator_tag,
+ void *
+ > type;
+};
+
+template<class IndexExpr>
+struct discard_iterator_index_expr
+{
+ typedef void result_type;
+
+ discard_iterator_index_expr(const IndexExpr &expr)
+ : m_expr(expr)
+ {
+ }
+
+ IndexExpr m_expr;
+};
+
+template<class IndexExpr>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const discard_iterator_index_expr<IndexExpr> &expr)
+{
+ (void) expr;
+
+ return kernel;
+}
+
+} // end detail namespace
+
+/// \class discard_iterator
+/// \brief An iterator which discards all values written to it.
+///
+/// \see make_discard_iterator(), constant_iterator
+class discard_iterator : public detail::discard_iterator_base::type
+{
+public:
+ typedef detail::discard_iterator_base::type super_type;
+ typedef super_type::reference reference;
+ typedef super_type::difference_type difference_type;
+
+ discard_iterator(size_t index = 0)
+ : m_index(index)
+ {
+ }
+
+ discard_iterator(const discard_iterator &other)
+ : m_index(other.m_index)
+ {
+ }
+
+ discard_iterator& operator=(const discard_iterator &other)
+ {
+ if(this != &other){
+ m_index = other.m_index;
+ }
+
+ return *this;
+ }
+
+ ~discard_iterator()
+ {
+ }
+
+ /// \internal_
+ template<class Expr>
+ detail::discard_iterator_index_expr<Expr>
+ operator[](const Expr &expr) const
+ {
+ return detail::discard_iterator_index_expr<Expr>(expr);
+ }
+
+private:
+ friend class ::boost::iterator_core_access;
+
+ /// \internal_
+ reference dereference() const
+ {
+ return 0;
+ }
+
+ /// \internal_
+ bool equal(const discard_iterator &other) const
+ {
+ return m_index == other.m_index;
+ }
+
+ /// \internal_
+ void increment()
+ {
+ m_index++;
+ }
+
+ /// \internal_
+ void decrement()
+ {
+ m_index--;
+ }
+
+ /// \internal_
+ void advance(difference_type n)
+ {
+ m_index = static_cast<size_t>(static_cast<difference_type>(m_index) + n);
+ }
+
+ /// \internal_
+ difference_type distance_to(const discard_iterator &other) const
+ {
+ return static_cast<difference_type>(other.m_index - m_index);
+ }
+
+private:
+ size_t m_index;
+};
+
+/// Returns a new discard_iterator with \p index.
+///
+/// \param index the index of the iterator
+///
+/// \return a \c discard_iterator at \p index
+inline discard_iterator make_discard_iterator(size_t index = 0)
+{
+ return discard_iterator(index);
+}
+
+/// internal_ (is_device_iterator specialization for discard_iterator)
+template<>
+struct is_device_iterator<discard_iterator> : boost::true_type {};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ITERATOR_DISCARD_ITERATOR_HPP
diff --git a/boost/compute/iterator/function_input_iterator.hpp b/boost/compute/iterator/function_input_iterator.hpp
new file mode 100644
index 0000000000..bd89b6c0fc
--- /dev/null
+++ b/boost/compute/iterator/function_input_iterator.hpp
@@ -0,0 +1,186 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ITERATOR_FUNCTION_INPUT_ITERATOR_HPP
+#define BOOST_COMPUTE_ITERATOR_FUNCTION_INPUT_ITERATOR_HPP
+
+#include <cstddef>
+#include <iterator>
+
+#include <boost/config.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/type_traits/is_device_iterator.hpp>
+#include <boost/compute/type_traits/result_of.hpp>
+
+namespace boost {
+namespace compute {
+
+// forward declaration for function_input_iterator<Function>
+template<class Function> class function_input_iterator;
+
+namespace detail {
+
+// helper class which defines the iterator_facade super-class
+// type for function_input_iterator<Function>
+template<class Function>
+class function_input_iterator_base
+{
+public:
+ typedef ::boost::iterator_facade<
+ ::boost::compute::function_input_iterator<Function>,
+ typename ::boost::compute::result_of<Function()>::type,
+ ::std::random_access_iterator_tag,
+ typename ::boost::compute::result_of<Function()>::type
+ > type;
+};
+
+template<class Function>
+struct function_input_iterator_expr
+{
+ typedef typename ::boost::compute::result_of<Function()>::type result_type;
+
+ function_input_iterator_expr(const Function &function)
+ : m_function(function)
+ {
+ }
+
+ Function m_function;
+};
+
+template<class Function>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const function_input_iterator_expr<Function> &expr)
+{
+ return kernel << expr.m_function();
+}
+
+} // end detail namespace
+
+/// \class function_input_iterator
+/// \brief Iterator which returns the result of a function when dereferenced
+///
+/// For example:
+///
+/// \snippet test/test_function_input_iterator.cpp generate_42
+///
+/// \see make_function_input_iterator()
+template<class Function>
+class function_input_iterator :
+ public detail::function_input_iterator_base<Function>::type
+{
+public:
+ typedef typename detail::function_input_iterator_base<Function>::type super_type;
+ typedef typename super_type::reference reference;
+ typedef typename super_type::difference_type difference_type;
+ typedef Function function;
+
+ function_input_iterator(const Function &function, size_t index = 0)
+ : m_function(function),
+ m_index(index)
+ {
+ }
+
+ function_input_iterator(const function_input_iterator<Function> &other)
+ : m_function(other.m_function),
+ m_index(other.m_index)
+ {
+ }
+
+ function_input_iterator<Function>&
+ operator=(const function_input_iterator<Function> &other)
+ {
+ if(this != &other){
+ m_function = other.m_function;
+ m_index = other.m_index;
+ }
+
+ return *this;
+ }
+
+ ~function_input_iterator()
+ {
+ }
+
+ size_t get_index() const
+ {
+ return m_index;
+ }
+
+ template<class Expr>
+ detail::function_input_iterator_expr<Function>
+ operator[](const Expr &expr) const
+ {
+ (void) expr;
+
+ return detail::function_input_iterator_expr<Function>(m_function);
+ }
+
+private:
+ friend class ::boost::iterator_core_access;
+
+ reference dereference() const
+ {
+ return reference();
+ }
+
+ bool equal(const function_input_iterator<Function> &other) const
+ {
+ return m_function == other.m_function && m_index == other.m_index;
+ }
+
+ void increment()
+ {
+ m_index++;
+ }
+
+ void decrement()
+ {
+ m_index--;
+ }
+
+ void advance(difference_type n)
+ {
+ m_index = static_cast<size_t>(static_cast<difference_type>(m_index) + n);
+ }
+
+ difference_type
+ distance_to(const function_input_iterator<Function> &other) const
+ {
+ return static_cast<difference_type>(other.m_index - m_index);
+ }
+
+private:
+ Function m_function;
+ size_t m_index;
+};
+
+/// Returns a function_input_iterator with \p function.
+///
+/// \param function function to execute when dereferenced
+/// \param index index of the iterator
+///
+/// \return a \c function_input_iterator with \p function
+template<class Function>
+inline function_input_iterator<Function>
+make_function_input_iterator(const Function &function, size_t index = 0)
+{
+ return function_input_iterator<Function>(function, index);
+}
+
+/// \internal_ (is_device_iterator specialization for function_input_iterator)
+template<class Function>
+struct is_device_iterator<function_input_iterator<Function> > : boost::true_type {};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ITERATOR_FUNCTION_INPUT_ITERATOR_HPP
diff --git a/boost/compute/iterator/permutation_iterator.hpp b/boost/compute/iterator/permutation_iterator.hpp
new file mode 100644
index 0000000000..8a7f97a402
--- /dev/null
+++ b/boost/compute/iterator/permutation_iterator.hpp
@@ -0,0 +1,192 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ITERATOR_PERMUTATION_ITERATOR_HPP
+#define BOOST_COMPUTE_ITERATOR_PERMUTATION_ITERATOR_HPP
+
+#include <string>
+#include <cstddef>
+#include <iterator>
+
+#include <boost/config.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+
+#include <boost/compute/functional.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/is_buffer_iterator.hpp>
+#include <boost/compute/detail/read_write_single_value.hpp>
+#include <boost/compute/iterator/detail/get_base_iterator_buffer.hpp>
+#include <boost/compute/type_traits/is_device_iterator.hpp>
+
+namespace boost {
+namespace compute {
+
+// forward declaration for transform_iterator
+template<class ElementIterator, class IndexIterator>
+class permutation_iterator;
+
+namespace detail {
+
+// helper class which defines the iterator_adaptor super-class
+// type for permutation_iterator
+template<class ElementIterator, class IndexIterator>
+class permutation_iterator_base
+{
+public:
+ typedef ::boost::iterator_adaptor<
+ ::boost::compute::permutation_iterator<ElementIterator, IndexIterator>,
+ ElementIterator
+ > type;
+};
+
+template<class ElementIterator, class IndexIterator, class IndexExpr>
+struct permutation_iterator_access_expr
+{
+ typedef typename std::iterator_traits<ElementIterator>::value_type result_type;
+
+ permutation_iterator_access_expr(const ElementIterator &e,
+ const IndexIterator &i,
+ const IndexExpr &expr)
+ : m_element_iter(e),
+ m_index_iter(i),
+ m_expr(expr)
+ {
+ }
+
+ ElementIterator m_element_iter;
+ IndexIterator m_index_iter;
+ IndexExpr m_expr;
+};
+
+template<class ElementIterator, class IndexIterator, class IndexExpr>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const permutation_iterator_access_expr<ElementIterator,
+ IndexIterator,
+ IndexExpr> &expr)
+{
+ return kernel << expr.m_element_iter[expr.m_index_iter[expr.m_expr]];
+}
+
+} // end detail namespace
+
+/// \class permutation_iterator
+/// \brief The permutation_iterator class provides a permuation iterator
+///
+/// A permutation iterator iterates over a value range and an index range. When
+/// dereferenced, it returns the value from the value range using the current
+/// index from the index range.
+///
+/// For example, to reverse a range using the copy() algorithm and a permutation
+/// sequence:
+///
+/// \snippet test/test_permutation_iterator.cpp reverse_range
+///
+/// \see make_permutation_iterator()
+template<class ElementIterator, class IndexIterator>
+class permutation_iterator
+ : public detail::permutation_iterator_base<ElementIterator,
+ IndexIterator>::type
+{
+public:
+ typedef typename
+ detail::permutation_iterator_base<ElementIterator,
+ IndexIterator>::type super_type;
+ typedef typename super_type::value_type value_type;
+ typedef typename super_type::reference reference;
+ typedef typename super_type::base_type base_type;
+ typedef typename super_type::difference_type difference_type;
+ typedef IndexIterator index_iterator;
+
+ permutation_iterator(ElementIterator e, IndexIterator i)
+ : super_type(e),
+ m_map(i)
+ {
+ }
+
+ permutation_iterator(const permutation_iterator<ElementIterator,
+ IndexIterator> &other)
+ : super_type(other),
+ m_map(other.m_map)
+ {
+ }
+
+ permutation_iterator<ElementIterator, IndexIterator>&
+ operator=(const permutation_iterator<ElementIterator,
+ IndexIterator> &other)
+ {
+ if(this != &other){
+ super_type::operator=(other);
+ m_map = other.m_map;
+ }
+
+ return *this;
+ }
+
+ ~permutation_iterator()
+ {
+ }
+
+ size_t get_index() const
+ {
+ return super_type::base().get_index();
+ }
+
+ const buffer& get_buffer() const
+ {
+ return detail::get_base_iterator_buffer(*this);
+ }
+
+ template<class IndexExpr>
+ detail::permutation_iterator_access_expr<ElementIterator,
+ IndexIterator,
+ IndexExpr>
+ operator[](const IndexExpr &expr) const
+ {
+ return detail::permutation_iterator_access_expr<ElementIterator,
+ IndexIterator,
+ IndexExpr>(super_type::base(),
+ m_map,
+ expr);
+ }
+
+private:
+ friend class ::boost::iterator_core_access;
+
+ reference dereference() const
+ {
+ return reference();
+ }
+
+private:
+ IndexIterator m_map;
+};
+
+/// Returns a permutation_iterator for \p e using indices from \p i.
+///
+/// \param e the element range iterator
+/// \param i the index range iterator
+///
+/// \return a \c permutation_iterator for \p e using \p i
+template<class ElementIterator, class IndexIterator>
+inline permutation_iterator<ElementIterator, IndexIterator>
+make_permutation_iterator(ElementIterator e, IndexIterator i)
+{
+ return permutation_iterator<ElementIterator, IndexIterator>(e, i);
+}
+
+/// \internal_ (is_device_iterator specialization for permutation_iterator)
+template<class ElementIterator, class IndexIterator>
+struct is_device_iterator<
+ permutation_iterator<ElementIterator, IndexIterator> > : boost::true_type {};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ITERATOR_PERMUTATION_ITERATOR_HPP
diff --git a/boost/compute/iterator/strided_iterator.hpp b/boost/compute/iterator/strided_iterator.hpp
new file mode 100644
index 0000000000..52e7f07bd8
--- /dev/null
+++ b/boost/compute/iterator/strided_iterator.hpp
@@ -0,0 +1,296 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2015 Jakub Szuppe <j.szuppe@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ITERATOR_STRIDED_ITERATOR_HPP
+#define BOOST_COMPUTE_ITERATOR_STRIDED_ITERATOR_HPP
+
+#include <cstddef>
+#include <iterator>
+
+#include <boost/config.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+
+#include <boost/compute/functional.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/is_buffer_iterator.hpp>
+#include <boost/compute/detail/read_write_single_value.hpp>
+#include <boost/compute/iterator/detail/get_base_iterator_buffer.hpp>
+#include <boost/compute/type_traits/is_device_iterator.hpp>
+#include <boost/compute/type_traits/result_of.hpp>
+
+namespace boost {
+namespace compute {
+
+// forward declaration for strided_iterator
+template<class Iterator>
+class strided_iterator;
+
+namespace detail {
+
+// helper class which defines the iterator_adaptor super-class
+// type for strided_iterator
+template<class Iterator>
+class strided_iterator_base
+{
+public:
+ typedef ::boost::iterator_adaptor<
+ ::boost::compute::strided_iterator<Iterator>,
+ Iterator
+ > type;
+};
+
+// helper class for including stride value in index expression
+template<class IndexExpr, class Stride>
+struct stride_expr
+{
+ stride_expr(const IndexExpr &expr, const Stride &stride)
+ : m_index_expr(expr),
+ m_stride(stride)
+ {
+ }
+
+ IndexExpr m_index_expr;
+ Stride m_stride;
+};
+
+template<class IndexExpr, class Stride>
+inline stride_expr<IndexExpr, Stride> make_stride_expr(const IndexExpr &expr,
+ const Stride &stride)
+{
+ return stride_expr<IndexExpr, Stride>(expr, stride);
+}
+
+template<class IndexExpr, class Stride>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const stride_expr<IndexExpr, Stride> &expr)
+{
+ // (expr.m_stride * (expr.m_index_expr))
+ return kernel << "(" << static_cast<ulong_>(expr.m_stride)
+ << " * (" << expr.m_index_expr << "))";
+}
+
+template<class Iterator, class Stride, class IndexExpr>
+struct strided_iterator_index_expr
+{
+ typedef typename std::iterator_traits<Iterator>::value_type result_type;
+
+ strided_iterator_index_expr(const Iterator &input_iter,
+ const Stride &stride,
+ const IndexExpr &index_expr)
+ : m_input_iter(input_iter),
+ m_stride(stride),
+ m_index_expr(index_expr)
+ {
+ }
+
+ Iterator m_input_iter;
+ const Stride& m_stride;
+ IndexExpr m_index_expr;
+};
+
+template<class Iterator, class Stride, class IndexExpr>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const strided_iterator_index_expr<Iterator,
+ Stride,
+ IndexExpr> &expr)
+{
+ return kernel << expr.m_input_iter[make_stride_expr(expr.m_index_expr, expr.m_stride)];
+}
+
+} // end detail namespace
+
+/// \class strided_iterator
+/// \brief An iterator adaptor with adjustable iteration step.
+///
+/// The strided iterator adaptor skips over multiple elements each time
+/// it is incremented or decremented.
+///
+/// \see buffer_iterator, make_strided_iterator(), make_strided_iterator_end()
+template<class Iterator>
+class strided_iterator :
+ public detail::strided_iterator_base<Iterator>::type
+{
+public:
+ typedef typename
+ detail::strided_iterator_base<Iterator>::type super_type;
+ typedef typename super_type::value_type value_type;
+ typedef typename super_type::reference reference;
+ typedef typename super_type::base_type base_type;
+ typedef typename super_type::difference_type difference_type;
+
+ strided_iterator(Iterator iterator, difference_type stride)
+ : super_type(iterator),
+ m_stride(static_cast<difference_type>(stride))
+ {
+ // stride must be greater than zero
+ BOOST_ASSERT_MSG(stride > 0, "Stride must be greater than zero");
+ }
+
+ strided_iterator(const strided_iterator<Iterator> &other)
+ : super_type(other.base()),
+ m_stride(other.m_stride)
+ {
+ }
+
+ strided_iterator<Iterator>&
+ operator=(const strided_iterator<Iterator> &other)
+ {
+ if(this != &other){
+ super_type::operator=(other);
+
+ m_stride = other.m_stride;
+ }
+
+ return *this;
+ }
+
+ ~strided_iterator()
+ {
+ }
+
+ size_t get_index() const
+ {
+ return super_type::base().get_index();
+ }
+
+ const buffer& get_buffer() const
+ {
+ return detail::get_base_iterator_buffer(*this);
+ }
+
+ template<class IndexExpression>
+ detail::strided_iterator_index_expr<Iterator, difference_type, IndexExpression>
+ operator[](const IndexExpression &expr) const
+ {
+ typedef
+ typename detail::strided_iterator_index_expr<Iterator,
+ difference_type,
+ IndexExpression>
+ StridedIndexExprType;
+ return StridedIndexExprType(super_type::base(),m_stride, expr);
+ }
+
+private:
+ friend class ::boost::iterator_core_access;
+
+ reference dereference() const
+ {
+ return reference();
+ }
+
+ bool equal(const strided_iterator<Iterator> &other) const
+ {
+ return (other.m_stride == m_stride)
+ && (other.base_reference() == this->base_reference());
+ }
+
+ void increment()
+ {
+ std::advance(super_type::base_reference(), m_stride);
+ }
+
+ void decrement()
+ {
+ std::advance(super_type::base_reference(),-m_stride);
+ }
+
+ void advance(typename super_type::difference_type n)
+ {
+ std::advance(super_type::base_reference(), n * m_stride);
+ }
+
+ difference_type distance_to(const strided_iterator<Iterator> &other) const
+ {
+ return std::distance(this->base_reference(), other.base_reference()) / m_stride;
+ }
+
+private:
+ difference_type m_stride;
+};
+
+/// Returns a strided_iterator for \p iterator with \p stride.
+///
+/// \param iterator the underlying iterator
+/// \param stride the iteration step for strided_iterator
+///
+/// \return a \c strided_iterator for \p iterator with \p stride.
+///
+/// For example, to create an iterator which iterates over every other
+/// element in a \c vector<int>:
+/// \code
+/// auto strided_iterator = make_strided_iterator(vec.begin(), 2);
+/// \endcode
+template<class Iterator>
+inline strided_iterator<Iterator>
+make_strided_iterator(Iterator iterator,
+ typename std::iterator_traits<Iterator>::difference_type stride)
+{
+ return strided_iterator<Iterator>(iterator, stride);
+}
+
+/// Returns a strided_iterator which refers to element that would follow
+/// the last element accessible through strided_iterator for \p first iterator
+/// with \p stride.
+///
+/// Parameter \p stride must be greater than zero.
+///
+/// \param first the iterator referring to the first element accessible
+/// through strided_iterator for \p first with \p stride
+/// \param last the iterator referring to the last element that may be
+//// accessible through strided_iterator for \p first with \p stride
+/// \param stride the iteration step
+///
+/// \return a \c strided_iterator referring to element that would follow
+/// the last element accessible through strided_iterator for \p first
+/// iterator with \p stride.
+///
+/// It can be helpful when iterating over strided_iterator:
+/// \code
+/// // vec.size() may not be divisible by 3
+/// auto strided_iterator_begin = make_strided_iterator(vec.begin(), 3);
+/// auto strided_iterator_end = make_strided_iterator_end(vec.begin(), vec.end(), 3);
+///
+/// // copy every 3rd element to result
+/// boost::compute::copy(
+/// strided_iterator_begin,
+/// strided_iterator_end,
+/// result.begin(),
+/// queue
+/// );
+/// \endcode
+template<class Iterator>
+strided_iterator<Iterator>
+make_strided_iterator_end(Iterator first,
+ Iterator last,
+ typename std::iterator_traits<Iterator>::difference_type stride)
+{
+ typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
+
+ // calculate distance from end to the last element that would be
+ // accessible through strided_iterator.
+ difference_type range = std::distance(first, last);
+ difference_type d = (range - 1) / stride;
+ d *= stride;
+ d -= range;
+ // advance from end to the element that would follow the last
+ // accessible element
+ Iterator end_for_strided_iterator = last;
+ std::advance(end_for_strided_iterator, d + stride);
+ return strided_iterator<Iterator>(end_for_strided_iterator, stride);
+}
+
+/// \internal_ (is_device_iterator specialization for strided_iterator)
+template<class Iterator>
+struct is_device_iterator<strided_iterator<Iterator> > : boost::true_type {};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ITERATOR_STRIDED_ITERATOR_HPP
diff --git a/boost/compute/iterator/transform_iterator.hpp b/boost/compute/iterator/transform_iterator.hpp
new file mode 100644
index 0000000000..c040922f9d
--- /dev/null
+++ b/boost/compute/iterator/transform_iterator.hpp
@@ -0,0 +1,227 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ITERATOR_TRANSFORM_ITERATOR_HPP
+#define BOOST_COMPUTE_ITERATOR_TRANSFORM_ITERATOR_HPP
+
+#include <cstddef>
+#include <iterator>
+
+#include <boost/config.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+
+#include <boost/compute/functional.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/is_buffer_iterator.hpp>
+#include <boost/compute/detail/read_write_single_value.hpp>
+#include <boost/compute/iterator/detail/get_base_iterator_buffer.hpp>
+#include <boost/compute/type_traits/is_device_iterator.hpp>
+#include <boost/compute/type_traits/result_of.hpp>
+
+namespace boost {
+namespace compute {
+
+// forward declaration for transform_iterator
+template<class InputIterator, class UnaryFunction>
+class transform_iterator;
+
+namespace detail {
+
+// meta-function returning the value_type for a transform_iterator
+template<class InputIterator, class UnaryFunction>
+struct make_transform_iterator_value_type
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type value_type;
+
+ typedef typename boost::compute::result_of<UnaryFunction(value_type)>::type type;
+};
+
+// helper class which defines the iterator_adaptor super-class
+// type for transform_iterator
+template<class InputIterator, class UnaryFunction>
+class transform_iterator_base
+{
+public:
+ typedef ::boost::iterator_adaptor<
+ ::boost::compute::transform_iterator<InputIterator, UnaryFunction>,
+ InputIterator,
+ typename make_transform_iterator_value_type<InputIterator, UnaryFunction>::type,
+ typename std::iterator_traits<InputIterator>::iterator_category,
+ typename make_transform_iterator_value_type<InputIterator, UnaryFunction>::type
+ > type;
+};
+
+template<class InputIterator, class UnaryFunction, class IndexExpr>
+struct transform_iterator_index_expr
+{
+ typedef typename
+ make_transform_iterator_value_type<
+ InputIterator,
+ UnaryFunction
+ >::type result_type;
+
+ transform_iterator_index_expr(const InputIterator &input_iter,
+ const UnaryFunction &transform_expr,
+ const IndexExpr &index_expr)
+ : m_input_iter(input_iter),
+ m_transform_expr(transform_expr),
+ m_index_expr(index_expr)
+ {
+ }
+
+ InputIterator m_input_iter;
+ UnaryFunction m_transform_expr;
+ IndexExpr m_index_expr;
+};
+
+template<class InputIterator, class UnaryFunction, class IndexExpr>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const transform_iterator_index_expr<InputIterator,
+ UnaryFunction,
+ IndexExpr> &expr)
+{
+ return kernel << expr.m_transform_expr(expr.m_input_iter[expr.m_index_expr]);
+}
+
+} // end detail namespace
+
+/// \class transform_iterator
+/// \brief A transform iterator adaptor.
+///
+/// The transform_iterator adaptor applies a unary function to each element
+/// produced from the underlying iterator when dereferenced.
+///
+/// For example, to copy from an input range to an output range while taking
+/// the absolute value of each element:
+///
+/// \snippet test/test_transform_iterator.cpp copy_abs
+///
+/// \see buffer_iterator, make_transform_iterator()
+template<class InputIterator, class UnaryFunction>
+class transform_iterator :
+ public detail::transform_iterator_base<InputIterator, UnaryFunction>::type
+{
+public:
+ typedef typename
+ detail::transform_iterator_base<InputIterator,
+ UnaryFunction>::type super_type;
+ typedef typename super_type::value_type value_type;
+ typedef typename super_type::reference reference;
+ typedef typename super_type::base_type base_type;
+ typedef typename super_type::difference_type difference_type;
+ typedef UnaryFunction unary_function;
+
+ transform_iterator(InputIterator iterator, UnaryFunction transform)
+ : super_type(iterator),
+ m_transform(transform)
+ {
+ }
+
+ transform_iterator(const transform_iterator<InputIterator,
+ UnaryFunction> &other)
+ : super_type(other.base()),
+ m_transform(other.m_transform)
+ {
+ }
+
+ transform_iterator<InputIterator, UnaryFunction>&
+ operator=(const transform_iterator<InputIterator,
+ UnaryFunction> &other)
+ {
+ if(this != &other){
+ super_type::operator=(other);
+
+ m_transform = other.m_transform;
+ }
+
+ return *this;
+ }
+
+ ~transform_iterator()
+ {
+ }
+
+ size_t get_index() const
+ {
+ return super_type::base().get_index();
+ }
+
+ const buffer& get_buffer() const
+ {
+ return detail::get_base_iterator_buffer(*this);
+ }
+
+ template<class IndexExpression>
+ detail::transform_iterator_index_expr<InputIterator, UnaryFunction, IndexExpression>
+ operator[](const IndexExpression &expr) const
+ {
+ return detail::transform_iterator_index_expr<InputIterator,
+ UnaryFunction,
+ IndexExpression>(super_type::base(),
+ m_transform,
+ expr);
+ }
+
+private:
+ friend class ::boost::iterator_core_access;
+
+ reference dereference() const
+ {
+ const context &context = super_type::base().get_buffer().get_context();
+ command_queue queue(context, context.get_device());
+
+ detail::meta_kernel k("read");
+ size_t output_arg = k.add_arg<value_type *>(memory_object::global_memory, "output");
+ k << "*output = " << m_transform(super_type::base()[k.lit(0)]) << ";";
+
+ kernel kernel = k.compile(context);
+
+ buffer output_buffer(context, sizeof(value_type));
+
+ kernel.set_arg(output_arg, output_buffer);
+
+ queue.enqueue_task(kernel);
+
+ return detail::read_single_value<value_type>(output_buffer, queue);
+ }
+
+private:
+ UnaryFunction m_transform;
+};
+
+/// Returns a transform_iterator for \p iterator with \p transform.
+///
+/// \param iterator the underlying iterator
+/// \param transform the unary transform function
+///
+/// \return a \c transform_iterator for \p iterator with \p transform
+///
+/// For example, to create an iterator which returns the square-root of each
+/// value in a \c vector<int>:
+/// \code
+/// auto sqrt_iterator = make_transform_iterator(vec.begin(), sqrt<int>());
+/// \endcode
+template<class InputIterator, class UnaryFunction>
+inline transform_iterator<InputIterator, UnaryFunction>
+make_transform_iterator(InputIterator iterator, UnaryFunction transform)
+{
+ return transform_iterator<InputIterator,
+ UnaryFunction>(iterator, transform);
+}
+
+/// \internal_ (is_device_iterator specialization for transform_iterator)
+template<class InputIterator, class UnaryFunction>
+struct is_device_iterator<
+ transform_iterator<InputIterator, UnaryFunction> > : boost::true_type {};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ITERATOR_TRANSFORM_ITERATOR_HPP
diff --git a/boost/compute/iterator/zip_iterator.hpp b/boost/compute/iterator/zip_iterator.hpp
new file mode 100644
index 0000000000..2860d73a93
--- /dev/null
+++ b/boost/compute/iterator/zip_iterator.hpp
@@ -0,0 +1,316 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ITERATOR_ZIP_ITERATOR_HPP
+#define BOOST_COMPUTE_ITERATOR_ZIP_ITERATOR_HPP
+
+#include <cstddef>
+#include <iterator>
+
+#include <boost/config.hpp>
+#include <boost/fusion/algorithm/iteration/for_each.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/mpl/transform.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/preprocessor/repetition.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/tuple/tuple_comparison.hpp>
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/mpl_vector_to_tuple.hpp>
+#include <boost/compute/types/tuple.hpp>
+#include <boost/compute/type_traits/is_device_iterator.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+
+namespace boost {
+namespace compute {
+
+// forward declaration for zip_iterator
+template<class IteratorTuple>
+class zip_iterator;
+
+namespace detail {
+
+namespace mpl = boost::mpl;
+
+// meta-function returning the value_type for an iterator
+template<class Iterator>
+struct make_iterator_value_type
+{
+ typedef typename std::iterator_traits<Iterator>::value_type type;
+};
+
+// meta-function returning the value_type for a zip_iterator
+template<class IteratorTuple>
+struct make_zip_iterator_value_type
+{
+ typedef typename
+ detail::mpl_vector_to_tuple<
+ typename mpl::transform<
+ IteratorTuple,
+ make_iterator_value_type<mpl::_1>,
+ mpl::back_inserter<mpl::vector<> >
+ >::type
+ >::type type;
+};
+
+// helper class which defines the iterator_facade super-class
+// type for zip_iterator
+template<class IteratorTuple>
+class zip_iterator_base
+{
+public:
+ typedef ::boost::iterator_facade<
+ ::boost::compute::zip_iterator<IteratorTuple>,
+ typename make_zip_iterator_value_type<IteratorTuple>::type,
+ ::std::random_access_iterator_tag,
+ typename make_zip_iterator_value_type<IteratorTuple>::type
+ > type;
+};
+
+template<class IteratorTuple, class IndexExpr>
+struct zip_iterator_index_expr
+{
+ typedef typename
+ make_zip_iterator_value_type<IteratorTuple>::type
+ result_type;
+
+ zip_iterator_index_expr(const IteratorTuple &iterators,
+ const IndexExpr &index_expr)
+ : m_iterators(iterators),
+ m_index_expr(index_expr)
+ {
+ }
+
+ IteratorTuple m_iterators;
+ IndexExpr m_index_expr;
+};
+
+/// \internal_
+#define BOOST_COMPUTE_PRINT_ELEM(z, n, unused) \
+ BOOST_PP_EXPR_IF(n, << ", ") \
+ << boost::get<n>(expr.m_iterators)[expr.m_index_expr]
+
+/// \internal_
+#define BOOST_COMPUTE_PRINT_ZIP_IDX(z, n, unused) \
+template<BOOST_PP_ENUM_PARAMS(n, class Iterator), class IndexExpr> \
+inline meta_kernel& operator<<( \
+ meta_kernel &kernel, \
+ const zip_iterator_index_expr< \
+ boost::tuple<BOOST_PP_ENUM_PARAMS(n, Iterator)>, \
+ IndexExpr \
+ > &expr) \
+{ \
+ typedef typename \
+ boost::tuple<BOOST_PP_ENUM_PARAMS(n, Iterator)> \
+ tuple_type; \
+ typedef typename \
+ make_zip_iterator_value_type<tuple_type>::type \
+ value_type; \
+ kernel.inject_type<value_type>(); \
+ return kernel \
+ << "(" << type_name<value_type>() << ")" \
+ << "{ " \
+ BOOST_PP_REPEAT(n, BOOST_COMPUTE_PRINT_ELEM, ~) \
+ << "}"; \
+}
+
+BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_PRINT_ZIP_IDX, ~)
+
+#undef BOOST_COMPUTE_PRINT_ZIP_IDX
+#undef BOOST_COMPUTE_PRINT_ELEM
+
+struct iterator_advancer
+{
+ iterator_advancer(size_t n)
+ : m_distance(n)
+ {
+ }
+
+ template<class Iterator>
+ void operator()(Iterator &i) const
+ {
+ std::advance(i, m_distance);
+ }
+
+ size_t m_distance;
+};
+
+template<class Iterator>
+void increment_iterator(Iterator &i)
+{
+ i++;
+}
+
+template<class Iterator>
+void decrement_iterator(Iterator &i)
+{
+ i--;
+}
+
+} // end detail namespace
+
+/// \class zip_iterator
+/// \brief A zip iterator adaptor.
+///
+/// The zip_iterator class combines values from multiple input iterators. When
+/// dereferenced it returns a tuple containing each value at the current
+/// position in each input range.
+///
+/// \see make_zip_iterator()
+template<class IteratorTuple>
+class zip_iterator : public detail::zip_iterator_base<IteratorTuple>::type
+{
+public:
+ typedef typename
+ detail::zip_iterator_base<IteratorTuple>::type
+ super_type;
+ typedef typename super_type::value_type value_type;
+ typedef typename super_type::reference reference;
+ typedef typename super_type::difference_type difference_type;
+ typedef IteratorTuple iterator_tuple;
+
+ zip_iterator(IteratorTuple iterators)
+ : m_iterators(iterators)
+ {
+ }
+
+ zip_iterator(const zip_iterator<IteratorTuple> &other)
+ : m_iterators(other.m_iterators)
+ {
+ }
+
+ zip_iterator<IteratorTuple>&
+ operator=(const zip_iterator<IteratorTuple> &other)
+ {
+ if(this != &other){
+ super_type::operator=(other);
+
+ m_iterators = other.m_iterators;
+ }
+
+ return *this;
+ }
+
+ ~zip_iterator()
+ {
+ }
+
+ const IteratorTuple& get_iterator_tuple() const
+ {
+ return m_iterators;
+ }
+
+ template<class IndexExpression>
+ detail::zip_iterator_index_expr<IteratorTuple, IndexExpression>
+ operator[](const IndexExpression &expr) const
+ {
+ return detail::zip_iterator_index_expr<IteratorTuple,
+ IndexExpression>(m_iterators,
+ expr);
+ }
+
+private:
+ friend class ::boost::iterator_core_access;
+
+ reference dereference() const
+ {
+ return reference();
+ }
+
+ bool equal(const zip_iterator<IteratorTuple> &other) const
+ {
+ return m_iterators == other.m_iterators;
+ }
+
+ void increment()
+ {
+ boost::fusion::for_each(m_iterators, detail::increment_iterator);
+ }
+
+ void decrement()
+ {
+ boost::fusion::for_each(m_iterators, detail::decrement_iterator);
+ }
+
+ void advance(difference_type n)
+ {
+ boost::fusion::for_each(m_iterators, detail::iterator_advancer(n));
+ }
+
+ difference_type distance_to(const zip_iterator<IteratorTuple> &other) const
+ {
+ return std::distance(boost::get<0>(m_iterators),
+ boost::get<0>(other.m_iterators));
+ }
+
+private:
+ IteratorTuple m_iterators;
+};
+
+/// Creates a zip_iterator for \p iterators.
+///
+/// \param iterators a tuple of input iterators to zip together
+///
+/// \return a \c zip_iterator for \p iterators
+///
+/// For example, to zip together iterators from three vectors (\c a, \c b, and
+/// \p c):
+/// \code
+/// auto zipped = boost::compute::make_zip_iterator(
+/// boost::make_tuple(a.begin(), b.begin(), c.begin())
+/// );
+/// \endcode
+template<class IteratorTuple>
+inline zip_iterator<IteratorTuple>
+make_zip_iterator(IteratorTuple iterators)
+{
+ return zip_iterator<IteratorTuple>(iterators);
+}
+
+/// \internal_ (is_device_iterator specialization for zip_iterator)
+template<class IteratorTuple>
+struct is_device_iterator<zip_iterator<IteratorTuple> > : boost::true_type {};
+
+namespace detail {
+
+// get<N>() specialization for zip_iterator
+/// \internal_
+#define BOOST_COMPUTE_ZIP_GET_N(z, n, unused) \
+template<size_t N, class IteratorTuple, class IndexExpr, \
+ BOOST_PP_ENUM_PARAMS(n, class T)> \
+inline meta_kernel& \
+operator<<(meta_kernel &kernel, \
+ const invoked_get< \
+ N, \
+ zip_iterator_index_expr<IteratorTuple, IndexExpr>, \
+ boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> \
+ > &expr) \
+{ \
+ typedef typename boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> Tuple; \
+ typedef typename boost::tuples::element<N, Tuple>::type T; \
+ BOOST_STATIC_ASSERT(N < size_t(boost::tuples::length<Tuple>::value)); \
+ kernel.inject_type<T>(); \
+ return kernel \
+ << boost::get<N>(expr.m_arg.m_iterators)[expr.m_arg.m_index_expr]; \
+}
+
+BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_ZIP_GET_N, ~)
+
+#undef BOOST_COMPUTE_ZIP_GET_N
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ITERATOR_ZIP_ITERATOR_HPP
diff --git a/boost/compute/kernel.hpp b/boost/compute/kernel.hpp
new file mode 100644
index 0000000000..9494e46de2
--- /dev/null
+++ b/boost/compute/kernel.hpp
@@ -0,0 +1,394 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_KERNEL_HPP
+#define BOOST_COMPUTE_KERNEL_HPP
+
+#include <string>
+
+#include <boost/assert.hpp>
+#include <boost/utility/enable_if.hpp>
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/program.hpp>
+#include <boost/compute/exception.hpp>
+#include <boost/compute/type_traits/is_fundamental.hpp>
+#include <boost/compute/detail/get_object_info.hpp>
+#include <boost/compute/detail/assert_cl_success.hpp>
+#include <boost/compute/memory/svm_ptr.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class T> struct set_kernel_arg;
+
+} // end detail namespace
+
+/// \class kernel
+/// \brief A compute kernel.
+///
+/// \see command_queue, program
+class kernel
+{
+public:
+ /// Creates a null kernel object.
+ kernel()
+ : m_kernel(0)
+ {
+ }
+
+ /// Creates a new kernel object for \p kernel. If \p retain is
+ /// \c true, the reference count for \p kernel will be incremented.
+ explicit kernel(cl_kernel kernel, bool retain = true)
+ : m_kernel(kernel)
+ {
+ if(m_kernel && retain){
+ clRetainKernel(m_kernel);
+ }
+ }
+
+ /// Creates a new kernel object with \p name from \p program.
+ kernel(const program &program, const std::string &name)
+ {
+ cl_int error = 0;
+ m_kernel = clCreateKernel(program.get(), name.c_str(), &error);
+
+ if(!m_kernel){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+ }
+
+ /// Creates a new kernel object as a copy of \p other.
+ kernel(const kernel &other)
+ : m_kernel(other.m_kernel)
+ {
+ if(m_kernel){
+ clRetainKernel(m_kernel);
+ }
+ }
+
+ /// Copies the kernel object from \p other to \c *this.
+ kernel& operator=(const kernel &other)
+ {
+ if(this != &other){
+ if(m_kernel){
+ clReleaseKernel(m_kernel);
+ }
+
+ m_kernel = other.m_kernel;
+
+ if(m_kernel){
+ clRetainKernel(m_kernel);
+ }
+ }
+
+ return *this;
+ }
+
+ #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+ /// Move-constructs a new kernel object from \p other.
+ kernel(kernel&& other) BOOST_NOEXCEPT
+ : m_kernel(other.m_kernel)
+ {
+ other.m_kernel = 0;
+ }
+
+ /// Move-assigns the kernel from \p other to \c *this.
+ kernel& operator=(kernel&& other) BOOST_NOEXCEPT
+ {
+ if(m_kernel){
+ clReleaseKernel(m_kernel);
+ }
+
+ m_kernel = other.m_kernel;
+ other.m_kernel = 0;
+
+ return *this;
+ }
+ #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+ /// Destroys the kernel object.
+ ~kernel()
+ {
+ if(m_kernel){
+ BOOST_COMPUTE_ASSERT_CL_SUCCESS(
+ clReleaseKernel(m_kernel)
+ );
+ }
+ }
+
+ /// Returns a reference to the underlying OpenCL kernel object.
+ cl_kernel& get() const
+ {
+ return const_cast<cl_kernel &>(m_kernel);
+ }
+
+ /// Returns the function name for the kernel.
+ std::string name() const
+ {
+ return get_info<std::string>(CL_KERNEL_FUNCTION_NAME);
+ }
+
+ /// Returns the number of arguments for the kernel.
+ size_t arity() const
+ {
+ return get_info<cl_uint>(CL_KERNEL_NUM_ARGS);
+ }
+
+ /// Returns the program for the kernel.
+ program get_program() const
+ {
+ return program(get_info<cl_program>(CL_KERNEL_PROGRAM));
+ }
+
+ /// Returns the context for the kernel.
+ context get_context() const
+ {
+ return context(get_info<cl_context>(CL_KERNEL_CONTEXT));
+ }
+
+ /// Returns information about the kernel.
+ ///
+ /// \see_opencl_ref{clGetKernelInfo}
+ template<class T>
+ T get_info(cl_kernel_info info) const
+ {
+ return detail::get_object_info<T>(clGetKernelInfo, m_kernel, info);
+ }
+
+ /// \overload
+ template<int Enum>
+ typename detail::get_object_info_type<kernel, Enum>::type
+ get_info() const;
+
+ #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ /// Returns information about the argument at \p index.
+ ///
+ /// For example, to get the name of the first argument:
+ /// \code
+ /// std::string arg = kernel.get_arg_info<std::string>(0, CL_KERNEL_ARG_NAME);
+ /// \endcode
+ ///
+ /// Note, this function requires that the program be compiled with the
+ /// \c "-cl-kernel-arg-info" flag. For example:
+ /// \code
+ /// program.build("-cl-kernel-arg-info");
+ /// \endcode
+ ///
+ /// \opencl_version_warning{1,2}
+ ///
+ /// \see_opencl_ref{clGetKernelArgInfo}
+ template<class T>
+ T get_arg_info(size_t index, cl_kernel_arg_info info) const
+ {
+ return detail::get_object_info<T>(clGetKernelArgInfo, m_kernel, info, index);
+ }
+ #endif // CL_VERSION_1_2
+
+ /// Returns work-group information for the kernel with \p device.
+ ///
+ /// \see_opencl_ref{clGetKernelWorkGroupInfo}
+ template<class T>
+ T get_work_group_info(const device &device, cl_kernel_work_group_info info) const
+ {
+ return detail::get_object_info<T>(clGetKernelWorkGroupInfo, m_kernel, info, device.id());
+ }
+
+ /// Sets the argument at \p index to \p value with \p size.
+ ///
+ /// \see_opencl_ref{clSetKernelArg}
+ void set_arg(size_t index, size_t size, const void *value)
+ {
+ BOOST_ASSERT(index < arity());
+
+ cl_int ret = clSetKernelArg(m_kernel,
+ static_cast<cl_uint>(index),
+ size,
+ value);
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+ }
+
+ /// Sets the argument at \p index to \p value.
+ ///
+ /// For built-in types (e.g. \c float, \c int4_), this is equivalent to
+ /// calling set_arg(index, sizeof(type), &value).
+ ///
+ /// Additionally, this method is specialized for device memory objects
+ /// such as buffer and image2d. This allows for them to be passed directly
+ /// without having to extract their underlying cl_mem object.
+ ///
+ /// This method is also specialized for device container types such as
+ /// vector<T> and array<T, N>. This allows for them to be passed directly
+ /// as kernel arguments without having to extract their underlying buffer.
+ ///
+ /// For setting local memory arguments (e.g. "__local float *buf"), the
+ /// local_buffer<T> class may be used:
+ /// \code
+ /// // set argument to a local buffer with storage for 32 float's
+ /// kernel.set_arg(0, local_buffer<float>(32));
+ /// \endcode
+ template<class T>
+ void set_arg(size_t index, const T &value)
+ {
+ // if you get a compilation error pointing here it means you
+ // attempted to set a kernel argument from an invalid type.
+ detail::set_kernel_arg<T>()(*this, index, value);
+ }
+
+ /// \internal_
+ void set_arg(size_t index, const cl_mem mem)
+ {
+ set_arg(index, sizeof(cl_mem), static_cast<const void *>(&mem));
+ }
+
+ /// \internal_
+ void set_arg(size_t index, const cl_sampler sampler)
+ {
+ set_arg(index, sizeof(cl_sampler), static_cast<const void *>(&sampler));
+ }
+
+ /// \internal_
+ template<class T>
+ void set_arg(size_t index, const svm_ptr<T> ptr)
+ {
+ #ifdef CL_VERSION_2_0
+ cl_int ret = clSetKernelArgSVMPointer(m_kernel, index, ptr.get());
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+ #else
+ BOOST_THROW_EXCEPTION(opencl_error(CL_INVALID_ARG_VALUE));
+ #endif
+ }
+
+ #ifndef BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
+ /// Sets the arguments for the kernel to \p args.
+ template<class... T>
+ void set_args(T&&... args)
+ {
+ BOOST_ASSERT(sizeof...(T) <= arity());
+
+ _set_args<0>(args...);
+ }
+ #endif // BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
+
+ #if defined(CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ /// Sets additional execution information for the kernel.
+ ///
+ /// \opencl_version_warning{2,0}
+ ///
+ /// \see_opencl2_ref{clSetKernelExecInfo}
+ void set_exec_info(cl_kernel_exec_info info, size_t size, const void *value)
+ {
+ cl_int ret = clSetKernelExecInfo(m_kernel, info, size, value);
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+ }
+ #endif // CL_VERSION_2_0
+
+ /// Returns \c true if the kernel is the same at \p other.
+ bool operator==(const kernel &other) const
+ {
+ return m_kernel == other.m_kernel;
+ }
+
+ /// Returns \c true if the kernel is different from \p other.
+ bool operator!=(const kernel &other) const
+ {
+ return m_kernel != other.m_kernel;
+ }
+
+ /// \internal_
+ operator cl_kernel() const
+ {
+ return m_kernel;
+ }
+
+ /// \internal_
+ static kernel create_with_source(const std::string &source,
+ const std::string &name,
+ const context &context)
+ {
+ return program::build_with_source(source, context).create_kernel(name);
+ }
+
+private:
+ #ifndef BOOST_NO_VARIADIC_TEMPLATES
+ /// \internal_
+ template<size_t N>
+ void _set_args()
+ {
+ }
+
+ /// \internal_
+ template<size_t N, class T, class... Args>
+ void _set_args(T&& arg, Args&&... rest)
+ {
+ set_arg(N, arg);
+ _set_args<N+1>(rest...);
+ }
+ #endif // BOOST_NO_VARIADIC_TEMPLATES
+
+private:
+ cl_kernel m_kernel;
+};
+
+inline kernel program::create_kernel(const std::string &name) const
+{
+ return kernel(*this, name);
+}
+
+/// \internal_ define get_info() specializations for kernel
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(kernel,
+ ((std::string, CL_KERNEL_FUNCTION_NAME))
+ ((cl_uint, CL_KERNEL_NUM_ARGS))
+ ((cl_uint, CL_KERNEL_REFERENCE_COUNT))
+ ((cl_context, CL_KERNEL_CONTEXT))
+ ((cl_program, CL_KERNEL_PROGRAM))
+)
+
+#ifdef CL_VERSION_1_2
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(kernel,
+ ((std::string, CL_KERNEL_ATTRIBUTES))
+)
+#endif // CL_VERSION_1_2
+
+namespace detail {
+
+// set_kernel_arg implementation for built-in types
+template<class T>
+struct set_kernel_arg
+{
+ typename boost::enable_if<is_fundamental<T> >::type
+ operator()(kernel &kernel_, size_t index, const T &value)
+ {
+ kernel_.set_arg(index, sizeof(T), &value);
+ }
+};
+
+// set_kernel_arg specialization for char (different from built-in cl_char)
+template<>
+struct set_kernel_arg<char>
+{
+ void operator()(kernel &kernel_, size_t index, const char c)
+ {
+ kernel_.set_arg(index, sizeof(char), &c);
+ }
+};
+
+} // end detail namespace
+} // end namespace compute
+} // end namespace boost
+
+#endif // BOOST_COMPUTE_KERNEL_HPP
diff --git a/boost/compute/lambda.hpp b/boost/compute/lambda.hpp
new file mode 100644
index 0000000000..24bedfd721
--- /dev/null
+++ b/boost/compute/lambda.hpp
@@ -0,0 +1,22 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_LAMBDA_HPP
+#define BOOST_COMPUTE_LAMBDA_HPP
+
+#include <boost/compute/lambda/context.hpp>
+#include <boost/compute/lambda/functional.hpp>
+#include <boost/compute/lambda/get.hpp>
+#include <boost/compute/lambda/make_pair.hpp>
+#include <boost/compute/lambda/make_tuple.hpp>
+#include <boost/compute/lambda/placeholders.hpp>
+#include <boost/compute/lambda/result_of.hpp>
+
+#endif // BOOST_COMPUTE_LAMBDA_HPP
diff --git a/boost/compute/lambda/context.hpp b/boost/compute/lambda/context.hpp
new file mode 100644
index 0000000000..ed25b79475
--- /dev/null
+++ b/boost/compute/lambda/context.hpp
@@ -0,0 +1,329 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_LAMBDA_CONTEXT_HPP
+#define BOOST_COMPUTE_LAMBDA_CONTEXT_HPP
+
+#include <boost/proto/core.hpp>
+#include <boost/proto/context.hpp>
+#include <boost/type_traits.hpp>
+#include <boost/preprocessor/repetition.hpp>
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/function.hpp>
+#include <boost/compute/lambda/result_of.hpp>
+#include <boost/compute/lambda/functional.hpp>
+#include <boost/compute/type_traits/result_of.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+
+namespace boost {
+namespace compute {
+namespace lambda {
+
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+
+#define BOOST_COMPUTE_LAMBDA_CONTEXT_DEFINE_BINARY_OPERATOR(tag, op) \
+ template<class LHS, class RHS> \
+ void operator()(tag, const LHS &lhs, const RHS &rhs) \
+ { \
+ if(proto::arity_of<LHS>::value > 0){ \
+ stream << '('; \
+ proto::eval(lhs, *this); \
+ stream << ')'; \
+ } \
+ else { \
+ proto::eval(lhs, *this); \
+ } \
+ \
+ stream << op; \
+ \
+ if(proto::arity_of<RHS>::value > 0){ \
+ stream << '('; \
+ proto::eval(rhs, *this); \
+ stream << ')'; \
+ } \
+ else { \
+ proto::eval(rhs, *this); \
+ } \
+ }
+
+// lambda expression context
+template<class Args>
+struct context : proto::callable_context<context<Args> >
+{
+ typedef void result_type;
+ typedef Args args_tuple;
+
+ // create a lambda context for kernel with args
+ context(boost::compute::detail::meta_kernel &kernel, const Args &args_)
+ : stream(kernel),
+ args(args_)
+ {
+ }
+
+ // handle terminals
+ template<class T>
+ void operator()(proto::tag::terminal, const T &x)
+ {
+ // terminal values in lambda expressions are always literals
+ stream << stream.lit(x);
+ }
+
+ // handle placeholders
+ template<int I>
+ void operator()(proto::tag::terminal, placeholder<I>)
+ {
+ stream << boost::get<I>(args);
+ }
+
+ // handle functions
+ #define BOOST_COMPUTE_LAMBDA_CONTEXT_FUNCTION_ARG(z, n, unused) \
+ BOOST_PP_COMMA_IF(n) BOOST_PP_CAT(const Arg, n) BOOST_PP_CAT(&arg, n)
+
+ #define BOOST_COMPUTE_LAMBDA_CONTEXT_FUNCTION(z, n, unused) \
+ template<class F, BOOST_PP_ENUM_PARAMS(n, class Arg)> \
+ void operator()( \
+ proto::tag::function, \
+ const F &function, \
+ BOOST_PP_REPEAT(n, BOOST_COMPUTE_LAMBDA_CONTEXT_FUNCTION_ARG, ~) \
+ ) \
+ { \
+ proto::value(function).apply(*this, BOOST_PP_ENUM_PARAMS(n, arg)); \
+ }
+
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_LAMBDA_CONTEXT_FUNCTION, ~)
+
+ #undef BOOST_COMPUTE_LAMBDA_CONTEXT_FUNCTION
+
+ // operators
+ BOOST_COMPUTE_LAMBDA_CONTEXT_DEFINE_BINARY_OPERATOR(proto::tag::plus, '+')
+ BOOST_COMPUTE_LAMBDA_CONTEXT_DEFINE_BINARY_OPERATOR(proto::tag::minus, '-')
+ BOOST_COMPUTE_LAMBDA_CONTEXT_DEFINE_BINARY_OPERATOR(proto::tag::multiplies, '*')
+ BOOST_COMPUTE_LAMBDA_CONTEXT_DEFINE_BINARY_OPERATOR(proto::tag::divides, '/')
+ BOOST_COMPUTE_LAMBDA_CONTEXT_DEFINE_BINARY_OPERATOR(proto::tag::modulus, '%')
+ BOOST_COMPUTE_LAMBDA_CONTEXT_DEFINE_BINARY_OPERATOR(proto::tag::less, '<')
+ BOOST_COMPUTE_LAMBDA_CONTEXT_DEFINE_BINARY_OPERATOR(proto::tag::greater, '>')
+ BOOST_COMPUTE_LAMBDA_CONTEXT_DEFINE_BINARY_OPERATOR(proto::tag::less_equal, "<=")
+ BOOST_COMPUTE_LAMBDA_CONTEXT_DEFINE_BINARY_OPERATOR(proto::tag::greater_equal, ">=")
+ BOOST_COMPUTE_LAMBDA_CONTEXT_DEFINE_BINARY_OPERATOR(proto::tag::equal_to, "==")
+ BOOST_COMPUTE_LAMBDA_CONTEXT_DEFINE_BINARY_OPERATOR(proto::tag::not_equal_to, "!=")
+ BOOST_COMPUTE_LAMBDA_CONTEXT_DEFINE_BINARY_OPERATOR(proto::tag::logical_and, "&&")
+ BOOST_COMPUTE_LAMBDA_CONTEXT_DEFINE_BINARY_OPERATOR(proto::tag::logical_or, "||")
+ BOOST_COMPUTE_LAMBDA_CONTEXT_DEFINE_BINARY_OPERATOR(proto::tag::bitwise_and, '&')
+ BOOST_COMPUTE_LAMBDA_CONTEXT_DEFINE_BINARY_OPERATOR(proto::tag::bitwise_or, '|')
+ BOOST_COMPUTE_LAMBDA_CONTEXT_DEFINE_BINARY_OPERATOR(proto::tag::bitwise_xor, '^')
+ BOOST_COMPUTE_LAMBDA_CONTEXT_DEFINE_BINARY_OPERATOR(proto::tag::assign, '=')
+
+ // subscript operator
+ template<class LHS, class RHS>
+ void operator()(proto::tag::subscript, const LHS &lhs, const RHS &rhs)
+ {
+ proto::eval(lhs, *this);
+ stream << '[';
+ proto::eval(rhs, *this);
+ stream << ']';
+ }
+
+ // ternary conditional operator
+ template<class Pred, class Arg1, class Arg2>
+ void operator()(proto::tag::if_else_, const Pred &p, const Arg1 &x, const Arg2 &y)
+ {
+ proto::eval(p, *this);
+ stream << '?';
+ proto::eval(x, *this);
+ stream << ':';
+ proto::eval(y, *this);
+ }
+
+ boost::compute::detail::meta_kernel &stream;
+ Args args;
+};
+
+namespace detail {
+
+template<class Expr, class Arg>
+struct invoked_unary_expression
+{
+ typedef typename ::boost::compute::result_of<Expr(Arg)>::type result_type;
+
+ invoked_unary_expression(const Expr &expr, const Arg &arg)
+ : m_expr(expr),
+ m_arg(arg)
+ {
+ }
+
+ Expr m_expr;
+ Arg m_arg;
+};
+
+template<class Expr, class Arg>
+boost::compute::detail::meta_kernel&
+operator<<(boost::compute::detail::meta_kernel &kernel,
+ const invoked_unary_expression<Expr, Arg> &expr)
+{
+ context<boost::tuple<Arg> > ctx(kernel, boost::make_tuple(expr.m_arg));
+ proto::eval(expr.m_expr, ctx);
+
+ return kernel;
+}
+
+template<class Expr, class Arg1, class Arg2>
+struct invoked_binary_expression
+{
+ typedef typename ::boost::compute::result_of<Expr(Arg1, Arg2)>::type result_type;
+
+ invoked_binary_expression(const Expr &expr,
+ const Arg1 &arg1,
+ const Arg2 &arg2)
+ : m_expr(expr),
+ m_arg1(arg1),
+ m_arg2(arg2)
+ {
+ }
+
+ Expr m_expr;
+ Arg1 m_arg1;
+ Arg2 m_arg2;
+};
+
+template<class Expr, class Arg1, class Arg2>
+boost::compute::detail::meta_kernel&
+operator<<(boost::compute::detail::meta_kernel &kernel,
+ const invoked_binary_expression<Expr, Arg1, Arg2> &expr)
+{
+ context<boost::tuple<Arg1, Arg2> > ctx(
+ kernel,
+ boost::make_tuple(expr.m_arg1, expr.m_arg2)
+ );
+ proto::eval(expr.m_expr, ctx);
+
+ return kernel;
+}
+
+} // end detail namespace
+
+// forward declare domain
+struct domain;
+
+// lambda expression wrapper
+template<class Expr>
+struct expression : proto::extends<Expr, expression<Expr>, domain>
+{
+ typedef proto::extends<Expr, expression<Expr>, domain> base_type;
+
+ BOOST_PROTO_EXTENDS_USING_ASSIGN(expression)
+
+ expression(const Expr &expr = Expr())
+ : base_type(expr)
+ {
+ }
+
+ // result_of protocol
+ template<class Signature>
+ struct result
+ {
+ };
+
+ template<class This>
+ struct result<This()>
+ {
+ typedef
+ typename ::boost::compute::lambda::result_of<Expr>::type type;
+ };
+
+ template<class This, class Arg>
+ struct result<This(Arg)>
+ {
+ typedef
+ typename ::boost::compute::lambda::result_of<
+ Expr,
+ typename boost::tuple<Arg>
+ >::type type;
+ };
+
+ template<class This, class Arg1, class Arg2>
+ struct result<This(Arg1, Arg2)>
+ {
+ typedef typename
+ ::boost::compute::lambda::result_of<
+ Expr,
+ typename boost::tuple<Arg1, Arg2>
+ >::type type;
+ };
+
+ template<class Arg>
+ detail::invoked_unary_expression<expression<Expr>, Arg>
+ operator()(const Arg &x) const
+ {
+ return detail::invoked_unary_expression<expression<Expr>, Arg>(*this, x);
+ }
+
+ template<class Arg1, class Arg2>
+ detail::invoked_binary_expression<expression<Expr>, Arg1, Arg2>
+ operator()(const Arg1 &x, const Arg2 &y) const
+ {
+ return detail::invoked_binary_expression<
+ expression<Expr>,
+ Arg1,
+ Arg2
+ >(*this, x, y);
+ }
+
+ // function<> conversion operator
+ template<class R, class A1>
+ operator function<R(A1)>() const
+ {
+ using ::boost::compute::detail::meta_kernel;
+
+ std::stringstream source;
+
+ ::boost::compute::detail::meta_kernel_variable<A1> arg1("x");
+
+ source << "inline " << type_name<R>() << " lambda"
+ << ::boost::compute::detail::generate_argument_list<R(A1)>('x')
+ << "{\n"
+ << " return " << meta_kernel::expr_to_string((*this)(arg1)) << ";\n"
+ << "}\n";
+
+ return make_function_from_source<R(A1)>("lambda", source.str());
+ }
+
+ template<class R, class A1, class A2>
+ operator function<R(A1, A2)>() const
+ {
+ using ::boost::compute::detail::meta_kernel;
+
+ std::stringstream source;
+
+ ::boost::compute::detail::meta_kernel_variable<A1> arg1("x");
+ ::boost::compute::detail::meta_kernel_variable<A1> arg2("y");
+
+ source << "inline " << type_name<R>() << " lambda"
+ << ::boost::compute::detail::generate_argument_list<R(A1, A2)>('x')
+ << "{\n"
+ << " return " << meta_kernel::expr_to_string((*this)(arg1, arg2)) << ";\n"
+ << "}\n";
+
+ return make_function_from_source<R(A1, A2)>("lambda", source.str());
+ }
+};
+
+// lambda expression domain
+struct domain : proto::domain<proto::generator<expression> >
+{
+};
+
+} // end lambda namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_LAMBDA_CONTEXT_HPP
diff --git a/boost/compute/lambda/functional.hpp b/boost/compute/lambda/functional.hpp
new file mode 100644
index 0000000000..dd7190e4d9
--- /dev/null
+++ b/boost/compute/lambda/functional.hpp
@@ -0,0 +1,242 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_LAMBDA_FUNCTIONAL_HPP
+#define BOOST_COMPUTE_LAMBDA_FUNCTIONAL_HPP
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include <boost/proto/core.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/stringize.hpp>
+
+#include <boost/compute/functional/get.hpp>
+#include <boost/compute/lambda/result_of.hpp>
+#include <boost/compute/lambda/placeholder.hpp>
+
+namespace boost {
+namespace compute {
+namespace lambda {
+
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+
+// wraps a unary boolean function
+#define BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(name) \
+ namespace detail { \
+ struct BOOST_PP_CAT(name, _func) \
+ { \
+ template<class Expr, class Args> \
+ struct lambda_result \
+ { \
+ typedef int type; \
+ }; \
+ \
+ template<class Context, class Arg> \
+ static void apply(Context &ctx, const Arg &arg) \
+ { \
+ ctx.stream << #name << "("; \
+ proto::eval(arg, ctx); \
+ ctx.stream << ")"; \
+ } \
+ }; \
+ } \
+ template<class Arg> \
+ inline typename proto::result_of::make_expr< \
+ proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg& \
+ >::type const \
+ name(const Arg &arg) \
+ { \
+ return proto::make_expr<proto::tag::function>( \
+ BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg) \
+ ); \
+ }
+
+// wraps a unary function who's return type is the same as the argument type
+#define BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(name) \
+ namespace detail { \
+ struct BOOST_PP_CAT(name, _func) \
+ { \
+ template<class Expr, class Args> \
+ struct lambda_result \
+ { \
+ typedef typename proto::result_of::child_c<Expr, 1>::type Arg1; \
+ typedef typename ::boost::compute::lambda::result_of<Arg1, Args>::type type; \
+ }; \
+ \
+ template<class Context, class Arg> \
+ static void apply(Context &ctx, const Arg &arg) \
+ { \
+ ctx.stream << #name << "("; \
+ proto::eval(arg, ctx); \
+ ctx.stream << ")"; \
+ } \
+ }; \
+ } \
+ template<class Arg> \
+ inline typename proto::result_of::make_expr< \
+ proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg& \
+ >::type const \
+ name(const Arg &arg) \
+ { \
+ return proto::make_expr<proto::tag::function>( \
+ BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg) \
+ ); \
+ }
+
+// wraps a binary function
+#define BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(name) \
+ namespace detail { \
+ struct BOOST_PP_CAT(name, _func) \
+ { \
+ template<class Expr, class Args> \
+ struct lambda_result \
+ { \
+ typedef typename proto::result_of::child_c<Expr, 1>::type Arg1; \
+ typedef typename ::boost::compute::lambda::result_of<Arg1, Args>::type type; \
+ }; \
+ \
+ template<class Context, class Arg1, class Arg2> \
+ static void apply(Context &ctx, const Arg1 &arg1, const Arg2 &arg2) \
+ { \
+ ctx.stream << #name << "("; \
+ proto::eval(arg1, ctx); \
+ ctx.stream << ", "; \
+ proto::eval(arg2, ctx); \
+ ctx.stream << ")"; \
+ } \
+ }; \
+ } \
+ template<class Arg1, class Arg2> \
+ inline typename proto::result_of::make_expr< \
+ proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg1&, const Arg2& \
+ >::type const \
+ name(const Arg1 &arg1, const Arg2 &arg2) \
+ { \
+ return proto::make_expr<proto::tag::function>( \
+ BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg1), ::boost::ref(arg2) \
+ ); \
+ }
+
+// wraps a binary function who's result type is the scalar type of the first argument
+#define BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_ST(name) \
+ namespace detail { \
+ struct BOOST_PP_CAT(name, _func) \
+ { \
+ template<class Expr, class Args> \
+ struct lambda_result \
+ { \
+ typedef typename proto::result_of::child_c<Expr, 1>::type Arg1; \
+ typedef typename ::boost::compute::lambda::result_of<Arg1, Args>::type result_type; \
+ typedef typename ::boost::compute::scalar_type<result_type>::type type; \
+ }; \
+ \
+ template<class Context, class Arg1, class Arg2> \
+ static void apply(Context &ctx, const Arg1 &arg1, const Arg2 &arg2) \
+ { \
+ ctx.stream << #name << "("; \
+ proto::eval(arg1, ctx); \
+ ctx.stream << ", "; \
+ proto::eval(arg2, ctx); \
+ ctx.stream << ")"; \
+ } \
+ }; \
+ } \
+ template<class Arg1, class Arg2> \
+ inline typename proto::result_of::make_expr< \
+ proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg1&, const Arg2& \
+ >::type const \
+ name(const Arg1 &arg1, const Arg2 &arg2) \
+ { \
+ return proto::make_expr<proto::tag::function>( \
+ BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg1), ::boost::ref(arg2) \
+ ); \
+ }
+
+// wraps a ternary function
+#define BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(name) \
+ namespace detail { \
+ struct BOOST_PP_CAT(name, _func) \
+ { \
+ template<class Expr, class Args> \
+ struct lambda_result \
+ { \
+ typedef typename proto::result_of::child_c<Expr, 1>::type Arg1; \
+ typedef typename ::boost::compute::lambda::result_of<Arg1, Args>::type type; \
+ }; \
+ \
+ template<class Context, class Arg1, class Arg2, class Arg3> \
+ static void apply(Context &ctx, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) \
+ { \
+ ctx.stream << #name << "("; \
+ proto::eval(arg1, ctx); \
+ ctx.stream << ", "; \
+ proto::eval(arg2, ctx); \
+ ctx.stream << ", "; \
+ proto::eval(arg3, ctx); \
+ ctx.stream << ")"; \
+ } \
+ }; \
+ } \
+ template<class Arg1, class Arg2, class Arg3> \
+ inline typename proto::result_of::make_expr< \
+ proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg1&, const Arg2&, const Arg3& \
+ >::type const \
+ name(const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) \
+ { \
+ return proto::make_expr<proto::tag::function>( \
+ BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg1), ::boost::ref(arg2), ::boost::ref(arg3) \
+ ); \
+ }
+
+
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(all)
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(any)
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(isinf)
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(isnan)
+BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(isfinite)
+
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(abs)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(cos)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(acos)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(sin)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(asin)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(tan)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(atan)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(sqrt)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(rsqrt)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(exp)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(exp2)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(exp10)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(log)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(log2)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(log10)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(round)
+BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(length)
+
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(cross)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(pow)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(pown)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(powr)
+
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_ST(dot)
+BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_ST(distance)
+
+BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(clamp)
+BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(fma)
+BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(mad)
+BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(smoothstep)
+
+} // end lambda namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_LAMBDA_FUNCTIONAL_HPP
diff --git a/boost/compute/lambda/get.hpp b/boost/compute/lambda/get.hpp
new file mode 100644
index 0000000000..547c208e95
--- /dev/null
+++ b/boost/compute/lambda/get.hpp
@@ -0,0 +1,148 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_LAMBDA_GET_HPP
+#define BOOST_COMPUTE_LAMBDA_GET_HPP
+
+#include <boost/preprocessor/repetition.hpp>
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/functional/get.hpp>
+#include <boost/compute/lambda/placeholder.hpp>
+
+namespace boost {
+namespace compute {
+namespace lambda {
+namespace detail {
+
+// function wrapper for get<N>() in lambda expressions
+template<size_t N>
+struct get_func
+{
+ template<class Expr, class Args>
+ struct lambda_result
+ {
+ typedef typename proto::result_of::child_c<Expr, 1>::type Arg;
+ typedef typename ::boost::compute::lambda::result_of<Arg, Args>::type T;
+ typedef typename ::boost::compute::detail::get_result_type<N, T>::type type;
+ };
+
+ template<class Context, class Arg>
+ struct make_get_result_type
+ {
+ typedef typename boost::remove_cv<
+ typename boost::compute::lambda::result_of<
+ Arg, typename Context::args_tuple
+ >::type
+ >::type type;
+ };
+
+ // returns the suffix string for get<N>() in lambda expressions
+ // (e.g. ".x" for get<0>() with float4)
+ template<class T>
+ struct make_get_suffix
+ {
+ static std::string value()
+ {
+ BOOST_STATIC_ASSERT(N < 16);
+
+ std::stringstream stream;
+
+ if(N < 10){
+ stream << ".s" << uint_(N);
+ }
+ else if(N < 16){
+ stream << ".s" << char('a' + (N - 10));
+ }
+
+ return stream.str();
+ }
+ };
+
+ // get<N>() specialization for std::pair<T1, T2>
+ template<class T1, class T2>
+ struct make_get_suffix<std::pair<T1, T2> >
+ {
+ static std::string value()
+ {
+ BOOST_STATIC_ASSERT(N < 2);
+
+ if(N == 0){
+ return ".first";
+ }
+ else {
+ return ".second";
+ }
+ };
+ };
+
+ // get<N>() specialization for boost::tuple<T...>
+ #define BOOST_COMPUTE_LAMBDA_GET_MAKE_TUPLE_SUFFIX(z, n, unused) \
+ template<BOOST_PP_ENUM_PARAMS(n, class T)> \
+ struct make_get_suffix<boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> > \
+ { \
+ static std::string value() \
+ { \
+ BOOST_STATIC_ASSERT(N < n); \
+ return ".v" + boost::lexical_cast<std::string>(N); \
+ } \
+ };
+
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_LAMBDA_GET_MAKE_TUPLE_SUFFIX, ~)
+
+ #undef BOOST_COMPUTE_LAMBDA_GET_MAKE_TUPLE_SUFFIX
+
+ template<class Context, class Arg>
+ static void dispatch_apply_terminal(Context &ctx, const Arg &arg)
+ {
+ typedef typename make_get_result_type<Context, Arg>::type T;
+
+ proto::eval(arg, ctx);
+ ctx.stream << make_get_suffix<T>::value();
+ }
+
+ template<class Context, int I>
+ static void dispatch_apply_terminal(Context &ctx, placeholder<I>)
+ {
+ ctx.stream << ::boost::compute::get<N>()(::boost::get<I>(ctx.args));
+ }
+
+ template<class Context, class Arg>
+ static void dispatch_apply(Context &ctx, const Arg &arg, proto::tag::terminal)
+ {
+ dispatch_apply_terminal(ctx, proto::value(arg));
+ }
+
+ template<class Context, class Arg>
+ static void apply(Context &ctx, const Arg &arg)
+ {
+ dispatch_apply(ctx, arg, typename proto::tag_of<Arg>::type());
+ }
+};
+
+} // end detail namespace
+
+// get<N>()
+template<size_t N, class Arg>
+inline typename proto::result_of::make_expr<
+ proto::tag::function, detail::get_func<N>, const Arg&
+>::type const
+get(const Arg &arg)
+{
+ return proto::make_expr<proto::tag::function>(
+ detail::get_func<N>(), ::boost::ref(arg)
+ );
+}
+
+} // end lambda namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_LAMBDA_GET_HPP
diff --git a/boost/compute/lambda/make_pair.hpp b/boost/compute/lambda/make_pair.hpp
new file mode 100644
index 0000000000..3adca97c71
--- /dev/null
+++ b/boost/compute/lambda/make_pair.hpp
@@ -0,0 +1,70 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_LAMBDA_MAKE_PAIR_HPP
+#define BOOST_COMPUTE_LAMBDA_MAKE_PAIR_HPP
+
+#include <boost/compute/types/pair.hpp>
+
+namespace boost {
+namespace compute {
+namespace lambda {
+namespace detail {
+
+// function wrapper for make_pair() in lambda expressions
+struct make_pair_func
+{
+ template<class Expr, class Args>
+ struct lambda_result
+ {
+ typedef typename proto::result_of::child_c<Expr, 1>::type Arg1;
+ typedef typename proto::result_of::child_c<Expr, 2>::type Arg2;
+
+ typedef typename lambda::result_of<Arg1, Args>::type T1;
+ typedef typename lambda::result_of<Arg2, Args>::type T2;
+
+ typedef std::pair<T1, T2> type;
+ };
+
+ template<class Context, class Arg1, class Arg2>
+ static void apply(Context &ctx, const Arg1 &arg1, const Arg2 &arg2)
+ {
+ typedef typename lambda::result_of<Arg1, typename Context::args_tuple>::type T1;
+ typedef typename lambda::result_of<Arg2, typename Context::args_tuple>::type T2;
+
+ ctx.stream << "boost_make_pair(";
+ ctx.stream << type_name<T1>() << ", ";
+ proto::eval(arg1, ctx);
+ ctx.stream << ", ";
+ ctx.stream << type_name<T2>() << ", ";
+ proto::eval(arg2, ctx);
+ ctx.stream << ")";
+ }
+};
+
+} // end detail namespace
+
+// make_pair(first, second)
+template<class Arg1, class Arg2>
+inline typename proto::result_of::make_expr<
+ proto::tag::function, detail::make_pair_func, const Arg1&, const Arg2&
+>::type const
+make_pair(const Arg1 &first, const Arg2 &second)
+{
+ return proto::make_expr<proto::tag::function>(
+ detail::make_pair_func(), ::boost::ref(first), ::boost::ref(second)
+ );
+}
+
+} // end lambda namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_LAMBDA_MAKE_PAIR_HPP
diff --git a/boost/compute/lambda/make_tuple.hpp b/boost/compute/lambda/make_tuple.hpp
new file mode 100644
index 0000000000..2d065a999a
--- /dev/null
+++ b/boost/compute/lambda/make_tuple.hpp
@@ -0,0 +1,127 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_LAMBDA_MAKE_TUPLE_HPP
+#define BOOST_COMPUTE_LAMBDA_MAKE_TUPLE_HPP
+
+#include <boost/preprocessor/repetition.hpp>
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/types/tuple.hpp>
+
+namespace boost {
+namespace compute {
+namespace lambda {
+namespace detail {
+
+// function wrapper for make_tuple() in lambda expressions
+struct make_tuple_func
+{
+ template<class Expr, class Args, int N>
+ struct make_tuple_result_type;
+
+ #define BOOST_COMPUTE_MAKE_TUPLE_RESULT_GET_ARG(z, n, unused) \
+ typedef typename proto::result_of::child_c<Expr, BOOST_PP_INC(n)>::type BOOST_PP_CAT(Arg, n);
+
+ #define BOOST_COMPUTE_MAKE_TUPLE_RESULT_GET_ARG_TYPE(z, n, unused) \
+ typedef typename lambda::result_of<BOOST_PP_CAT(Arg, n), Args>::type BOOST_PP_CAT(T, n);
+
+ #define BOOST_COMPUTE_MAKE_TUPLE_RESULT_TYPE(z, n, unused) \
+ template<class Expr, class Args> \
+ struct make_tuple_result_type<Expr, Args, n> \
+ { \
+ BOOST_PP_REPEAT(n, BOOST_COMPUTE_MAKE_TUPLE_RESULT_GET_ARG, ~) \
+ BOOST_PP_REPEAT(n, BOOST_COMPUTE_MAKE_TUPLE_RESULT_GET_ARG_TYPE, ~) \
+ typedef boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> type; \
+ };
+
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_MAKE_TUPLE_RESULT_TYPE, ~)
+
+ #undef BOOST_COMPUTE_MAKE_TUPLE_RESULT_GET_ARG
+ #undef BOOST_COMPUTE_MAKE_TUPLE_RESULT_GET_ARG_TYPE
+ #undef BOOST_COMPUTE_MAKE_TUPLE_RESULT_TYPE
+
+ template<class Expr, class Args>
+ struct lambda_result
+ {
+ typedef typename make_tuple_result_type<
+ Expr, Args, proto::arity_of<Expr>::value - 1
+ >::type type;
+ };
+
+ #define BOOST_COMPUTE_MAKE_TUPLE_GET_ARG_TYPE(z, n, unused) \
+ typedef typename lambda::result_of< \
+ BOOST_PP_CAT(Arg, n), typename Context::args_tuple \
+ >::type BOOST_PP_CAT(T, n);
+
+ #define BOOST_COMPUTE_LAMBDA_MAKE_TUPLE_APPLY_ARG(z, n, unused) \
+ BOOST_PP_COMMA_IF(n) BOOST_PP_CAT(const Arg, n) BOOST_PP_CAT(&arg, n)
+
+ #define BOOST_COMPUTE_LAMBDA_MAKE_TUPLE_APPLY_EVAL_ARG(z, n, unused) \
+ BOOST_PP_EXPR_IF(n, ctx.stream << ", ";) proto::eval(BOOST_PP_CAT(arg, n), ctx);
+
+ #define BOOST_COMPUTE_MAKE_TUPLE_APPLY(z, n, unused) \
+ template<class Context, BOOST_PP_ENUM_PARAMS(n, class Arg)> \
+ static void apply(Context &ctx, BOOST_PP_REPEAT(n, BOOST_COMPUTE_LAMBDA_MAKE_TUPLE_APPLY_ARG, ~)) \
+ { \
+ BOOST_PP_REPEAT(n, BOOST_COMPUTE_MAKE_TUPLE_GET_ARG_TYPE, ~) \
+ typedef typename boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> tuple_type; \
+ ctx.stream.template inject_type<tuple_type>(); \
+ ctx.stream << "((" << type_name<tuple_type>() << "){"; \
+ BOOST_PP_REPEAT(n, BOOST_COMPUTE_LAMBDA_MAKE_TUPLE_APPLY_EVAL_ARG, ~) \
+ ctx.stream << "})"; \
+ }
+
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_MAKE_TUPLE_APPLY, ~)
+
+ #undef BOOST_COMPUTE_MAKE_TUPLE_GET_ARG_TYPE
+ #undef BOOST_COMPUTE_LAMBDA_MAKE_TUPLE_APPLY_ARG
+ #undef BOOST_COMPUTE_LAMBDA_MAKE_TUPLE_APPLY_EVAL_ARG
+ #undef BOOST_COMPUTE_LAMBDA_MAKE_TUPLE_APPLY
+};
+
+} // end detail namespace
+
+#define BOOST_COMPUTE_LAMBDA_MAKE_TUPLE_ARG(z, n, unused) \
+ BOOST_PP_COMMA_IF(n) BOOST_PP_CAT(const Arg, n) BOOST_PP_CAT(&arg, n)
+
+#define BOOST_COMPUTE_LAMBDA_MAKE_TUPLE_ARG_TYPE(z, n, unused) \
+ BOOST_PP_COMMA_IF(n) BOOST_PP_CAT(const Arg, n) &
+
+#define BOOST_COMPUTE_LAMBDA_MAKE_TUPLE_REF_ARG(z, n, unused) \
+ BOOST_PP_COMMA_IF(n) ::boost::ref(BOOST_PP_CAT(arg, n))
+
+#define BOOST_COMPUTE_LAMBDA_MAKE_TUPLE(z, n, unused) \
+template<BOOST_PP_ENUM_PARAMS(n, class Arg)> \
+inline typename proto::result_of::make_expr< \
+ proto::tag::function, \
+ detail::make_tuple_func, \
+ BOOST_PP_REPEAT(n, BOOST_COMPUTE_LAMBDA_MAKE_TUPLE_ARG_TYPE, ~) \
+>::type \
+make_tuple(BOOST_PP_REPEAT(n, BOOST_COMPUTE_LAMBDA_MAKE_TUPLE_ARG, ~)) \
+{ \
+ return proto::make_expr<proto::tag::function>( \
+ detail::make_tuple_func(), \
+ BOOST_PP_REPEAT(n, BOOST_COMPUTE_LAMBDA_MAKE_TUPLE_REF_ARG, ~) \
+ ); \
+}
+
+BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_LAMBDA_MAKE_TUPLE, ~)
+
+#undef BOOST_COMPUTE_LAMBDA_MAKE_TUPLE_ARG
+#undef BOOST_COMPUTE_LAMBDA_MAKE_TUPLE_ARG_TYPE
+#undef BOOST_COMPUTE_LAMBDA_MAKE_TUPLE_REF_ARG
+#undef BOOST_COMPUTE_LAMBDA_MAKE_TUPLE
+
+} // end lambda namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_LAMBDA_MAKE_TUPLE_HPP
diff --git a/boost/compute/lambda/placeholder.hpp b/boost/compute/lambda/placeholder.hpp
new file mode 100644
index 0000000000..4774b1b4f3
--- /dev/null
+++ b/boost/compute/lambda/placeholder.hpp
@@ -0,0 +1,28 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_LAMBDA_PLACEHOLDER_HPP
+#define BOOST_COMPUTE_LAMBDA_PLACEHOLDER_HPP
+
+namespace boost {
+namespace compute {
+namespace lambda {
+
+// lambda placeholder type
+template<int I>
+struct placeholder
+{
+};
+
+} // end lambda namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_LAMBDA_PLACEHOLDER_HPP
diff --git a/boost/compute/lambda/placeholders.hpp b/boost/compute/lambda/placeholders.hpp
new file mode 100644
index 0000000000..5c3fe531d1
--- /dev/null
+++ b/boost/compute/lambda/placeholders.hpp
@@ -0,0 +1,93 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_LAMBDA_PLACEHOLDERS_HPP
+#define BOOST_COMPUTE_LAMBDA_PLACEHOLDERS_HPP
+
+#include <boost/mpl/has_xxx.hpp>
+
+#include <boost/compute/lambda/context.hpp>
+#include <boost/compute/lambda/result_of.hpp>
+
+namespace boost {
+namespace compute {
+namespace lambda {
+
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+
+// lambda placeholders
+expression<proto::terminal<placeholder<0> >::type> const _1;
+expression<proto::terminal<placeholder<1> >::type> const _2;
+expression<proto::terminal<placeholder<2> >::type> const _3;
+
+namespace detail {
+
+BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
+
+template<class T, bool HasResultType>
+struct terminal_type_impl;
+
+template<class T>
+struct terminal_type_impl<T, true>
+{
+ typedef typename T::result_type type;
+};
+
+template<class T>
+struct terminal_type_impl<T, false>
+{
+ typedef T type;
+};
+
+template<class T>
+struct terminal_type
+{
+ typedef typename terminal_type_impl<T, has_result_type<T>::value>::type type;
+};
+
+} // end detail namespace
+
+// result_of placeholders
+template<class Args>
+struct result_of<expression<proto::terminal<placeholder<0> >::type>, Args, proto::tag::terminal>
+{
+ typedef typename boost::tuples::element<0, Args>::type arg_type;
+
+ typedef typename detail::terminal_type<arg_type>::type type;
+};
+
+template<class Args>
+struct result_of<expression<proto::terminal<placeholder<1> >::type>, Args, proto::tag::terminal>
+{
+ typedef typename boost::tuples::element<1, Args>::type arg_type;
+
+ typedef typename detail::terminal_type<arg_type>::type type;
+};
+
+template<class Args>
+struct result_of<expression<proto::terminal<placeholder<2> >::type>, Args, proto::tag::terminal>
+{
+ typedef typename boost::tuples::element<2, Args>::type arg_type;
+
+ typedef typename detail::terminal_type<arg_type>::type type;
+};
+
+} // end lambda namespace
+
+// lift lambda placeholders up to the boost::compute namespace
+using lambda::_1;
+using lambda::_2;
+using lambda::_3;
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_LAMBDA_PLACEHOLDERS_HPP
diff --git a/boost/compute/lambda/result_of.hpp b/boost/compute/lambda/result_of.hpp
new file mode 100644
index 0000000000..baae87f05c
--- /dev/null
+++ b/boost/compute/lambda/result_of.hpp
@@ -0,0 +1,113 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_LAMBDA_RESULT_OF_HPP
+#define BOOST_COMPUTE_LAMBDA_RESULT_OF_HPP
+
+#include <boost/mpl/vector.hpp>
+#include <boost/proto/proto.hpp>
+
+#include <boost/compute/type_traits/common_type.hpp>
+
+namespace boost {
+namespace compute {
+namespace lambda {
+
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+
+// meta-function returning the result type of a lambda expression
+template<class Expr,
+ class Args = void,
+ class Tags = typename proto::tag_of<Expr>::type>
+struct result_of
+{
+};
+
+// terminals
+template<class Expr, class Args>
+struct result_of<Expr, Args, proto::tag::terminal>
+{
+ typedef typename proto::result_of::value<Expr>::type type;
+};
+
+// binary operators
+#define BOOST_COMPUTE_LAMBDA_RESULT_OF_BINARY_OPERATOR(tag) \
+ template<class Expr, class Args> \
+ struct result_of<Expr, Args, tag> \
+ { \
+ typedef typename proto::result_of::child_c<Expr, 0>::type left; \
+ typedef typename proto::result_of::child_c<Expr, 1>::type right; \
+ \
+ typedef typename boost::common_type< \
+ typename ::boost::compute::lambda::result_of< \
+ left, \
+ Args, \
+ typename proto::tag_of<left>::type>::type, \
+ typename ::boost::compute::lambda::result_of< \
+ right, \
+ Args, \
+ typename proto::tag_of<right>::type>::type \
+ >::type type; \
+ };
+
+BOOST_COMPUTE_LAMBDA_RESULT_OF_BINARY_OPERATOR(proto::tag::plus)
+BOOST_COMPUTE_LAMBDA_RESULT_OF_BINARY_OPERATOR(proto::tag::minus)
+BOOST_COMPUTE_LAMBDA_RESULT_OF_BINARY_OPERATOR(proto::tag::multiplies)
+BOOST_COMPUTE_LAMBDA_RESULT_OF_BINARY_OPERATOR(proto::tag::divides)
+BOOST_COMPUTE_LAMBDA_RESULT_OF_BINARY_OPERATOR(proto::tag::modulus)
+BOOST_COMPUTE_LAMBDA_RESULT_OF_BINARY_OPERATOR(proto::tag::bitwise_and)
+BOOST_COMPUTE_LAMBDA_RESULT_OF_BINARY_OPERATOR(proto::tag::bitwise_or)
+BOOST_COMPUTE_LAMBDA_RESULT_OF_BINARY_OPERATOR(proto::tag::bitwise_xor)
+
+// comparision operators
+#define BOOST_COMPUTE_LAMBDA_RESULT_OF_COMPARISON_OPERATOR(tag) \
+ template<class Expr, class Args> \
+ struct result_of<Expr, Args, tag> \
+ { \
+ typedef bool type; \
+ };
+
+BOOST_COMPUTE_LAMBDA_RESULT_OF_COMPARISON_OPERATOR(proto::tag::less)
+BOOST_COMPUTE_LAMBDA_RESULT_OF_COMPARISON_OPERATOR(proto::tag::greater)
+BOOST_COMPUTE_LAMBDA_RESULT_OF_COMPARISON_OPERATOR(proto::tag::less_equal)
+BOOST_COMPUTE_LAMBDA_RESULT_OF_COMPARISON_OPERATOR(proto::tag::greater_equal)
+BOOST_COMPUTE_LAMBDA_RESULT_OF_COMPARISON_OPERATOR(proto::tag::equal_to)
+BOOST_COMPUTE_LAMBDA_RESULT_OF_COMPARISON_OPERATOR(proto::tag::not_equal_to)
+BOOST_COMPUTE_LAMBDA_RESULT_OF_COMPARISON_OPERATOR(proto::tag::logical_and)
+BOOST_COMPUTE_LAMBDA_RESULT_OF_COMPARISON_OPERATOR(proto::tag::logical_or)
+
+// assignment operator
+template<class Expr, class Args>
+struct result_of<Expr, Args, proto::tag::assign>
+{
+ typedef typename proto::result_of::child_c<Expr, 0>::type left;
+ typedef typename proto::result_of::child_c<Expr, 1>::type right;
+
+ typedef typename ::boost::compute::lambda::result_of<
+ right, Args, typename proto::tag_of<right>::type
+ >::type type;
+};
+
+// functions
+template<class Expr, class Args>
+struct result_of<Expr, Args, proto::tag::function>
+{
+ typedef typename proto::result_of::child_c<Expr, 0>::type func_expr;
+ typedef typename proto::result_of::value<func_expr>::type func;
+
+ typedef typename func::template lambda_result<Expr, Args>::type type;
+};
+
+} // end lambda namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_LAMBDA_RESULT_OF_HPP
diff --git a/boost/compute/memory.hpp b/boost/compute/memory.hpp
new file mode 100644
index 0000000000..b4dccf4890
--- /dev/null
+++ b/boost/compute/memory.hpp
@@ -0,0 +1,21 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_MEMORY_HPP
+#define BOOST_COMPUTE_MEMORY_HPP
+
+/// \file
+///
+/// Meta-header to include all Boost.Compute memory headers.
+
+#include <boost/compute/memory/local_buffer.hpp>
+#include <boost/compute/memory/svm_ptr.hpp>
+
+#endif // BOOST_COMPUTE_MEMORY_HPP
diff --git a/boost/compute/memory/local_buffer.hpp b/boost/compute/memory/local_buffer.hpp
new file mode 100644
index 0000000000..aaf631317a
--- /dev/null
+++ b/boost/compute/memory/local_buffer.hpp
@@ -0,0 +1,91 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_MEMORY_LOCAL_BUFFER_HPP
+#define BOOST_COMPUTE_MEMORY_LOCAL_BUFFER_HPP
+
+#include <boost/compute/cl.hpp>
+#include <boost/compute/kernel.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class local_buffer
+/// \brief Represents a local memory buffer on the device.
+///
+/// The local_buffer class represents a block of local memory on a compute
+/// device.
+///
+/// This class is most commonly used to set local memory arguments for compute
+/// kernels:
+/// \code
+/// // set argument to a local buffer with storage for 32 float's
+/// kernel.set_arg(0, local_buffer<float>(32));
+/// \endcode
+///
+/// \see buffer, kernel
+template<class T>
+class local_buffer
+{
+public:
+ /// Creates a local buffer object for \p size elements.
+ local_buffer(const size_t size)
+ : m_size(size)
+ {
+ }
+
+ /// Creates a local buffer object as a copy of \p other.
+ local_buffer(const local_buffer &other)
+ : m_size(other.m_size)
+ {
+ }
+
+ /// Copies \p other to \c *this.
+ local_buffer& operator=(const local_buffer &other)
+ {
+ if(this != &other){
+ m_size = other.m_size;
+ }
+
+ return *this;
+ }
+
+ /// Destroys the local memory object.
+ ~local_buffer()
+ {
+ }
+
+ /// Returns the number of elements in the local buffer.
+ size_t size() const
+ {
+ return m_size;
+ }
+
+private:
+ size_t m_size;
+};
+
+namespace detail {
+
+// set_kernel_arg specialization for local_buffer<T>
+template<class T>
+struct set_kernel_arg<local_buffer<T> >
+{
+ void operator()(kernel &kernel_, size_t index, const local_buffer<T> &buffer)
+ {
+ kernel_.set_arg(index, buffer.size() * sizeof(T), 0);
+ }
+};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_MEMORY_SVM_PTR_HPP
diff --git a/boost/compute/memory/svm_ptr.hpp b/boost/compute/memory/svm_ptr.hpp
new file mode 100644
index 0000000000..2dbcb8f635
--- /dev/null
+++ b/boost/compute/memory/svm_ptr.hpp
@@ -0,0 +1,81 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_MEMORY_SVM_PTR_HPP
+#define BOOST_COMPUTE_MEMORY_SVM_PTR_HPP
+
+#include <boost/compute/cl.hpp>
+#include <boost/compute/type_traits/is_device_iterator.hpp>
+
+namespace boost {
+namespace compute {
+
+template<class T>
+class svm_ptr
+{
+public:
+ typedef T value_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef T* pointer;
+ typedef T& reference;
+ typedef std::random_access_iterator_tag iterator_category;
+
+ svm_ptr()
+ : m_ptr(0)
+ {
+ }
+
+ explicit svm_ptr(void *ptr)
+ : m_ptr(static_cast<T*>(ptr))
+ {
+ }
+
+ svm_ptr(const svm_ptr<T> &other)
+ : m_ptr(other.m_ptr)
+ {
+ }
+
+ svm_ptr& operator=(const svm_ptr<T> &other)
+ {
+ m_ptr = other.m_ptr;
+ return *this;
+ }
+
+ ~svm_ptr()
+ {
+ }
+
+ void* get() const
+ {
+ return m_ptr;
+ }
+
+ svm_ptr<T> operator+(difference_type n)
+ {
+ return svm_ptr<T>(m_ptr + n);
+ }
+
+ difference_type operator-(svm_ptr<T> other)
+ {
+ return m_ptr - other.m_ptr;
+ }
+
+private:
+ T *m_ptr;
+};
+
+/// \internal_ (is_device_iterator specialization for svm_ptr)
+template<class T>
+struct is_device_iterator<svm_ptr<T> > : boost::true_type {};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_MEMORY_SVM_PTR_HPP
diff --git a/boost/compute/memory_object.hpp b/boost/compute/memory_object.hpp
new file mode 100644
index 0000000000..14c4cf4c7e
--- /dev/null
+++ b/boost/compute/memory_object.hpp
@@ -0,0 +1,264 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_MEMORY_OBJECT_HPP
+#define BOOST_COMPUTE_MEMORY_OBJECT_HPP
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/detail/get_object_info.hpp>
+#include <boost/compute/detail/assert_cl_success.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class memory_object
+/// \brief Base-class for memory objects.
+///
+/// The memory_object class is the base-class for memory objects on
+/// compute devices.
+///
+/// \see buffer, vector
+class memory_object
+{
+public:
+ /// Flags for the creation of memory objects.
+ enum mem_flags {
+ read_write = CL_MEM_READ_WRITE,
+ read_only = CL_MEM_READ_ONLY,
+ write_only = CL_MEM_WRITE_ONLY,
+ use_host_ptr = CL_MEM_USE_HOST_PTR,
+ alloc_host_ptr = CL_MEM_ALLOC_HOST_PTR,
+ copy_host_ptr = CL_MEM_COPY_HOST_PTR
+ #ifdef CL_VERSION_1_2
+ ,
+ host_write_only = CL_MEM_HOST_WRITE_ONLY,
+ host_read_only = CL_MEM_HOST_READ_ONLY,
+ host_no_access = CL_MEM_HOST_NO_ACCESS
+ #endif
+ };
+
+ /// Symbolic names for the OpenCL address spaces.
+ enum address_space {
+ global_memory,
+ local_memory,
+ private_memory,
+ constant_memory
+ };
+
+ /// Returns the underlying OpenCL memory object.
+ cl_mem& get() const
+ {
+ return const_cast<cl_mem &>(m_mem);
+ }
+
+ /// Returns the size of the memory object in bytes.
+ size_t get_memory_size() const
+ {
+ return get_memory_info<size_t>(CL_MEM_SIZE);
+ }
+
+ /// Returns the type for the memory object.
+ cl_mem_object_type get_memory_type() const
+ {
+ return get_memory_info<cl_mem_object_type>(CL_MEM_TYPE);
+ }
+
+ /// Returns the flags for the memory object.
+ cl_mem_flags get_memory_flags() const
+ {
+ return get_memory_info<cl_mem_flags>(CL_MEM_FLAGS);
+ }
+
+ /// Returns the context for the memory object.
+ context get_context() const
+ {
+ return context(get_memory_info<cl_context>(CL_MEM_CONTEXT));
+ }
+
+ /// Returns the host pointer associated with the memory object.
+ void* get_host_ptr() const
+ {
+ return get_memory_info<void *>(CL_MEM_HOST_PTR);
+ }
+
+ /// Returns the reference count for the memory object.
+ uint_ reference_count() const
+ {
+ return get_memory_info<uint_>(CL_MEM_REFERENCE_COUNT);
+ }
+
+ /// Returns information about the memory object.
+ ///
+ /// \see_opencl_ref{clGetMemObjectInfo}
+ template<class T>
+ T get_memory_info(cl_mem_info info) const
+ {
+ return detail::get_object_info<T>(clGetMemObjectInfo, m_mem, info);
+ }
+
+ #if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ /// Registers a function to be called when the memory object is deleted
+ /// and its resources freed.
+ ///
+ /// \see_opencl_ref{clSetMemObjectDestructorCallback}
+ ///
+ /// \opencl_version_warning{1,1}
+ void set_destructor_callback(void (BOOST_COMPUTE_CL_CALLBACK *callback)(
+ cl_mem memobj, void *user_data
+ ),
+ void *user_data = 0)
+ {
+ cl_int ret = clSetMemObjectDestructorCallback(m_mem, callback, user_data);
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+ }
+ /// Registers a function to be called when the memory object is deleted
+ /// and its resources freed.
+ ///
+ /// The function specified by \p callback must be invokable with zero
+ /// arguments (e.g. \c callback()).
+ ///
+ /// \opencl_version_warning{1,1}
+ template<class Function>
+ void set_destructor_callback(Function callback)
+ {
+ set_destructor_callback(
+ destructor_callback_invoker,
+ new boost::function<void()>(callback)
+ );
+ }
+ #endif // CL_VERSION_1_1
+
+ /// Returns \c true if the memory object is the same as \p other.
+ bool operator==(const memory_object &other) const
+ {
+ return m_mem == other.m_mem;
+ }
+
+ /// Returns \c true if the memory object is different from \p other.
+ bool operator!=(const memory_object &other) const
+ {
+ return m_mem != other.m_mem;
+ }
+
+private:
+ #ifdef CL_VERSION_1_1
+ /// \internal_
+ static void BOOST_COMPUTE_CL_CALLBACK
+ destructor_callback_invoker(cl_mem, void *user_data)
+ {
+ boost::function<void()> *callback =
+ static_cast<boost::function<void()> *>(user_data);
+
+ (*callback)();
+
+ delete callback;
+ }
+ #endif // CL_VERSION_1_1
+
+protected:
+ /// \internal_
+ memory_object()
+ : m_mem(0)
+ {
+ }
+
+ /// \internal_
+ explicit memory_object(cl_mem mem, bool retain = true)
+ : m_mem(mem)
+ {
+ if(m_mem && retain){
+ clRetainMemObject(m_mem);
+ }
+ }
+
+ /// \internal_
+ memory_object(const memory_object &other)
+ : m_mem(other.m_mem)
+ {
+ if(m_mem){
+ clRetainMemObject(m_mem);
+ }
+ }
+
+ /// \internal_
+ memory_object& operator=(const memory_object &other)
+ {
+ if(this != &other){
+ if(m_mem){
+ clReleaseMemObject(m_mem);
+ }
+
+ m_mem = other.m_mem;
+
+ if(m_mem){
+ clRetainMemObject(m_mem);
+ }
+ }
+
+ return *this;
+ }
+
+ #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+ /// \internal_
+ memory_object(memory_object&& other) BOOST_NOEXCEPT
+ : m_mem(other.m_mem)
+ {
+ other.m_mem = 0;
+ }
+
+ /// \internal_
+ memory_object& operator=(memory_object&& other) BOOST_NOEXCEPT
+ {
+ if(m_mem){
+ clReleaseMemObject(m_mem);
+ }
+
+ m_mem = other.m_mem;
+ other.m_mem = 0;
+
+ return *this;
+ }
+ #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+ /// \internal_
+ ~memory_object()
+ {
+ if(m_mem){
+ BOOST_COMPUTE_ASSERT_CL_SUCCESS(
+ clReleaseMemObject(m_mem)
+ );
+ }
+ }
+
+protected:
+ cl_mem m_mem;
+};
+
+namespace detail {
+
+// set_kernel_arg specialization for memory_object
+template<>
+struct set_kernel_arg<memory_object>
+{
+ void operator()(kernel &kernel_, size_t index, const memory_object &mem)
+ {
+ kernel_.set_arg(index, mem.get());
+ }
+};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_MEMORY_OBJECT_HPP
diff --git a/boost/compute/pipe.hpp b/boost/compute/pipe.hpp
new file mode 100644
index 0000000000..944674e622
--- /dev/null
+++ b/boost/compute/pipe.hpp
@@ -0,0 +1,154 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_PIPE_HPP
+#define BOOST_COMPUTE_PIPE_HPP
+
+#include <boost/compute/cl.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/memory_object.hpp>
+#include <boost/compute/exception/opencl_error.hpp>
+#include <boost/compute/detail/get_object_info.hpp>
+
+// pipe objects require opencl 2.0
+#if defined(CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+
+namespace boost {
+namespace compute {
+
+/// \class pipe
+/// \brief A FIFO data pipe
+///
+/// \opencl_version_warning{2,0}
+///
+/// \see memory_object
+class pipe : public memory_object
+{
+public:
+ /// Creates a null pipe object.
+ pipe()
+ : memory_object()
+ {
+ }
+
+ /// Creates a pipe object for \p mem. If \p retain is \c true, the
+ /// reference count for \p mem will be incremented.
+ explicit pipe(cl_mem mem, bool retain = true)
+ : memory_object(mem, retain)
+ {
+ }
+
+ /// Creates a new pipe in \p context.
+ pipe(const context &context,
+ uint_ pipe_packet_size,
+ uint_ pipe_max_packets,
+ cl_mem_flags flags = read_write,
+ const cl_pipe_properties *properties = 0)
+ {
+ cl_int error = 0;
+ m_mem = clCreatePipe(context,
+ flags,
+ pipe_packet_size,
+ pipe_max_packets,
+ properties,
+ &error);
+ if(!m_mem){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+ }
+
+ /// Creates a new pipe object as a copy of \p other.
+ pipe(const pipe &other)
+ : memory_object(other)
+ {
+ }
+
+ /// Copies the pipe object from \p other to \c *this.
+ pipe& operator=(const pipe &other)
+ {
+ if(this != &other){
+ memory_object::operator=(other);
+ }
+
+ return *this;
+ }
+
+ #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+ /// Move-constructs a new pipe object from \p other.
+ pipe(pipe&& other) BOOST_NOEXCEPT
+ : memory_object(std::move(other))
+ {
+ }
+
+ /// Move-assigns the pipe from \p other to \c *this.
+ pipe& operator=(pipe&& other) BOOST_NOEXCEPT
+ {
+ memory_object::operator=(std::move(other));
+
+ return *this;
+ }
+ #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+ /// Destroys the pipe object.
+ ~pipe()
+ {
+ }
+
+ /// Returns the packet size.
+ uint_ packet_size() const
+ {
+ return get_info<uint_>(CL_PIPE_PACKET_SIZE);
+ }
+
+ /// Returns the max number of packets.
+ uint_ max_packets() const
+ {
+ return get_info<uint_>(CL_PIPE_MAX_PACKETS);
+ }
+
+ /// Returns information about the pipe.
+ ///
+ /// \see_opencl2_ref{clGetPipeInfo}
+ template<class T>
+ T get_info(cl_pipe_info info) const
+ {
+ return detail::get_object_info<T>(clGetPipeInfo, m_mem, info);
+ }
+
+ /// \overload
+ template<int Enum>
+ typename detail::get_object_info_type<pipe, Enum>::type get_info() const;
+};
+
+/// \internal_ define get_info() specializations for pipe
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(pipe,
+ ((cl_uint, CL_PIPE_PACKET_SIZE))
+ ((cl_uint, CL_PIPE_MAX_PACKETS))
+)
+
+namespace detail {
+
+// set_kernel_arg specialization for pipe
+template<>
+struct set_kernel_arg<pipe>
+{
+ void operator()(kernel &kernel_, size_t index, const pipe &pipe_)
+ {
+ kernel_.set_arg(index, pipe_.get());
+ }
+};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // CL_VERSION_2_0
+
+#endif // BOOST_COMPUTE_PIPE_HPP
diff --git a/boost/compute/platform.hpp b/boost/compute/platform.hpp
new file mode 100644
index 0000000000..65fda84e11
--- /dev/null
+++ b/boost/compute/platform.hpp
@@ -0,0 +1,235 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_PLATFORM_HPP
+#define BOOST_COMPUTE_PLATFORM_HPP
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/classification.hpp>
+
+#include <boost/compute/cl.hpp>
+#include <boost/compute/device.hpp>
+#include <boost/compute/detail/get_object_info.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class platform
+/// \brief A compute platform.
+///
+/// The platform class provides an interface to an OpenCL platform.
+///
+/// To obtain a list of all platforms on the system use the
+/// system::platforms() method.
+///
+/// \see device, context
+class platform
+{
+public:
+ /// Creates a new platform object for \p id.
+ explicit platform(cl_platform_id id)
+ : m_platform(id)
+ {
+ }
+
+ /// Creates a new platform as a copy of \p other.
+ platform(const platform &other)
+ : m_platform(other.m_platform)
+ {
+ }
+
+ /// Copies the platform id from \p other.
+ platform& operator=(const platform &other)
+ {
+ if(this != &other){
+ m_platform = other.m_platform;
+ }
+
+ return *this;
+ }
+
+ /// Destroys the platform object.
+ ~platform()
+ {
+ }
+
+ /// Returns the ID of the platform.
+ cl_platform_id id() const
+ {
+ return m_platform;
+ }
+
+ /// Returns the name of the platform.
+ std::string name() const
+ {
+ return get_info<std::string>(CL_PLATFORM_NAME);
+ }
+
+ /// Returns the name of the vendor for the platform.
+ std::string vendor() const
+ {
+ return get_info<std::string>(CL_PLATFORM_VENDOR);
+ }
+
+ /// Returns the profile string for the platform.
+ std::string profile() const
+ {
+ return get_info<std::string>(CL_PLATFORM_PROFILE);
+ }
+
+ /// Returns the version string for the platform.
+ std::string version() const
+ {
+ return get_info<std::string>(CL_PLATFORM_VERSION);
+ }
+
+ /// Returns a list of extensions supported by the platform.
+ std::vector<std::string> extensions() const
+ {
+ std::string extensions_string =
+ get_info<std::string>(CL_PLATFORM_EXTENSIONS);
+ std::vector<std::string> extensions_vector;
+ boost::split(extensions_vector,
+ extensions_string,
+ boost::is_any_of("\t "),
+ boost::token_compress_on);
+ return extensions_vector;
+ }
+
+ /// Returns \c true if the platform supports the extension with
+ /// \p name.
+ bool supports_extension(const std::string &name) const
+ {
+ const std::vector<std::string> extensions = this->extensions();
+
+ return std::find(
+ extensions.begin(), extensions.end(), name) != extensions.end();
+ }
+
+ /// Returns a list of devices on the platform.
+ std::vector<device> devices(cl_device_type type = CL_DEVICE_TYPE_ALL) const
+ {
+ size_t count = device_count(type);
+ if(count == 0){
+ // no devices for this platform
+ return std::vector<device>();
+ }
+
+ std::vector<cl_device_id> device_ids(count);
+ cl_int ret = clGetDeviceIDs(m_platform,
+ type,
+ static_cast<cl_uint>(count),
+ &device_ids[0],
+ 0);
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ std::vector<device> devices;
+ for(cl_uint i = 0; i < count; i++){
+ devices.push_back(device(device_ids[i]));
+ }
+
+ return devices;
+ }
+
+ /// Returns the number of devices on the platform.
+ size_t device_count(cl_device_type type = CL_DEVICE_TYPE_ALL) const
+ {
+ cl_uint count = 0;
+ cl_int ret = clGetDeviceIDs(m_platform, type, 0, 0, &count);
+ if(ret != CL_SUCCESS){
+ if(ret == CL_DEVICE_NOT_FOUND){
+ // no devices for this platform
+ return 0;
+ }
+ else {
+ // something else went wrong
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+ }
+
+ return count;
+ }
+
+ /// Returns information about the platform.
+ ///
+ /// \see_opencl_ref{clGetPlatformInfo}
+ template<class T>
+ T get_info(cl_platform_info info) const
+ {
+ return detail::get_object_info<T>(clGetPlatformInfo, m_platform, info);
+ }
+
+ /// \overload
+ template<int Enum>
+ typename detail::get_object_info_type<platform, Enum>::type
+ get_info() const;
+
+ /// Returns the address of the \p function_name extension
+ /// function. Returns \c 0 if \p function_name is invalid.
+ void* get_extension_function_address(const char *function_name) const
+ {
+ #ifdef CL_VERSION_1_2
+ return clGetExtensionFunctionAddressForPlatform(m_platform,
+ function_name);
+ #else
+ return clGetExtensionFunctionAddress(function_name);
+ #endif
+ }
+
+ /// Requests that the platform unload any compiler resources.
+ void unload_compiler()
+ {
+ #ifdef CL_VERSION_1_2
+ clUnloadPlatformCompiler(m_platform);
+ #else
+ clUnloadCompiler();
+ #endif
+ }
+
+ /// Returns \c true if the platform is the same at \p other.
+ bool operator==(const platform &other) const
+ {
+ return m_platform == other.m_platform;
+ }
+
+ /// Returns \c true if the platform is different from \p other.
+ bool operator!=(const platform &other) const
+ {
+ return m_platform != other.m_platform;
+ }
+
+private:
+ cl_platform_id m_platform;
+};
+
+/// \internal_ define get_info() specializations for platform
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(platform,
+ ((std::string, CL_PLATFORM_PROFILE))
+ ((std::string, CL_PLATFORM_VERSION))
+ ((std::string, CL_PLATFORM_NAME))
+ ((std::string, CL_PLATFORM_VENDOR))
+ ((std::string, CL_PLATFORM_EXTENSIONS))
+)
+
+inline boost::compute::platform device::platform() const
+{
+ return boost::compute::platform(get_info<CL_DEVICE_PLATFORM>());
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_PLATFORM_HPP
diff --git a/boost/compute/program.hpp b/boost/compute/program.hpp
new file mode 100644
index 0000000000..7573aa02e6
--- /dev/null
+++ b/boost/compute/program.hpp
@@ -0,0 +1,650 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_PROGRAM_HPP
+#define BOOST_COMPUTE_PROGRAM_HPP
+
+#include <string>
+#include <vector>
+#include <fstream>
+#include <streambuf>
+
+#ifdef BOOST_COMPUTE_DEBUG_KERNEL_COMPILATION
+#include <iostream>
+#endif
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/exception.hpp>
+#include <boost/compute/detail/assert_cl_success.hpp>
+
+#ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE
+#include <sstream>
+#include <boost/optional.hpp>
+#include <boost/compute/platform.hpp>
+#include <boost/compute/detail/getenv.hpp>
+#include <boost/compute/detail/path.hpp>
+#include <boost/compute/detail/sha1.hpp>
+#endif
+
+namespace boost {
+namespace compute {
+
+class kernel;
+
+/// \class program
+/// \brief A compute program.
+///
+/// The program class represents an OpenCL program.
+///
+/// Program objects are created with one of the static \c create_with_*
+/// functions. For example, to create a program from a source string:
+///
+/// \snippet test/test_program.cpp create_with_source
+///
+/// And to create a program from a source file:
+/// \code
+/// boost::compute::program bar_program =
+/// boost::compute::program::create_with_source_file("/path/to/bar.cl", context);
+/// \endcode
+///
+/// Once a program object has been succesfully created, it can be compiled
+/// using the \c build() method:
+/// \code
+/// // build the program
+/// foo_program.build();
+/// \endcode
+///
+/// Once the program is built, \ref kernel objects can be created using the
+/// \c create_kernel() method by passing their name:
+/// \code
+/// // create a kernel from the compiled program
+/// boost::compute::kernel foo_kernel = foo_program.create_kernel("foo");
+/// \endcode
+///
+/// \see kernel
+class program
+{
+public:
+ /// Creates a null program object.
+ program()
+ : m_program(0)
+ {
+ }
+
+ /// Creates a program object for \p program. If \p retain is \c true,
+ /// the reference count for \p program will be incremented.
+ explicit program(cl_program program, bool retain = true)
+ : m_program(program)
+ {
+ if(m_program && retain){
+ clRetainProgram(m_program);
+ }
+ }
+
+ /// Creates a new program object as a copy of \p other.
+ program(const program &other)
+ : m_program(other.m_program)
+ {
+ if(m_program){
+ clRetainProgram(m_program);
+ }
+ }
+
+ /// Copies the program object from \p other to \c *this.
+ program& operator=(const program &other)
+ {
+ if(this != &other){
+ if(m_program){
+ clReleaseProgram(m_program);
+ }
+
+ m_program = other.m_program;
+
+ if(m_program){
+ clRetainProgram(m_program);
+ }
+ }
+
+ return *this;
+ }
+
+ #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+ /// Move-constructs a new program object from \p other.
+ program(program&& other) BOOST_NOEXCEPT
+ : m_program(other.m_program)
+ {
+ other.m_program = 0;
+ }
+
+ /// Move-assigns the program from \p other to \c *this.
+ program& operator=(program&& other) BOOST_NOEXCEPT
+ {
+ if(m_program){
+ clReleaseProgram(m_program);
+ }
+
+ m_program = other.m_program;
+ other.m_program = 0;
+
+ return *this;
+ }
+ #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+ /// Destroys the program object.
+ ~program()
+ {
+ if(m_program){
+ BOOST_COMPUTE_ASSERT_CL_SUCCESS(
+ clReleaseProgram(m_program)
+ );
+ }
+ }
+
+ /// Returns the underlying OpenCL program.
+ cl_program& get() const
+ {
+ return const_cast<cl_program &>(m_program);
+ }
+
+ /// Returns the source code for the program.
+ std::string source() const
+ {
+ return get_info<std::string>(CL_PROGRAM_SOURCE);
+ }
+
+ /// Returns the binary for the program.
+ std::vector<unsigned char> binary() const
+ {
+ size_t binary_size = get_info<size_t>(CL_PROGRAM_BINARY_SIZES);
+ std::vector<unsigned char> binary(binary_size);
+
+ unsigned char *binary_ptr = &binary[0];
+ cl_int error = clGetProgramInfo(m_program,
+ CL_PROGRAM_BINARIES,
+ sizeof(unsigned char **),
+ &binary_ptr,
+ 0);
+ if(error != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+
+ return binary;
+ }
+
+ std::vector<device> get_devices() const
+ {
+ std::vector<cl_device_id> device_ids =
+ get_info<std::vector<cl_device_id> >(CL_PROGRAM_DEVICES);
+
+ std::vector<device> devices;
+ for(size_t i = 0; i < device_ids.size(); i++){
+ devices.push_back(device(device_ids[i]));
+ }
+
+ return devices;
+ }
+
+ /// Returns the context for the program.
+ context get_context() const
+ {
+ return context(get_info<cl_context>(CL_PROGRAM_CONTEXT));
+ }
+
+ /// Returns information about the program.
+ ///
+ /// \see_opencl_ref{clGetProgramInfo}
+ template<class T>
+ T get_info(cl_program_info info) const
+ {
+ return detail::get_object_info<T>(clGetProgramInfo, m_program, info);
+ }
+
+ /// \overload
+ template<int Enum>
+ typename detail::get_object_info_type<program, Enum>::type
+ get_info() const;
+
+ /// Returns build information about the program.
+ ///
+ /// For example, this function can be used to retreive the options used
+ /// to build the program:
+ /// \code
+ /// std::string build_options =
+ /// program.get_build_info<std::string>(CL_PROGRAM_BUILD_OPTIONS);
+ /// \endcode
+ ///
+ /// \see_opencl_ref{clGetProgramInfo}
+ template<class T>
+ T get_build_info(cl_program_build_info info, const device &device) const
+ {
+ return detail::get_object_info<T>(clGetProgramBuildInfo, m_program, info, device.id());
+ }
+
+ /// Builds the program with \p options.
+ ///
+ /// If the program fails to compile, this function will throw an
+ /// opencl_error exception.
+ /// \code
+ /// try {
+ /// // attempt to compile to program
+ /// program.build();
+ /// }
+ /// catch(boost::compute::opencl_error &e){
+ /// // program failed to compile, print out the build log
+ /// std::cout << program.build_log() << std::endl;
+ /// }
+ /// \endcode
+ ///
+ /// \see_opencl_ref{clBuildProgram}
+ void build(const std::string &options = std::string())
+ {
+ const char *options_string = 0;
+
+ if(!options.empty()){
+ options_string = options.c_str();
+ }
+
+ cl_int ret = clBuildProgram(m_program, 0, 0, options_string, 0, 0);
+
+ #ifdef BOOST_COMPUTE_DEBUG_KERNEL_COMPILATION
+ if(ret != CL_SUCCESS){
+ // print the error, source code and build log
+ std::cerr << "Boost.Compute: "
+ << "kernel compilation failed (" << ret << ")\n"
+ << "--- source ---\n"
+ << source()
+ << "\n--- build log ---\n"
+ << build_log()
+ << std::endl;
+ }
+ #endif
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+ }
+
+ #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ /// Compiles the program with \p options.
+ ///
+ /// \opencl_version_warning{1,2}
+ ///
+ /// \see_opencl_ref{clCompileProgram}
+ void compile(const std::string &options = std::string())
+ {
+ const char *options_string = 0;
+
+ if(!options.empty()){
+ options_string = options.c_str();
+ }
+
+ cl_int ret = clCompileProgram(
+ m_program, 0, 0, options_string, 0, 0, 0, 0, 0
+ );
+
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+ }
+
+ /// Links the programs in \p programs with \p options in \p context.
+ ///
+ /// \opencl_version_warning{1,2}
+ ///
+ /// \see_opencl_ref{clLinkProgram}
+ static program link(const std::vector<program> &programs,
+ const context &context,
+ const std::string &options = std::string())
+ {
+ const char *options_string = 0;
+
+ if(!options.empty()){
+ options_string = options.c_str();
+ }
+
+ cl_int ret;
+ cl_program program_ = clLinkProgram(
+ context.get(),
+ 0,
+ 0,
+ options_string,
+ static_cast<uint_>(programs.size()),
+ reinterpret_cast<const cl_program*>(&programs[0]),
+ 0,
+ 0,
+ &ret
+ );
+
+ if(!program_){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+
+ return program(program_, false);
+ }
+ #endif // CL_VERSION_1_2
+
+ /// Returns the build log.
+ std::string build_log() const
+ {
+ return get_build_info<std::string>(CL_PROGRAM_BUILD_LOG, get_devices().front());
+ }
+
+ /// Creates and returns a new kernel object for \p name.
+ ///
+ /// For example, to create the \c "foo" kernel (after the program has been
+ /// created and built):
+ /// \code
+ /// boost::compute::kernel foo_kernel = foo_program.create_kernel("foo");
+ /// \endcode
+ kernel create_kernel(const std::string &name) const;
+
+ /// Returns \c true if the program is the same at \p other.
+ bool operator==(const program &other) const
+ {
+ return m_program == other.m_program;
+ }
+
+ /// Returns \c true if the program is different from \p other.
+ bool operator!=(const program &other) const
+ {
+ return m_program != other.m_program;
+ }
+
+ /// \internal_
+ operator cl_program() const
+ {
+ return m_program;
+ }
+
+ /// Creates a new program with \p source in \p context.
+ ///
+ /// \see_opencl_ref{clCreateProgramWithSource}
+ static program create_with_source(const std::string &source,
+ const context &context)
+ {
+ const char *source_string = source.c_str();
+
+ cl_int error = 0;
+ cl_program program_ = clCreateProgramWithSource(context,
+ uint_(1),
+ &source_string,
+ 0,
+ &error);
+ if(!program_){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+
+ return program(program_, false);
+ }
+
+ /// Creates a new program with \p sources in \p context.
+ ///
+ /// \see_opencl_ref{clCreateProgramWithSource}
+ static program create_with_source(const std::vector<std::string> &sources,
+ const context &context)
+ {
+ std::vector<const char*> source_strings(sources.size());
+ for(size_t i = 0; i < sources.size(); i++){
+ source_strings[i] = sources[i].c_str();
+ }
+
+ cl_int error = 0;
+ cl_program program_ = clCreateProgramWithSource(context,
+ uint_(sources.size()),
+ &source_strings[0],
+ 0,
+ &error);
+ if(!program_){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+
+ return program(program_, false);
+ }
+
+ /// Creates a new program with \p file in \p context.
+ ///
+ /// \see_opencl_ref{clCreateProgramWithSource}
+ static program create_with_source_file(const std::string &file,
+ const context &context)
+ {
+ // open file stream
+ std::ifstream stream(file.c_str());
+
+ if(stream.fail()){
+ BOOST_THROW_EXCEPTION(std::ios_base::failure("failed to create stream."));
+ }
+
+ // read source
+ std::string source(
+ (std::istreambuf_iterator<char>(stream)),
+ std::istreambuf_iterator<char>()
+ );
+
+ // create program
+ return create_with_source(source, context);
+ }
+
+ /// Creates a new program with \p binary of \p binary_size in
+ /// \p context.
+ ///
+ /// \see_opencl_ref{clCreateProgramWithBinary}
+ static program create_with_binary(const unsigned char *binary,
+ size_t binary_size,
+ const context &context)
+ {
+ const cl_device_id device = context.get_device().id();
+
+ cl_int error = 0;
+ cl_int binary_status = 0;
+ cl_program program_ = clCreateProgramWithBinary(context,
+ uint_(1),
+ &device,
+ &binary_size,
+ &binary,
+ &binary_status,
+ &error);
+ if(!program_){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+ if(binary_status != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(binary_status));
+ }
+
+ return program(program_, false);
+ }
+
+ /// Creates a new program with \p binary in \p context.
+ ///
+ /// \see_opencl_ref{clCreateProgramWithBinary}
+ static program create_with_binary(const std::vector<unsigned char> &binary,
+ const context &context)
+ {
+ return create_with_binary(&binary[0], binary.size(), context);
+ }
+
+ /// Creates a new program with \p file in \p context.
+ ///
+ /// \see_opencl_ref{clCreateProgramWithBinary}
+ static program create_with_binary_file(const std::string &file,
+ const context &context)
+ {
+ // open file stream
+ std::ifstream stream(file.c_str(), std::ios::in | std::ios::binary);
+
+ // read binary
+ std::vector<unsigned char> binary(
+ (std::istreambuf_iterator<char>(stream)),
+ std::istreambuf_iterator<char>()
+ );
+
+ // create program
+ return create_with_binary(&binary[0], binary.size(), context);
+ }
+
+ #if defined(CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+ /// Creates a new program with the built-in kernels listed in
+ /// \p kernel_names for \p devices in \p context.
+ ///
+ /// \opencl_version_warning{1,2}
+ ///
+ /// \see_opencl_ref{clCreateProgramWithBuiltInKernels}
+ static program create_with_builtin_kernels(const context &context,
+ const std::vector<device> &devices,
+ const std::string &kernel_names)
+ {
+ cl_int error = 0;
+
+ cl_program program_ = clCreateProgramWithBuiltInKernels(
+ context.get(),
+ static_cast<uint_>(devices.size()),
+ reinterpret_cast<const cl_device_id *>(&devices[0]),
+ kernel_names.c_str(),
+ &error
+ );
+
+ if(!program_){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+
+ return program(program_, false);
+ }
+ #endif // CL_VERSION_1_2
+
+ /// Create a new program with \p source in \p context and builds it with \p options.
+ /**
+ * In case BOOST_COMPUTE_USE_OFFLINE_CACHE macro is defined,
+ * the compiled binary is stored for reuse in the offline cache located in
+ * $HOME/.boost_compute on UNIX-like systems and in %APPDATA%/boost_compute
+ * on Windows.
+ */
+ static program build_with_source(
+ const std::string &source,
+ const context &context,
+ const std::string &options = std::string()
+ )
+ {
+#ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE
+ // Get hash string for the kernel.
+ device d = context.get_device();
+ platform p = d.platform();
+
+ detail::sha1 hash;
+ hash.process( p.name() )
+ .process( p.version() )
+ .process( d.name() )
+ .process( options )
+ .process( source )
+ ;
+
+ // Try to get cached program binaries:
+ try {
+ boost::optional<program> prog = load_program_binary(hash, context);
+
+ if (prog) {
+ prog->build(options);
+ return *prog;
+ }
+ } catch (...) {
+ // Something bad happened. Fallback to normal compilation.
+ }
+
+ // Cache is apparently not available. Just compile the sources.
+#endif
+ const char *source_string = source.c_str();
+
+ cl_int error = 0;
+ cl_program program_ = clCreateProgramWithSource(context,
+ uint_(1),
+ &source_string,
+ 0,
+ &error);
+ if(!program_){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+
+ program prog(program_, false);
+ prog.build(options);
+
+#ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE
+ // Save program binaries for future reuse.
+ save_program_binary(hash, prog);
+#endif
+
+ return prog;
+ }
+
+private:
+#ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE
+ // Saves program binaries for future reuse.
+ static void save_program_binary(const std::string &hash, const program &prog)
+ {
+ std::string fname = detail::program_binary_path(hash, true) + "kernel";
+ std::ofstream bfile(fname.c_str(), std::ios::binary);
+ if (!bfile) return;
+
+ std::vector<unsigned char> binary = prog.binary();
+
+ size_t binary_size = binary.size();
+ bfile.write((char*)&binary_size, sizeof(size_t));
+ bfile.write((char*)binary.data(), binary_size);
+ }
+
+ // Tries to read program binaries from file cache.
+ static boost::optional<program> load_program_binary(
+ const std::string &hash, const context &ctx
+ )
+ {
+ std::string fname = detail::program_binary_path(hash) + "kernel";
+ std::ifstream bfile(fname.c_str(), std::ios::binary);
+ if (!bfile) return boost::optional<program>();
+
+ size_t binary_size;
+ std::vector<unsigned char> binary;
+
+ bfile.read((char*)&binary_size, sizeof(size_t));
+
+ binary.resize(binary_size);
+ bfile.read((char*)binary.data(), binary_size);
+
+ return boost::optional<program>(
+ program::create_with_binary(
+ binary.data(), binary_size, ctx
+ )
+ );
+ }
+#endif // BOOST_COMPUTE_USE_OFFLINE_CACHE
+
+private:
+ cl_program m_program;
+};
+
+/// \internal_ define get_info() specializations for program
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(program,
+ ((cl_uint, CL_PROGRAM_REFERENCE_COUNT))
+ ((cl_context, CL_PROGRAM_CONTEXT))
+ ((cl_uint, CL_PROGRAM_NUM_DEVICES))
+ ((std::vector<cl_device_id>, CL_PROGRAM_DEVICES))
+ ((std::string, CL_PROGRAM_SOURCE))
+ ((std::vector<size_t>, CL_PROGRAM_BINARY_SIZES))
+ ((std::vector<unsigned char *>, CL_PROGRAM_BINARIES))
+)
+
+#ifdef CL_VERSION_1_2
+BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(program,
+ ((size_t, CL_PROGRAM_NUM_KERNELS))
+ ((std::string, CL_PROGRAM_KERNEL_NAMES))
+)
+#endif // CL_VERSION_1_2
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_PROGRAM_HPP
diff --git a/boost/compute/random.hpp b/boost/compute/random.hpp
new file mode 100644
index 0000000000..1a361fe48b
--- /dev/null
+++ b/boost/compute/random.hpp
@@ -0,0 +1,28 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_RANDOM_HPP
+#define BOOST_COMPUTE_RANDOM_HPP
+
+/// \file
+///
+/// Meta-header to include all Boost.Compute random headers.
+
+#include <boost/compute/random/bernoulli_distribution.hpp>
+#include <boost/compute/random/default_random_engine.hpp>
+#include <boost/compute/random/discrete_distribution.hpp>
+#include <boost/compute/random/linear_congruential_engine.hpp>
+#include <boost/compute/random/mersenne_twister_engine.hpp>
+#include <boost/compute/random/threefry_engine.hpp>
+#include <boost/compute/random/normal_distribution.hpp>
+#include <boost/compute/random/uniform_int_distribution.hpp>
+#include <boost/compute/random/uniform_real_distribution.hpp>
+
+#endif // BOOST_COMPUTE_RANDOM_HPP
diff --git a/boost/compute/random/bernoulli_distribution.hpp b/boost/compute/random/bernoulli_distribution.hpp
new file mode 100644
index 0000000000..edd1125090
--- /dev/null
+++ b/boost/compute/random/bernoulli_distribution.hpp
@@ -0,0 +1,92 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_RANDOM_BERNOULLI_DISTRIBUTION_HPP
+#define BOOST_COMPUTE_RANDOM_BERNOULLI_DISTRIBUTION_HPP
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/function.hpp>
+#include <boost/compute/types/fundamental.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/detail/literal.hpp>
+
+namespace boost {
+namespace compute {
+
+///
+/// \class bernoulli_distribution
+/// \brief Produces random boolean values according to the following
+/// discrete probability function with parameter p :
+/// P(true/p) = p and P(false/p) = (1 - p)
+///
+/// The following example shows how to setup a bernoulli distribution to
+/// produce random boolean values with parameter p = 0.25
+///
+/// \snippet test/test_bernoulli_distribution.cpp generate
+///
+template<class RealType = float>
+class bernoulli_distribution
+{
+public:
+
+ /// Creates a new bernoulli distribution
+ bernoulli_distribution(RealType p = 0.5f)
+ : m_p(p)
+ {
+ }
+
+ /// Destroys the bernoulli_distribution object
+ ~bernoulli_distribution()
+ {
+ }
+
+ /// Returns the value of the parameter p
+ RealType p() const
+ {
+ return m_p;
+ }
+
+ /// Generates bernoulli distributed booleans and stores
+ /// them in the range [\p first, \p last).
+ template<class OutputIterator, class Generator>
+ void generate(OutputIterator first,
+ OutputIterator last,
+ Generator &generator,
+ command_queue &queue)
+ {
+ size_t count = detail::iterator_range_size(first, last);
+
+ vector<uint_> tmp(count, queue.get_context());
+ generator.generate(tmp.begin(), tmp.end(), queue);
+
+ BOOST_COMPUTE_FUNCTION(bool, scale_random, (const uint_ x),
+ {
+ return (convert_RealType(x) / MAX_RANDOM) < PARAM;
+ });
+
+ scale_random.define("PARAM", detail::make_literal(m_p));
+ scale_random.define("MAX_RANDOM", "UINT_MAX");
+ scale_random.define(
+ "convert_RealType", std::string("convert_") + type_name<RealType>()
+ );
+
+ transform(
+ tmp.begin(), tmp.end(), first, scale_random, queue
+ );
+ }
+
+private:
+ RealType m_p;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_RANDOM_BERNOULLI_DISTRIBUTION_HPP
diff --git a/boost/compute/random/default_random_engine.hpp b/boost/compute/random/default_random_engine.hpp
new file mode 100644
index 0000000000..b34dbd01fa
--- /dev/null
+++ b/boost/compute/random/default_random_engine.hpp
@@ -0,0 +1,24 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_RANDOM_DEFAULT_RANDOM_ENGINE_HPP
+#define BOOST_COMPUTE_RANDOM_DEFAULT_RANDOM_ENGINE_HPP
+
+#include <boost/compute/random/mersenne_twister_engine.hpp>
+
+namespace boost {
+namespace compute {
+
+typedef mt19937 default_random_engine;
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_RANDOM_DEFAULT_RANDOM_ENGINE_HPP
diff --git a/boost/compute/random/discrete_distribution.hpp b/boost/compute/random/discrete_distribution.hpp
new file mode 100644
index 0000000000..3707928f98
--- /dev/null
+++ b/boost/compute/random/discrete_distribution.hpp
@@ -0,0 +1,117 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_RANDOM_DISCRETE_DISTRIBUTION_HPP
+#define BOOST_COMPUTE_RANDOM_DISCRETE_DISTRIBUTION_HPP
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/function.hpp>
+#include <boost/compute/algorithm/accumulate.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/detail/literal.hpp>
+#include <boost/compute/types/fundamental.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class discrete_distribution
+/// \brief Produces random integers on the interval [0, n), where
+/// probability of each integer is given by the weight of the ith
+/// integer divided by the sum of all weights.
+///
+/// The following example shows how to setup a discrete distribution to
+/// produce 0 and 1 with equal probability
+///
+/// \snippet test/test_discrete_distribution.cpp generate
+///
+template<class IntType = uint_>
+class discrete_distribution
+{
+public:
+ typedef IntType result_type;
+
+ /// Creates a new discrete distribution with weights given by
+ /// the range [\p first, \p last)
+ template<class InputIterator>
+ discrete_distribution(InputIterator first, InputIterator last)
+ : m_n(std::distance(first, last)),
+ m_probabilities(std::distance(first, last))
+ {
+ double sum = 0;
+
+ for(InputIterator iter = first; iter!=last; iter++)
+ {
+ sum += *iter;
+ }
+
+ for(size_t i=0; i<m_n; i++)
+ {
+ m_probabilities[i] = m_probabilities[i-1] + first[i]/sum;
+ }
+ }
+
+ /// Destroys the discrete_distribution object.
+ ~discrete_distribution()
+ {
+ }
+
+ /// Returns the value of n
+ result_type n() const
+ {
+ return m_n;
+ }
+
+ /// Returns the probabilities
+ ::std::vector<double> probabilities() const
+ {
+ return m_probabilities;
+ }
+
+ /// Generates uniformily distributed integers and stores
+ /// them to the range [\p first, \p last).
+ template<class OutputIterator, class Generator>
+ void generate(OutputIterator first,
+ OutputIterator last,
+ Generator &generator,
+ command_queue &queue)
+ {
+ std::string source = "inline uint scale_random(uint x)\n";
+
+ source = source +
+ "{\n" +
+ "float rno = convert_float(x) / UINT_MAX;\n";
+ for(size_t i=0; i<m_n; i++)
+ {
+ source = source +
+ "if(rno <= " + detail::make_literal<float>(m_probabilities[i]) + ")\n" +
+ " return " + detail::make_literal(i) + ";\n";
+ }
+
+ source = source +
+ "return " + detail::make_literal(m_n - 1) + ";\n" +
+ "}\n";
+
+ BOOST_COMPUTE_FUNCTION(IntType, scale_random, (const uint_ x), {});
+
+ scale_random.set_source(source);
+
+ generator.generate(first, last, scale_random, queue);
+ }
+
+private:
+ size_t m_n;
+ ::std::vector<double> m_probabilities;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_RANDOM_UNIFORM_INT_DISTRIBUTION_HPP
diff --git a/boost/compute/random/linear_congruential_engine.hpp b/boost/compute/random/linear_congruential_engine.hpp
new file mode 100644
index 0000000000..173a6c2881
--- /dev/null
+++ b/boost/compute/random/linear_congruential_engine.hpp
@@ -0,0 +1,238 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_RANDOM_LINEAR_CONGRUENTIAL_ENGINE_HPP
+#define BOOST_COMPUTE_RANDOM_LINEAR_CONGRUENTIAL_ENGINE_HPP
+
+#include <algorithm>
+
+#include <boost/compute/types.hpp>
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/program.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/iterator/discard_iterator.hpp>
+#include <boost/compute/utility/program_cache.hpp>
+
+namespace boost {
+namespace compute {
+
+///
+/// \class linear_congruential_engine
+/// \brief 'Quick and Dirty' linear congruential engine
+///
+/// Quick and dirty linear congruential engine to generate low quality
+/// random numbers very quickly. For uses in which good quality of random
+/// numbers is required(Monte-Carlo Simulations), use other engines like
+/// Mersenne Twister instead.
+///
+template<class T = uint_>
+class linear_congruential_engine
+{
+public:
+ typedef T result_type;
+ static const T default_seed = 1;
+ static const T a = 1099087573;
+ static const size_t threads = 1024;
+
+ /// Creates a new linear_congruential_engine and seeds it with \p value.
+ explicit linear_congruential_engine(command_queue &queue,
+ result_type value = default_seed)
+ : m_context(queue.get_context()),
+ m_multiplicands(m_context, threads * sizeof(result_type))
+ {
+ // setup program
+ load_program();
+
+ // seed state
+ seed(value, queue);
+
+ // generate multiplicands
+ generate_multiplicands(queue);
+ }
+
+ /// Creates a new linear_congruential_engine object as a copy of \p other.
+ linear_congruential_engine(const linear_congruential_engine<T> &other)
+ : m_context(other.m_context),
+ m_program(other.m_program),
+ m_seed(other.m_seed),
+ m_multiplicands(other.m_multiplicands)
+ {
+ }
+
+ /// Copies \p other to \c *this.
+ linear_congruential_engine<T>&
+ operator=(const linear_congruential_engine<T> &other)
+ {
+ if(this != &other){
+ m_context = other.m_context;
+ m_program = other.m_program;
+ m_seed = other.m_seed;
+ m_multiplicands = other.m_multiplicands;
+ }
+
+ return *this;
+ }
+
+ /// Destroys the linear_congruential_engine object.
+ ~linear_congruential_engine()
+ {
+ }
+
+ /// Seeds the random number generator with \p value.
+ ///
+ /// \param value seed value for the random-number generator
+ /// \param queue command queue to perform the operation
+ ///
+ /// If no seed value is provided, \c default_seed is used.
+ void seed(result_type value, command_queue &queue)
+ {
+ (void) queue;
+
+ m_seed = value;
+ }
+
+ /// \overload
+ void seed(command_queue &queue)
+ {
+ seed(default_seed, queue);
+ }
+
+ /// Generates random numbers and stores them to the range [\p first, \p last).
+ template<class OutputIterator>
+ void generate(OutputIterator first, OutputIterator last, command_queue &queue)
+ {
+ size_t size = detail::iterator_range_size(first, last);
+
+ kernel fill_kernel(m_program, "fill");
+ fill_kernel.set_arg(1, m_multiplicands);
+ fill_kernel.set_arg(2, first.get_buffer());
+
+ size_t offset = 0;
+
+ for(;;){
+ size_t count = 0;
+ if(size > threads){
+ count = (std::min)(static_cast<size_t>(threads), size - offset);
+ }
+ else {
+ count = size;
+ }
+ fill_kernel.set_arg(0, static_cast<const uint_>(m_seed));
+ fill_kernel.set_arg(3, static_cast<const uint_>(offset));
+ queue.enqueue_1d_range_kernel(fill_kernel, 0, count, 0);
+
+ offset += count;
+
+ if(offset >= size){
+ break;
+ }
+
+ update_seed(queue);
+ }
+ }
+
+ /// \internal_
+ void generate(discard_iterator first, discard_iterator last, command_queue &queue)
+ {
+ (void) queue;
+
+ size_t size = detail::iterator_range_size(first, last);
+ uint_ max_mult =
+ detail::read_single_value<T>(m_multiplicands, threads-1, queue);
+ while(size >= threads) {
+ m_seed *= max_mult;
+ size -= threads;
+ }
+ m_seed *=
+ detail::read_single_value<T>(m_multiplicands, size-1, queue);
+ }
+
+ /// Generates random numbers, transforms them with \p op, and then stores
+ /// them to the range [\p first, \p last).
+ template<class OutputIterator, class Function>
+ void generate(OutputIterator first, OutputIterator last, Function op, command_queue &queue)
+ {
+ vector<T> tmp(std::distance(first, last), queue.get_context());
+ generate(tmp.begin(), tmp.end(), queue);
+ transform(tmp.begin(), tmp.end(), first, op, queue);
+ }
+
+ /// Generates \p z random numbers and discards them.
+ void discard(size_t z, command_queue &queue)
+ {
+ generate(discard_iterator(0), discard_iterator(z), queue);
+ }
+
+private:
+ /// \internal_
+ /// Generates the multiplicands for each thread
+ void generate_multiplicands(command_queue &queue)
+ {
+ kernel multiplicand_kernel =
+ m_program.create_kernel("multiplicand");
+ multiplicand_kernel.set_arg(0, m_multiplicands);
+
+ queue.enqueue_task(multiplicand_kernel);
+ }
+
+ /// \internal_
+ void update_seed(command_queue &queue)
+ {
+ m_seed *=
+ detail::read_single_value<T>(m_multiplicands, threads-1, queue);
+ }
+
+ /// \internal_
+ void load_program()
+ {
+ boost::shared_ptr<program_cache> cache =
+ program_cache::get_global_cache(m_context);
+
+ std::string cache_key =
+ std::string("__boost_linear_congruential_engine_") + type_name<T>();
+
+ const char source[] =
+ "__kernel void multiplicand(__global uint *multiplicands)\n"
+ "{\n"
+ " uint a = 1099087573;\n"
+ " multiplicands[0] = a;\n"
+ " for(uint i = 1; i < 1024; i++){\n"
+ " multiplicands[i] = a * multiplicands[i-1];\n"
+ " }\n"
+ "}\n"
+
+ "__kernel void fill(const uint seed,\n"
+ " __global uint *multiplicands,\n"
+ " __global uint *result,"
+ " const uint offset)\n"
+ "{\n"
+ " const uint i = get_global_id(0);\n"
+ " result[offset+i] = seed * multiplicands[i];\n"
+ "}\n";
+
+ m_program = cache->get_or_build(cache_key, std::string(), source, m_context);
+ }
+
+private:
+ context m_context;
+ program m_program;
+ T m_seed;
+ buffer m_multiplicands;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_RANDOM_LINEAR_CONGRUENTIAL_ENGINE_HPP
diff --git a/boost/compute/random/mersenne_twister_engine.hpp b/boost/compute/random/mersenne_twister_engine.hpp
new file mode 100644
index 0000000000..db8560e53d
--- /dev/null
+++ b/boost/compute/random/mersenne_twister_engine.hpp
@@ -0,0 +1,254 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_RANDOM_MERSENNE_TWISTER_ENGINE_HPP
+#define BOOST_COMPUTE_RANDOM_MERSENNE_TWISTER_ENGINE_HPP
+
+#include <algorithm>
+
+#include <boost/compute/types.hpp>
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/program.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/iterator/discard_iterator.hpp>
+#include <boost/compute/utility/program_cache.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class mersenne_twister_engine
+/// \brief Mersenne twister pseudorandom number generator.
+template<class T>
+class mersenne_twister_engine
+{
+public:
+ typedef T result_type;
+ static const T default_seed = 5489U;
+ static const T n = 624;
+ static const T m = 397;
+
+ /// Creates a new mersenne_twister_engine and seeds it with \p value.
+ explicit mersenne_twister_engine(command_queue &queue,
+ result_type value = default_seed)
+ : m_context(queue.get_context()),
+ m_state_buffer(m_context, n * sizeof(result_type))
+ {
+ // setup program
+ load_program();
+
+ // seed state
+ seed(value, queue);
+ }
+
+ /// Creates a new mersenne_twister_engine object as a copy of \p other.
+ mersenne_twister_engine(const mersenne_twister_engine<T> &other)
+ : m_context(other.m_context),
+ m_state_index(other.m_state_index),
+ m_program(other.m_program),
+ m_state_buffer(other.m_state_buffer)
+ {
+ }
+
+ /// Copies \p other to \c *this.
+ mersenne_twister_engine<T>& operator=(const mersenne_twister_engine<T> &other)
+ {
+ if(this != &other){
+ m_context = other.m_context;
+ m_state_index = other.m_state_index;
+ m_program = other.m_program;
+ m_state_buffer = other.m_state_buffer;
+ }
+
+ return *this;
+ }
+
+ /// Destroys the mersenne_twister_engine object.
+ ~mersenne_twister_engine()
+ {
+ }
+
+ /// Seeds the random number generator with \p value.
+ ///
+ /// \param value seed value for the random-number generator
+ /// \param queue command queue to perform the operation
+ ///
+ /// If no seed value is provided, \c default_seed is used.
+ void seed(result_type value, command_queue &queue)
+ {
+ kernel seed_kernel = m_program.create_kernel("seed");
+ seed_kernel.set_arg(0, value);
+ seed_kernel.set_arg(1, m_state_buffer);
+
+ queue.enqueue_task(seed_kernel);
+
+ m_state_index = 0;
+ }
+
+ /// \overload
+ void seed(command_queue &queue)
+ {
+ seed(default_seed, queue);
+ }
+
+ /// Generates random numbers and stores them to the range [\p first, \p last).
+ template<class OutputIterator>
+ void generate(OutputIterator first, OutputIterator last, command_queue &queue)
+ {
+ const size_t size = detail::iterator_range_size(first, last);
+
+ kernel fill_kernel(m_program, "fill");
+ fill_kernel.set_arg(0, m_state_buffer);
+ fill_kernel.set_arg(2, first.get_buffer());
+
+ size_t offset = 0;
+ size_t &p = m_state_index;
+
+ for(;;){
+ size_t count = 0;
+ if(size > n){
+ count = (std::min)(static_cast<size_t>(n), size - offset);
+ }
+ else {
+ count = size;
+ }
+ fill_kernel.set_arg(1, static_cast<const uint_>(p));
+ fill_kernel.set_arg(3, static_cast<const uint_>(offset));
+ queue.enqueue_1d_range_kernel(fill_kernel, 0, count, 0);
+
+ p += count;
+ offset += count;
+
+ if(offset >= size){
+ break;
+ }
+
+ generate_state(queue);
+ p = 0;
+ }
+ }
+
+ /// \internal_
+ void generate(discard_iterator first, discard_iterator last, command_queue &queue)
+ {
+ (void) queue;
+
+ m_state_index += std::distance(first, last);
+ }
+
+ /// Generates random numbers, transforms them with \p op, and then stores
+ /// them to the range [\p first, \p last).
+ template<class OutputIterator, class Function>
+ void generate(OutputIterator first, OutputIterator last, Function op, command_queue &queue)
+ {
+ vector<T> tmp(std::distance(first, last), queue.get_context());
+ generate(tmp.begin(), tmp.end(), queue);
+ transform(tmp.begin(), tmp.end(), first, op, queue);
+ }
+
+ /// Generates \p z random numbers and discards them.
+ void discard(size_t z, command_queue &queue)
+ {
+ generate(discard_iterator(0), discard_iterator(z), queue);
+ }
+
+ /// \internal_ (deprecated)
+ template<class OutputIterator>
+ void fill(OutputIterator first, OutputIterator last, command_queue &queue)
+ {
+ generate(first, last, queue);
+ }
+
+private:
+ /// \internal_
+ void generate_state(command_queue &queue)
+ {
+ kernel generate_state_kernel =
+ m_program.create_kernel("generate_state");
+ generate_state_kernel.set_arg(0, m_state_buffer);
+ queue.enqueue_task(generate_state_kernel);
+ }
+
+ /// \internal_
+ void load_program()
+ {
+ boost::shared_ptr<program_cache> cache =
+ program_cache::get_global_cache(m_context);
+
+ std::string cache_key =
+ std::string("__boost_mersenne_twister_engine_") + type_name<T>();
+
+ const char source[] =
+ "static uint twiddle(uint u, uint v)\n"
+ "{\n"
+ " return (((u & 0x80000000U) | (v & 0x7FFFFFFFU)) >> 1) ^\n"
+ " ((v & 1U) ? 0x9908B0DFU : 0x0U);\n"
+ "}\n"
+
+ "__kernel void generate_state(__global uint *state)\n"
+ "{\n"
+ " const uint n = 624;\n"
+ " const uint m = 397;\n"
+ " for(uint i = 0; i < (n - m); i++)\n"
+ " state[i] = state[i+m] ^ twiddle(state[i], state[i+1]);\n"
+ " for(uint i = n - m; i < (n - 1); i++)\n"
+ " state[i] = state[i+m-n] ^ twiddle(state[i], state[i+1]);\n"
+ " state[n-1] = state[m-1] ^ twiddle(state[n-1], state[0]);\n"
+ "}\n"
+
+ "__kernel void seed(const uint s, __global uint *state)\n"
+ "{\n"
+ " const uint n = 624;\n"
+ " state[0] = s & 0xFFFFFFFFU;\n"
+ " for(uint i = 1; i < n; i++){\n"
+ " state[i] = 1812433253U * (state[i-1] ^ (state[i-1] >> 30)) + i;\n"
+ " state[i] &= 0xFFFFFFFFU;\n"
+ " }\n"
+ " generate_state(state);\n"
+ "}\n"
+
+ "static uint random_number(__global uint *state, const uint p)\n"
+ "{\n"
+ " uint x = state[p];\n"
+ " x ^= (x >> 11);\n"
+ " x ^= (x << 7) & 0x9D2C5680U;\n"
+ " x ^= (x << 15) & 0xEFC60000U;\n"
+ " return x ^ (x >> 18);\n"
+ "}\n"
+
+ "__kernel void fill(__global uint *state,\n"
+ " const uint state_index,\n"
+ " __global uint *vector,\n"
+ " const uint offset)\n"
+ "{\n"
+ " const uint i = get_global_id(0);\n"
+ " vector[offset+i] = random_number(state, state_index + i);\n"
+ "}\n";
+
+ m_program = cache->get_or_build(cache_key, std::string(), source, m_context);
+ }
+
+private:
+ context m_context;
+ size_t m_state_index;
+ program m_program;
+ buffer m_state_buffer;
+};
+
+typedef mersenne_twister_engine<uint_> mt19937;
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_RANDOM_MERSENNE_TWISTER_ENGINE_HPP
diff --git a/boost/compute/random/normal_distribution.hpp b/boost/compute/random/normal_distribution.hpp
new file mode 100644
index 0000000000..d025faeb2e
--- /dev/null
+++ b/boost/compute/random/normal_distribution.hpp
@@ -0,0 +1,124 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_RANDOM_NORMAL_DISTRIBUTION_HPP
+#define BOOST_COMPUTE_RANDOM_NORMAL_DISTRIBUTION_HPP
+
+#include <limits>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/function.hpp>
+#include <boost/compute/types/fundamental.hpp>
+#include <boost/compute/type_traits/make_vector_type.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class normal_distribution
+/// \brief Produces random, normally-distributed floating-point numbers.
+///
+/// The following example shows how to setup a normal distribution to
+/// produce random \c float values centered at \c 5:
+///
+/// \snippet test/test_normal_distribution.cpp generate
+///
+/// \see default_random_engine, uniform_real_distribution
+template<class RealType = float>
+class normal_distribution
+{
+public:
+ typedef RealType result_type;
+
+ /// Creates a new normal distribution producing numbers with the given
+ /// \p mean and \p stddev.
+ normal_distribution(RealType mean = 0.f, RealType stddev = 1.f)
+ : m_mean(mean),
+ m_stddev(stddev)
+ {
+ }
+
+ /// Destroys the normal distribution object.
+ ~normal_distribution()
+ {
+ }
+
+ /// Returns the mean value of the distribution.
+ result_type mean() const
+ {
+ return m_mean;
+ }
+
+ /// Returns the standard-deviation of the distribution.
+ result_type stddev() const
+ {
+ return m_stddev;
+ }
+
+ /// Returns the minimum value of the distribution.
+ result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const
+ {
+ return -std::numeric_limits<RealType>::infinity();
+ }
+
+ /// Returns the maximum value of the distribution.
+ result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const
+ {
+ return std::numeric_limits<RealType>::infinity();
+ }
+
+ /// Generates normally-distributed floating-point numbers and stores
+ /// them to the range [\p first, \p last).
+ template<class OutputIterator, class Generator>
+ void generate(OutputIterator first,
+ OutputIterator last,
+ Generator &generator,
+ command_queue &queue)
+ {
+ typedef typename make_vector_type<RealType, 2>::type RealType2;
+
+ size_t count = detail::iterator_range_size(first, last);
+
+ vector<uint_> tmp(count, queue.get_context());
+ generator.generate(tmp.begin(), tmp.end(), queue);
+
+ BOOST_COMPUTE_FUNCTION(RealType2, box_muller, (const uint2_ x),
+ {
+ const RealType x1 = x.x / (RealType) (UINT_MAX - 1);
+ const RealType x2 = x.y / (RealType) (UINT_MAX - 1);
+
+ const RealType z1 = sqrt(-2.f * log2(x1)) * cos(2.f * M_PI_F * x2);
+ const RealType z2 = sqrt(-2.f * log2(x1)) * sin(2.f * M_PI_F * x2);
+
+ return (RealType2)(MEAN, MEAN) + (RealType2)(z1, z2) * (RealType2)(STDDEV, STDDEV);
+ });
+
+ box_muller.define("MEAN", boost::lexical_cast<std::string>(m_mean));
+ box_muller.define("STDDEV", boost::lexical_cast<std::string>(m_stddev));
+ box_muller.define("RealType", type_name<RealType>());
+ box_muller.define("RealType2", type_name<RealType2>());
+
+ transform(
+ make_buffer_iterator<uint2_>(tmp.get_buffer(), 0),
+ make_buffer_iterator<uint2_>(tmp.get_buffer(), count / 2),
+ make_buffer_iterator<RealType2>(first.get_buffer(), 0),
+ box_muller,
+ queue
+ );
+ }
+
+private:
+ RealType m_mean;
+ RealType m_stddev;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_RANDOM_NORMAL_DISTRIBUTION_HPP
diff --git a/boost/compute/random/threefry_engine.hpp b/boost/compute/random/threefry_engine.hpp
new file mode 100644
index 0000000000..917bb72c06
--- /dev/null
+++ b/boost/compute/random/threefry_engine.hpp
@@ -0,0 +1,311 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2015 Muhammad Junaid Muzammil <mjunaidmuzammil@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_RANDOM_THREEFRY_HPP
+#define BOOST_COMPUTE_RANDOM_THREEFRY_HPP
+
+#include <algorithm>
+
+#include <boost/compute/types.hpp>
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/program.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/utility/program_cache.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/discard_iterator.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class threefry_engine
+/// \brief Threefry pseudorandom number generator.
+template<class T = uint_>
+class threefry_engine
+{
+public:
+ static const size_t threads = 1024;
+ typedef T result_type;
+
+ /// Creates a new threefry_engine and seeds it with \p value.
+ explicit threefry_engine(command_queue &queue)
+ : m_context(queue.get_context())
+ {
+ // setup program
+ load_program();
+ }
+
+ /// Creates a new threefry_engine object as a copy of \p other.
+ threefry_engine(const threefry_engine<T> &other)
+ : m_context(other.m_context),
+ m_program(other.m_program)
+ {
+ }
+
+ /// Copies \p other to \c *this.
+ threefry_engine<T>& operator=(const threefry_engine<T> &other)
+ {
+ if(this != &other){
+ m_context = other.m_context;
+ m_program = other.m_program;
+ }
+
+ return *this;
+ }
+
+ /// Destroys the threefry_engine object.
+ ~threefry_engine()
+ {
+ }
+
+private:
+ /// \internal_
+ void load_program()
+ {
+ boost::shared_ptr<program_cache> cache =
+ program_cache::get_global_cache(m_context);
+ std::string cache_key =
+ std::string("threefry_engine_32x2");
+
+ // Copyright 2010-2012, D. E. Shaw Research.
+ // All rights reserved.
+
+ // Redistribution and use in source and binary forms, with or without
+ // modification, are permitted provided that the following conditions are
+ // met:
+
+ // * Redistributions of source code must retain the above copyright
+ // notice, this list of conditions, and the following disclaimer.
+
+ // * Redistributions in binary form must reproduce the above copyright
+ // notice, this list of conditions, and the following disclaimer in the
+ // documentation and/or other materials provided with the distribution.
+
+ // * Neither the name of D. E. Shaw Research nor the names of its
+ // contributors may be used to endorse or promote products derived from
+ // this software without specific prior written permission.
+
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ const char source[] =
+ "#define THREEFRY2x32_DEFAULT_ROUNDS 20\n"
+ "#define SKEIN_KS_PARITY_32 0x1BD11BDA\n"
+
+ "enum r123_enum_threefry32x2 {\n"
+ " R_32x2_0_0=13,\n"
+ " R_32x2_1_0=15,\n"
+ " R_32x2_2_0=26,\n"
+ " R_32x2_3_0= 6,\n"
+ " R_32x2_4_0=17,\n"
+ " R_32x2_5_0=29,\n"
+ " R_32x2_6_0=16,\n"
+ " R_32x2_7_0=24\n"
+ "};\n"
+
+ "static uint RotL_32(uint x, uint N)\n"
+ "{\n"
+ " return (x << (N & 31)) | (x >> ((32-N) & 31));\n"
+ "}\n"
+
+ "struct r123array2x32 {\n"
+ " uint v[2];\n"
+ "};\n"
+ "typedef struct r123array2x32 threefry2x32_ctr_t;\n"
+ "typedef struct r123array2x32 threefry2x32_key_t;\n"
+
+ "threefry2x32_ctr_t threefry2x32_R(unsigned int Nrounds, threefry2x32_ctr_t in, threefry2x32_key_t k)\n"
+ "{\n"
+ " threefry2x32_ctr_t X;\n"
+ " uint ks[3];\n"
+ " uint i; \n"
+ " ks[2] = SKEIN_KS_PARITY_32;\n"
+ " for (i=0;i < 2; i++) {\n"
+ " ks[i] = k.v[i];\n"
+ " X.v[i] = in.v[i];\n"
+ " ks[2] ^= k.v[i];\n"
+ " }\n"
+ " X.v[0] += ks[0]; X.v[1] += ks[1];\n"
+ " if(Nrounds>0){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_0_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>1){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_1_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>2){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_2_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>3){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_3_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>3){\n"
+ " X.v[0] += ks[1]; X.v[1] += ks[2];\n"
+ " X.v[1] += 1;\n"
+ " }\n"
+ " if(Nrounds>4){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_4_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>5){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_5_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>6){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_6_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>7){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_7_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>7){\n"
+ " X.v[0] += ks[2]; X.v[1] += ks[0];\n"
+ " X.v[1] += 2;\n"
+ " }\n"
+ " if(Nrounds>8){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_0_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>9){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_1_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>10){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_2_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>11){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_3_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>11){\n"
+ " X.v[0] += ks[0]; X.v[1] += ks[1];\n"
+ " X.v[1] += 3;\n"
+ " }\n"
+ " if(Nrounds>12){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_4_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>13){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_5_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>14){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_6_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>15){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_7_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>15){\n"
+ " X.v[0] += ks[1]; X.v[1] += ks[2];\n"
+ " X.v[1] += 4;\n"
+ " }\n"
+ " if(Nrounds>16){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_0_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>17){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_1_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>18){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_2_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>19){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_3_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>19){\n"
+ " X.v[0] += ks[2]; X.v[1] += ks[0];\n"
+ " X.v[1] += 5;\n"
+ " }\n"
+ " if(Nrounds>20){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_4_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>21){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_5_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>22){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_6_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>23){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_7_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>23){\n"
+ " X.v[0] += ks[0]; X.v[1] += ks[1];\n"
+ " X.v[1] += 6;\n"
+ " }\n"
+ " if(Nrounds>24){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_0_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>25){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_1_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>26){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_2_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>27){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_3_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>27){\n"
+ " X.v[0] += ks[1]; X.v[1] += ks[2];\n"
+ " X.v[1] += 7;\n"
+ " }\n"
+ " if(Nrounds>28){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_4_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>29){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_5_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>30){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_6_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>31){ X.v[0] += X.v[1]; X.v[1] = RotL_32(X.v[1],R_32x2_7_0); X.v[1] ^= X.v[0]; }\n"
+ " if(Nrounds>31){\n"
+ " X.v[0] += ks[2]; X.v[1] += ks[0];\n"
+ " X.v[1] += 8;\n"
+ " }\n"
+ " return X;\n"
+ "}\n"
+
+ "__kernel void generate_rng(__global uint *ctr, __global uint *key, const uint offset) {\n"
+ " threefry2x32_ctr_t in;\n"
+ " threefry2x32_key_t k;\n"
+ " const uint i = get_global_id(0);\n"
+ " in.v[0] = ctr[2 * (offset + i)];\n"
+ " in.v[1] = ctr[2 * (offset + i) + 1];\n"
+ " k.v[0] = key[2 * (offset + i)];\n"
+ " k.v[1] = key[2 * (offset + i) + 1];\n"
+ " in = threefry2x32_R(20, in, k);\n"
+ " ctr[2 * (offset + i)] = in.v[0];\n"
+ " ctr[2 * (offset + i) + 1] = in.v[1];\n"
+ "}\n";
+
+ m_program = cache->get_or_build(cache_key, std::string(), source, m_context);
+ }
+
+public:
+
+
+ /// Generates Threefry random numbers using both the counter and key values, and then stores
+ /// them to the range [\p first_ctr, \p last_ctr).
+ template<class OutputIterator>
+ void generate(OutputIterator first_ctr, OutputIterator last_ctr, OutputIterator first_key, OutputIterator last_key, command_queue &queue) {
+ const size_t size_ctr = detail::iterator_range_size(first_ctr, last_ctr);
+ const size_t size_key = detail::iterator_range_size(first_key, last_key);
+ if(!size_ctr || !size_key || (size_ctr != size_key)) {
+ return;
+ }
+ kernel rng_kernel = m_program.create_kernel("generate_rng");
+
+ rng_kernel.set_arg(0, first_ctr.get_buffer());
+ rng_kernel.set_arg(1, first_key.get_buffer());
+ size_t offset = 0;
+
+ for(;;){
+ size_t count = 0;
+ size_t size = size_ctr/2;
+ if(size > threads){
+ count = (std::min)(static_cast<size_t>(threads), size - offset);
+ }
+ else {
+ count = size;
+ }
+ rng_kernel.set_arg(2, static_cast<const uint_>(offset));
+ queue.enqueue_1d_range_kernel(rng_kernel, 0, count, 0);
+
+ offset += count;
+
+ if(offset >= size){
+ break;
+ }
+
+ }
+ }
+
+ template<class OutputIterator>
+ void generate(OutputIterator first_ctr, OutputIterator last_ctr, command_queue &queue) {
+ const size_t size_ctr = detail::iterator_range_size(first_ctr, last_ctr);
+ if(!size_ctr) {
+ return;
+ }
+ boost::compute::vector<uint_> vector_key(size_ctr, m_context);
+ vector_key.assign(size_ctr, 0, queue);
+ kernel rng_kernel = m_program.create_kernel("generate_rng");
+
+ rng_kernel.set_arg(0, first_ctr.get_buffer());
+ rng_kernel.set_arg(1, vector_key);
+ size_t offset = 0;
+
+ for(;;){
+ size_t count = 0;
+ size_t size = size_ctr/2;
+ if(size > threads){
+ count = (std::min)(static_cast<size_t>(threads), size - offset);
+ }
+ else {
+ count = size;
+ }
+ rng_kernel.set_arg(2, static_cast<const uint_>(offset));
+ queue.enqueue_1d_range_kernel(rng_kernel, 0, count, 0);
+
+ offset += count;
+
+ if(offset >= size){
+ break;
+ }
+
+ }
+ }
+private:
+ context m_context;
+ program m_program;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_RANDOM_THREEFRY_HPP
diff --git a/boost/compute/random/uniform_int_distribution.hpp b/boost/compute/random/uniform_int_distribution.hpp
new file mode 100644
index 0000000000..92e8b3305f
--- /dev/null
+++ b/boost/compute/random/uniform_int_distribution.hpp
@@ -0,0 +1,111 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_RANDOM_UNIFORM_INT_DISTRIBUTION_HPP
+#define BOOST_COMPUTE_RANDOM_UNIFORM_INT_DISTRIBUTION_HPP
+
+#include <limits>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/function.hpp>
+#include <boost/compute/types/fundamental.hpp>
+#include <boost/compute/algorithm/copy_if.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class uniform_int_distribution
+/// \brief Produces uniformily distributed random integers
+///
+/// The following example shows how to setup a uniform int distribution to
+/// produce random integers 0 and 1.
+///
+/// \snippet test/test_uniform_int_distribution.cpp generate
+///
+template<class IntType = uint_>
+class uniform_int_distribution
+{
+public:
+ typedef IntType result_type;
+
+ /// Creates a new uniform distribution producing numbers in the range
+ /// [\p a, \p b].
+ explicit uniform_int_distribution(IntType a = 0,
+ IntType b = (std::numeric_limits<IntType>::max)())
+ : m_a(a),
+ m_b(b)
+ {
+ }
+
+ /// Destroys the uniform_int_distribution object.
+ ~uniform_int_distribution()
+ {
+ }
+
+ /// Returns the minimum value of the distribution.
+ result_type a() const
+ {
+ return m_a;
+ }
+
+ /// Returns the maximum value of the distribution.
+ result_type b() const
+ {
+ return m_b;
+ }
+
+ /// Generates uniformily distributed integers and stores
+ /// them to the range [\p first, \p last).
+ template<class OutputIterator, class Generator>
+ void generate(OutputIterator first,
+ OutputIterator last,
+ Generator &generator,
+ command_queue &queue)
+ {
+ size_t size = std::distance(first, last);
+ typedef typename Generator::result_type g_result_type;
+
+ vector<g_result_type> tmp(size, queue.get_context());
+ vector<g_result_type> tmp2(size, queue.get_context());
+
+ uint_ bound = ((uint_(-1))/(m_b-m_a+1))*(m_b-m_a+1);
+
+ buffer_iterator<g_result_type> tmp2_iter;
+
+ while(size>0)
+ {
+ generator.generate(tmp.begin(), tmp.begin() + size, queue);
+ tmp2_iter = copy_if(tmp.begin(), tmp.begin() + size, tmp2.begin(),
+ _1 <= bound, queue);
+ size = std::distance(tmp2_iter, tmp2.end());
+ }
+
+ BOOST_COMPUTE_FUNCTION(IntType, scale_random, (const g_result_type x),
+ {
+ return LO + (x % (HI-LO+1));
+ });
+
+ scale_random.define("LO", boost::lexical_cast<std::string>(m_a));
+ scale_random.define("HI", boost::lexical_cast<std::string>(m_b));
+
+ transform(tmp2.begin(), tmp2.end(), first, scale_random, queue);
+ }
+
+private:
+ IntType m_a;
+ IntType m_b;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_RANDOM_UNIFORM_INT_DISTRIBUTION_HPP
diff --git a/boost/compute/random/uniform_real_distribution.hpp b/boost/compute/random/uniform_real_distribution.hpp
new file mode 100644
index 0000000000..231b0dba01
--- /dev/null
+++ b/boost/compute/random/uniform_real_distribution.hpp
@@ -0,0 +1,105 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_RANDOM_UNIFORM_REAL_DISTRIBUTION_HPP
+#define BOOST_COMPUTE_RANDOM_UNIFORM_REAL_DISTRIBUTION_HPP
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/function.hpp>
+#include <boost/compute/detail/literal.hpp>
+#include <boost/compute/types/fundamental.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class uniform_real_distribution
+/// \brief Produces uniformily distributed random floating-point numbers.
+///
+/// The following example shows how to setup a uniform real distribution to
+/// produce random \c float values between \c 1 and \c 100.
+///
+/// \snippet test/test_uniform_real_distribution.cpp generate
+///
+/// \see default_random_engine, normal_distribution
+template<class RealType = float>
+class uniform_real_distribution
+{
+public:
+ typedef RealType result_type;
+
+ /// Creates a new uniform distribution producing numbers in the range
+ /// [\p a, \p b).
+ uniform_real_distribution(RealType a = 0.f, RealType b = 1.f)
+ : m_a(a),
+ m_b(b)
+ {
+ }
+
+ /// Destroys the uniform_real_distribution object.
+ ~uniform_real_distribution()
+ {
+ }
+
+ /// Returns the minimum value of the distribution.
+ result_type a() const
+ {
+ return m_a;
+ }
+
+ /// Returns the maximum value of the distribution.
+ result_type b() const
+ {
+ return m_b;
+ }
+
+ /// Generates uniformily distributed floating-point numbers and stores
+ /// them to the range [\p first, \p last).
+ template<class OutputIterator, class Generator>
+ void generate(OutputIterator first,
+ OutputIterator last,
+ Generator &generator,
+ command_queue &queue)
+ {
+ BOOST_COMPUTE_FUNCTION(RealType, scale_random, (const uint_ x),
+ {
+ return LO + (convert_RealType(x) / MAX_RANDOM) * (HI - LO);
+ });
+
+ scale_random.define("LO", detail::make_literal(m_a));
+ scale_random.define("HI", detail::make_literal(m_b));
+ scale_random.define("MAX_RANDOM", "UINT_MAX");
+ scale_random.define(
+ "convert_RealType", std::string("convert_") + type_name<RealType>()
+ );
+
+ generator.generate(
+ first, last, scale_random, queue
+ );
+ }
+
+ /// \internal_ (deprecated)
+ template<class OutputIterator, class Generator>
+ void fill(OutputIterator first,
+ OutputIterator last,
+ Generator &g,
+ command_queue &queue)
+ {
+ generate(first, last, g, queue);
+ }
+
+private:
+ RealType m_a;
+ RealType m_b;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_RANDOM_UNIFORM_REAL_DISTRIBUTION_HPP
diff --git a/boost/compute/source.hpp b/boost/compute/source.hpp
new file mode 100644
index 0000000000..844dfa49ea
--- /dev/null
+++ b/boost/compute/source.hpp
@@ -0,0 +1,12 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+// deprecated, use <boost/compute/utility/source.hpp> instead
+#include <boost/compute/utility/source.hpp>
diff --git a/boost/compute/svm.hpp b/boost/compute/svm.hpp
new file mode 100644
index 0000000000..d03c8d9079
--- /dev/null
+++ b/boost/compute/svm.hpp
@@ -0,0 +1,62 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_SVM_HPP
+#define BOOST_COMPUTE_SVM_HPP
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/memory/svm_ptr.hpp>
+
+// svm functions require opencl 2.0
+#if defined(CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+
+namespace boost {
+namespace compute {
+
+/// Allocates a shared virtual memory (SVM) buffer.
+//
+/// \opencl_version_warning{2,0}
+///
+/// \see_opencl2_ref{clSVMAlloc}
+///
+/// \see svm_free()
+template<class T>
+inline svm_ptr<T> svm_alloc(const context &context,
+ size_t size,
+ cl_svm_mem_flags flags = CL_MEM_READ_WRITE,
+ unsigned int alignment = 0)
+{
+ svm_ptr<T> ptr(clSVMAlloc(context.get(), flags, size * sizeof(T), alignment));
+ if(!ptr.get()){
+ BOOST_THROW_EXCEPTION(opencl_error(CL_MEM_OBJECT_ALLOCATION_FAILURE));
+ }
+ return ptr;
+}
+
+/// Deallocates a shared virtual memory (SVM) buffer.
+///
+/// \opencl_version_warning{2,0}
+///
+/// \see_opencl2_ref{clSVMFree}
+///
+/// \see svm_alloc(), command_queue::enqueue_svm_free()
+template<class T>
+inline void svm_free(const context &context, svm_ptr<T> ptr)
+{
+ clSVMFree(context.get(), ptr.get());
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // CL_VERSION_2_0
+
+#endif // BOOST_COMPUTE_PIPE_HPP
diff --git a/boost/compute/system.hpp b/boost/compute/system.hpp
new file mode 100644
index 0000000000..f205fece7d
--- /dev/null
+++ b/boost/compute/system.hpp
@@ -0,0 +1,278 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_SYSTEM_HPP
+#define BOOST_COMPUTE_SYSTEM_HPP
+
+#include <string>
+#include <vector>
+#include <cstdlib>
+
+#include <boost/throw_exception.hpp>
+
+#include <boost/compute/cl.hpp>
+#include <boost/compute/device.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/platform.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/detail/getenv.hpp>
+#include <boost/compute/exception/no_device_found.hpp>
+
+namespace boost {
+namespace compute {
+
+/// \class system
+/// \brief Provides access to platforms and devices on the system.
+///
+/// The system class contains a set of static functions which provide access to
+/// the OpenCL platforms and compute devices on the host system.
+///
+/// The default_device() convenience method automatically selects and returns
+/// the "best" compute device for the system following a set of heuristics and
+/// environment variables. This simplifies setup of the OpenCL enviornment.
+///
+/// \see platform, device, context
+class system
+{
+public:
+ /// Returns the default compute device for the system.
+ ///
+ /// The default device is selected based on a set of heuristics and can be
+ /// influenced using one of the following environment variables:
+ ///
+ /// \li \c BOOST_COMPUTE_DEFAULT_DEVICE -
+ /// name of the compute device (e.g. "GTX TITAN")
+ /// \li \c BOOST_COMPUTE_DEFAULT_DEVICE_TYPE
+ /// type of the compute device (e.g. "GPU" or "CPU")
+ /// \li \c BOOST_COMPUTE_DEFAULT_PLATFORM -
+ /// name of the platform (e.g. "NVIDIA CUDA")
+ /// \li \c BOOST_COMPUTE_DEFAULT_VENDOR -
+ /// name of the device vendor (e.g. "NVIDIA")
+ ///
+ /// The default device is determined once on the first time this function
+ /// is called. Calling this function multiple times will always result in
+ /// the same device being returned.
+ ///
+ /// If no OpenCL device is found on the system, a no_device_found exception
+ /// is thrown.
+ ///
+ /// For example, to print the name of the default compute device on the
+ /// system:
+ /// \code
+ /// // get the default compute device
+ /// boost::compute::device device = boost::compute::system::default_device();
+ ///
+ /// // print the name of the device
+ /// std::cout << "default device: " << device.name() << std::endl;
+ /// \endcode
+ static device default_device()
+ {
+ static device default_device = find_default_device();
+
+ return default_device;
+ }
+
+ /// Returns the device with \p name.
+ ///
+ /// \throws no_device_found if no device with \p name is found.
+ static device find_device(const std::string &name)
+ {
+ const std::vector<device> devices = system::devices();
+ for(size_t i = 0; i < devices.size(); i++){
+ const device& device = devices[i];
+
+ if(device.name() == name){
+ return device;
+ }
+ }
+
+ BOOST_THROW_EXCEPTION(no_device_found());
+ }
+
+ /// Returns a vector containing all of the compute devices on
+ /// the system.
+ ///
+ /// For example, to print out the name of each OpenCL-capable device
+ /// available on the system:
+ /// \code
+ /// for(const auto &device : boost::compute::system::devices()){
+ /// std::cout << device.name() << std::endl;
+ /// }
+ /// \endcode
+ static std::vector<device> devices()
+ {
+ std::vector<device> devices;
+
+ const std::vector<platform> platforms = system::platforms();
+ for(size_t i = 0; i < platforms.size(); i++){
+ const std::vector<device> platform_devices = platforms[i].devices();
+
+ devices.insert(
+ devices.end(), platform_devices.begin(), platform_devices.end()
+ );
+ }
+
+ return devices;
+ }
+
+ /// Returns the number of compute devices on the system.
+ static size_t device_count()
+ {
+ size_t count = 0;
+
+ const std::vector<platform> platforms = system::platforms();
+ for(size_t i = 0; i < platforms.size(); i++){
+ count += platforms[i].device_count();
+ }
+
+ return count;
+ }
+
+ /// Returns the default context for the system.
+ ///
+ /// The default context is created for the default device on the system
+ /// (as returned by default_device()).
+ ///
+ /// The default context is created once on the first time this function is
+ /// called. Calling this function multiple times will always result in the
+ /// same context object being returned.
+ static context default_context()
+ {
+ static context default_context(default_device());
+
+ return default_context;
+ }
+
+ /// Returns the default command queue for the system.
+ static command_queue& default_queue()
+ {
+ static command_queue queue(default_context(), default_device());
+
+ return queue;
+ }
+
+ /// Blocks until all outstanding computations on the default
+ /// command queue are complete.
+ ///
+ /// This is equivalent to:
+ /// \code
+ /// system::default_queue().finish();
+ /// \endcode
+ static void finish()
+ {
+ default_queue().finish();
+ }
+
+ /// Returns a vector containing each of the OpenCL platforms on the system.
+ ///
+ /// For example, to print out the name of each OpenCL platform present on
+ /// the system:
+ /// \code
+ /// for(const auto &platform : boost::compute::system::platforms()){
+ /// std::cout << platform.name() << std::endl;
+ /// }
+ /// \endcode
+ static std::vector<platform> platforms()
+ {
+ cl_uint count = 0;
+ clGetPlatformIDs(0, 0, &count);
+
+ std::vector<cl_platform_id> platform_ids(count);
+ clGetPlatformIDs(count, &platform_ids[0], 0);
+
+ std::vector<platform> platforms;
+ for(size_t i = 0; i < platform_ids.size(); i++){
+ platforms.push_back(platform(platform_ids[i]));
+ }
+
+ return platforms;
+ }
+
+ /// Returns the number of compute platforms on the system.
+ static size_t platform_count()
+ {
+ cl_uint count = 0;
+ clGetPlatformIDs(0, 0, &count);
+ return static_cast<size_t>(count);
+ }
+
+private:
+ /// \internal_
+ static device find_default_device()
+ {
+ // get a list of all devices on the system
+ const std::vector<device> devices_ = devices();
+ if(devices_.empty()){
+ BOOST_THROW_EXCEPTION(no_device_found());
+ }
+
+ // check for device from environment variable
+ const char *name = detail::getenv("BOOST_COMPUTE_DEFAULT_DEVICE");
+ const char *type = detail::getenv("BOOST_COMPUTE_DEFAULT_DEVICE_TYPE");
+ const char *platform = detail::getenv("BOOST_COMPUTE_DEFAULT_PLATFORM");
+ const char *vendor = detail::getenv("BOOST_COMPUTE_DEFAULT_VENDOR");
+
+ if(name || type || platform || vendor){
+ for(size_t i = 0; i < devices_.size(); i++){
+ const device& device = devices_[i];
+ if (name && !matches(device.name(), name))
+ continue;
+
+ if (type && matches(std::string("GPU"), type))
+ if (!(device.type() & device::gpu))
+ continue;
+
+ if (type && matches(std::string("CPU"), type))
+ if (!(device.type() & device::cpu))
+ continue;
+
+ if (platform && !matches(device.platform().name(), platform))
+ continue;
+
+ if (vendor && !matches(device.vendor(), vendor))
+ continue;
+
+ return device;
+ }
+ }
+
+ // find the first gpu device
+ for(size_t i = 0; i < devices_.size(); i++){
+ const device& device = devices_[i];
+
+ if(device.type() & device::gpu){
+ return device;
+ }
+ }
+
+ // find the first cpu device
+ for(size_t i = 0; i < devices_.size(); i++){
+ const device& device = devices_[i];
+
+ if(device.type() & device::cpu){
+ return device;
+ }
+ }
+
+ // return the first device found
+ return devices_[0];
+ }
+
+ /// \internal_
+ static bool matches(const std::string &str, const std::string &pattern)
+ {
+ return str.find(pattern) != std::string::npos;
+ }
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_SYSTEM_HPP
diff --git a/boost/compute/type_traits.hpp b/boost/compute/type_traits.hpp
new file mode 100644
index 0000000000..9ba98d9c2c
--- /dev/null
+++ b/boost/compute/type_traits.hpp
@@ -0,0 +1,25 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TYPE_TRAITS_HPP
+#define BOOST_COMPUTE_TYPE_TRAITS_HPP
+
+#include <boost/compute/type_traits/common_type.hpp>
+#include <boost/compute/type_traits/is_device_iterator.hpp>
+#include <boost/compute/type_traits/is_fundamental.hpp>
+#include <boost/compute/type_traits/is_vector_type.hpp>
+#include <boost/compute/type_traits/make_vector_type.hpp>
+#include <boost/compute/type_traits/result_of.hpp>
+#include <boost/compute/type_traits/scalar_type.hpp>
+#include <boost/compute/type_traits/type_definition.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/type_traits/vector_size.hpp>
+
+#endif // BOOST_COMPUTE_TYPE_TRAITS_HPP
diff --git a/boost/compute/type_traits/common_type.hpp b/boost/compute/type_traits/common_type.hpp
new file mode 100644
index 0000000000..49a81ff3fd
--- /dev/null
+++ b/boost/compute/type_traits/common_type.hpp
@@ -0,0 +1,55 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TYPE_TRAITS_COMMON_TYPE_HPP
+#define BOOST_COMPUTE_TYPE_TRAITS_COMMON_TYPE_HPP
+
+#include <boost/type_traits/common_type.hpp>
+
+#include <boost/compute/types/fundamental.hpp>
+
+namespace boost {
+
+/// \internal_
+#define BOOST_COMPUTE_DECLARE_SCALAR_VECTOR_COMMON_TYPE(scalar, size) \
+ template<> \
+ struct common_type<BOOST_COMPUTE_MAKE_VECTOR_TYPE(scalar, size), \
+ BOOST_COMPUTE_MAKE_SCALAR_TYPE(scalar)> \
+ { \
+ typedef BOOST_COMPUTE_MAKE_VECTOR_TYPE(scalar, size) type; \
+ }; \
+ template<> \
+ struct common_type<BOOST_COMPUTE_MAKE_SCALAR_TYPE(scalar), \
+ BOOST_COMPUTE_MAKE_VECTOR_TYPE(scalar, size)> \
+ { \
+ typedef BOOST_COMPUTE_MAKE_VECTOR_TYPE(scalar, size) type; \
+ };
+
+/// \internal_
+#define BOOST_COMPUTE_DECLARE_SCALAR_VECTOR_COMMON_TYPES(scalar) \
+ BOOST_COMPUTE_DECLARE_SCALAR_VECTOR_COMMON_TYPE(scalar, 2) \
+ BOOST_COMPUTE_DECLARE_SCALAR_VECTOR_COMMON_TYPE(scalar, 4) \
+ BOOST_COMPUTE_DECLARE_SCALAR_VECTOR_COMMON_TYPE(scalar, 8) \
+ BOOST_COMPUTE_DECLARE_SCALAR_VECTOR_COMMON_TYPE(scalar, 16) \
+
+BOOST_COMPUTE_DECLARE_SCALAR_VECTOR_COMMON_TYPES(char)
+BOOST_COMPUTE_DECLARE_SCALAR_VECTOR_COMMON_TYPES(uchar)
+BOOST_COMPUTE_DECLARE_SCALAR_VECTOR_COMMON_TYPES(short)
+BOOST_COMPUTE_DECLARE_SCALAR_VECTOR_COMMON_TYPES(ushort)
+BOOST_COMPUTE_DECLARE_SCALAR_VECTOR_COMMON_TYPES(int)
+BOOST_COMPUTE_DECLARE_SCALAR_VECTOR_COMMON_TYPES(uint)
+BOOST_COMPUTE_DECLARE_SCALAR_VECTOR_COMMON_TYPES(long)
+BOOST_COMPUTE_DECLARE_SCALAR_VECTOR_COMMON_TYPES(ulong)
+BOOST_COMPUTE_DECLARE_SCALAR_VECTOR_COMMON_TYPES(float)
+BOOST_COMPUTE_DECLARE_SCALAR_VECTOR_COMMON_TYPES(double)
+
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_TYPE_TRAITS_COMMON_TYPE_HPP
diff --git a/boost/compute/type_traits/detail/capture_traits.hpp b/boost/compute/type_traits/detail/capture_traits.hpp
new file mode 100644
index 0000000000..e790f80696
--- /dev/null
+++ b/boost/compute/type_traits/detail/capture_traits.hpp
@@ -0,0 +1,33 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TYPE_TRAITS_DETAIL_CAPTURE_TRAITS_HPP
+#define BOOST_COMPUTE_TYPE_TRAITS_DETAIL_CAPTURE_TRAITS_HPP
+
+#include <boost/compute/type_traits/type_name.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class T>
+struct capture_traits
+{
+ static std::string type_name()
+ {
+ return ::boost::compute::type_name<T>();
+ }
+};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_TYPE_TRAITS_DETAIL_CAPTURE_TRAITS_HPP
diff --git a/boost/compute/type_traits/is_device_iterator.hpp b/boost/compute/type_traits/is_device_iterator.hpp
new file mode 100644
index 0000000000..5e7021f2e8
--- /dev/null
+++ b/boost/compute/type_traits/is_device_iterator.hpp
@@ -0,0 +1,39 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TYPE_TRAITS_IS_DEVICE_ITERATOR_HPP
+#define BOOST_COMPUTE_TYPE_TRAITS_IS_DEVICE_ITERATOR_HPP
+
+#include <boost/type_traits/integral_constant.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Meta-function returning \c true if \c Iterator is a device-iterator.
+///
+/// By default, this function returns false. Device iterator types (such as
+/// buffer_iterator) should specialize this trait and return \c true.
+///
+/// For example:
+/// \code
+/// is_device_iterator<buffer_iterator<int>>::value == true
+/// is_device_iterator<std::vector<int>::iterator>::value == false
+/// \endcode
+template<class Iterator>
+struct is_device_iterator : boost::false_type {};
+
+/// \internal_
+template<class Iterator>
+struct is_device_iterator<const Iterator> : is_device_iterator<Iterator> {};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_TYPE_TRAITS_IS_DEVICE_ITERATOR_HPP
diff --git a/boost/compute/type_traits/is_fundamental.hpp b/boost/compute/type_traits/is_fundamental.hpp
new file mode 100644
index 0000000000..6386f1184d
--- /dev/null
+++ b/boost/compute/type_traits/is_fundamental.hpp
@@ -0,0 +1,58 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TYPE_TRAITS_IS_FUNDAMENTAL_HPP
+#define BOOST_COMPUTE_TYPE_TRAITS_IS_FUNDAMENTAL_HPP
+
+#include <boost/compute/types/fundamental.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Meta-function returning \c true if \p T is a fundamental (i.e.
+/// built-in) type.
+///
+/// For example,
+/// \code
+/// is_fundamental<float>::value == true
+/// is_fundamental<std::pair<int, float>>::value == false
+/// \endcode
+template<class T>
+struct is_fundamental : public boost::false_type {};
+
+/// \internal_
+#define BOOST_COMPUTE_DETAIL_DECLARE_FUNDAMENTAL(type) \
+ template<> struct is_fundamental<BOOST_PP_CAT(type, _)> : boost::true_type {}; \
+ template<> struct is_fundamental<BOOST_PP_CAT(BOOST_PP_CAT(type, 2), _)> : boost::true_type {}; \
+ template<> struct is_fundamental<BOOST_PP_CAT(BOOST_PP_CAT(type, 4), _)> : boost::true_type {}; \
+ template<> struct is_fundamental<BOOST_PP_CAT(BOOST_PP_CAT(type, 8), _)> : boost::true_type {}; \
+ template<> struct is_fundamental<BOOST_PP_CAT(BOOST_PP_CAT(type, 16), _)> : boost::true_type {}; \
+ template<> struct is_fundamental<BOOST_PP_CAT(cl_, BOOST_PP_CAT(type, 2))> : boost::true_type {}; \
+ template<> struct is_fundamental<BOOST_PP_CAT(cl_, BOOST_PP_CAT(type, 4))> : boost::true_type {}; \
+ template<> struct is_fundamental<BOOST_PP_CAT(cl_, BOOST_PP_CAT(type, 8))> : boost::true_type {}; \
+ template<> struct is_fundamental<BOOST_PP_CAT(cl_, BOOST_PP_CAT(type, 16))> : boost::true_type {};
+
+BOOST_COMPUTE_DETAIL_DECLARE_FUNDAMENTAL(char)
+BOOST_COMPUTE_DETAIL_DECLARE_FUNDAMENTAL(uchar)
+BOOST_COMPUTE_DETAIL_DECLARE_FUNDAMENTAL(short)
+BOOST_COMPUTE_DETAIL_DECLARE_FUNDAMENTAL(ushort)
+BOOST_COMPUTE_DETAIL_DECLARE_FUNDAMENTAL(int)
+BOOST_COMPUTE_DETAIL_DECLARE_FUNDAMENTAL(uint)
+BOOST_COMPUTE_DETAIL_DECLARE_FUNDAMENTAL(long)
+BOOST_COMPUTE_DETAIL_DECLARE_FUNDAMENTAL(ulong)
+BOOST_COMPUTE_DETAIL_DECLARE_FUNDAMENTAL(float)
+BOOST_COMPUTE_DETAIL_DECLARE_FUNDAMENTAL(double)
+
+#undef BOOST_COMPUTE_DETAIL_DECLARE_FUNDAMENTAL
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_TYPE_TRAITS_IS_FUNDAMENTAL_HPP
diff --git a/boost/compute/type_traits/is_vector_type.hpp b/boost/compute/type_traits/is_vector_type.hpp
new file mode 100644
index 0000000000..f4382f0e2b
--- /dev/null
+++ b/boost/compute/type_traits/is_vector_type.hpp
@@ -0,0 +1,38 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TYPE_TRAITS_IS_VECTOR_TYPE_HPP
+#define BOOST_COMPUTE_TYPE_TRAITS_IS_VECTOR_TYPE_HPP
+
+#include <boost/mpl/bool.hpp>
+
+#include <boost/compute/type_traits/vector_size.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Meta-function returning \c true if \p T is a vector type.
+///
+/// For example,
+/// \code
+/// is_vector_type<int>::value == false
+/// is_vector_type<float4_>::value == true
+/// \endcode
+///
+/// \see make_vector_type, vector_size
+template<class T>
+struct is_vector_type : boost::mpl::bool_<vector_size<T>::value != 1>
+{
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_TYPE_TRAITS_IS_VECTOR_TYPE_HPP
diff --git a/boost/compute/type_traits/make_vector_type.hpp b/boost/compute/type_traits/make_vector_type.hpp
new file mode 100644
index 0000000000..6494ff267f
--- /dev/null
+++ b/boost/compute/type_traits/make_vector_type.hpp
@@ -0,0 +1,71 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TYPE_TRAITS_MAKE_VECTOR_TYPE_HPP
+#define BOOST_COMPUTE_TYPE_TRAITS_MAKE_VECTOR_TYPE_HPP
+
+#include <boost/preprocessor/cat.hpp>
+
+#include <boost/compute/types/fundamental.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Meta-function which returns a vector type for \p Scalar with \p Size.
+///
+/// For example,
+/// \code
+/// make_vector_type<int, 2>::type == int2_
+/// make_vector_type<float, 4>::type == float4_
+/// \endcode
+///
+/// \see is_vector_type
+template<class Scalar, size_t Size>
+struct make_vector_type
+{
+};
+
+/// \internal_
+template<class Scalar>
+struct make_vector_type<Scalar, 1>
+{
+ typedef Scalar type;
+};
+
+/// \internal_
+#define BOOST_COMPUTE_DECLARE_MAKE_VECTOR_TYPE_FUNCTION(scalar, size) \
+ template<> \
+ struct make_vector_type<BOOST_PP_CAT(scalar, _), size> \
+ { \
+ typedef BOOST_PP_CAT(BOOST_PP_CAT(scalar, size), _) type; \
+ };
+
+/// \internal_
+#define BOOST_COMPUTE_DECLARE_MAKE_VECTOR_TYPE_FUNCTIONS(scalar) \
+ BOOST_COMPUTE_DECLARE_MAKE_VECTOR_TYPE_FUNCTION(scalar, 2) \
+ BOOST_COMPUTE_DECLARE_MAKE_VECTOR_TYPE_FUNCTION(scalar, 4) \
+ BOOST_COMPUTE_DECLARE_MAKE_VECTOR_TYPE_FUNCTION(scalar, 8) \
+ BOOST_COMPUTE_DECLARE_MAKE_VECTOR_TYPE_FUNCTION(scalar, 16)
+
+BOOST_COMPUTE_DECLARE_MAKE_VECTOR_TYPE_FUNCTIONS(char)
+BOOST_COMPUTE_DECLARE_MAKE_VECTOR_TYPE_FUNCTIONS(uchar)
+BOOST_COMPUTE_DECLARE_MAKE_VECTOR_TYPE_FUNCTIONS(short)
+BOOST_COMPUTE_DECLARE_MAKE_VECTOR_TYPE_FUNCTIONS(ushort)
+BOOST_COMPUTE_DECLARE_MAKE_VECTOR_TYPE_FUNCTIONS(int)
+BOOST_COMPUTE_DECLARE_MAKE_VECTOR_TYPE_FUNCTIONS(uint)
+BOOST_COMPUTE_DECLARE_MAKE_VECTOR_TYPE_FUNCTIONS(long)
+BOOST_COMPUTE_DECLARE_MAKE_VECTOR_TYPE_FUNCTIONS(ulong)
+BOOST_COMPUTE_DECLARE_MAKE_VECTOR_TYPE_FUNCTIONS(float)
+BOOST_COMPUTE_DECLARE_MAKE_VECTOR_TYPE_FUNCTIONS(double)
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_TYPE_TRAITS_MAKE_VECTOR_TYPE_HPP
diff --git a/boost/compute/type_traits/result_of.hpp b/boost/compute/type_traits/result_of.hpp
new file mode 100644
index 0000000000..3f475a35da
--- /dev/null
+++ b/boost/compute/type_traits/result_of.hpp
@@ -0,0 +1,39 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TYPE_TRAITS_RESULT_OF_HPP
+#define BOOST_COMPUTE_TYPE_TRAITS_RESULT_OF_HPP
+
+#include <boost/utility/result_of.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Returns the result of \c Function when called with \c Args.
+///
+/// For example,
+/// \code
+/// // int + int = int
+/// result_of<plus(int, int)>::type == int
+/// \endcode
+template<class Signature>
+struct result_of
+{
+ // the default implementation uses the TR1-style result_of protocol. note
+ // that we explicitly do *not* use the C++11 decltype operator as we want
+ // the result type as it would be on an OpenCL device, not the actual C++
+ // type resulting from "invoking" the function on the host.
+ typedef typename ::boost::tr1_result_of<Signature>::type type;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_TYPE_TRAITS_RESULT_OF_HPP
diff --git a/boost/compute/type_traits/scalar_type.hpp b/boost/compute/type_traits/scalar_type.hpp
new file mode 100644
index 0000000000..c40682fd27
--- /dev/null
+++ b/boost/compute/type_traits/scalar_type.hpp
@@ -0,0 +1,72 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TYPE_TRAITS_SCALAR_TYPE_HPP
+#define BOOST_COMPUTE_TYPE_TRAITS_SCALAR_TYPE_HPP
+
+#include <boost/preprocessor/cat.hpp>
+
+#include <boost/compute/types/fundamental.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Meta-function returning the scalar type for a vector type.
+///
+/// For example,
+/// \code
+/// scalar_type<float4_>::type == float
+/// \endcode
+template<class Vector>
+struct scalar_type
+{
+ /// \internal_
+ typedef void type;
+};
+
+/// \internal_
+#define BOOST_COMPUTE_DECLARE_SCALAR_TYPE_FUNCTION(scalar) \
+ template<> \
+ struct scalar_type<BOOST_PP_CAT(scalar, _)> \
+ { \
+ typedef BOOST_PP_CAT(scalar, _) type; \
+ };
+
+/// \internal_
+#define BOOST_COMPUTE_DECLARE_VECTOR_SCALAR_TYPE_FUNCTION(scalar, size) \
+ template<> \
+ struct scalar_type<BOOST_PP_CAT(BOOST_PP_CAT(scalar, size), _)> \
+ { \
+ typedef BOOST_PP_CAT(scalar, _) type; \
+ };
+
+/// \internal_
+#define BOOST_COMPUTE_DECLARE_SCALAR_TYPE_FUNCTIONS(scalar) \
+ BOOST_COMPUTE_DECLARE_SCALAR_TYPE_FUNCTION(scalar) \
+ BOOST_COMPUTE_DECLARE_VECTOR_SCALAR_TYPE_FUNCTION(scalar, 2) \
+ BOOST_COMPUTE_DECLARE_VECTOR_SCALAR_TYPE_FUNCTION(scalar, 4) \
+ BOOST_COMPUTE_DECLARE_VECTOR_SCALAR_TYPE_FUNCTION(scalar, 8) \
+ BOOST_COMPUTE_DECLARE_VECTOR_SCALAR_TYPE_FUNCTION(scalar, 16)
+
+BOOST_COMPUTE_DECLARE_SCALAR_TYPE_FUNCTIONS(char)
+BOOST_COMPUTE_DECLARE_SCALAR_TYPE_FUNCTIONS(uchar)
+BOOST_COMPUTE_DECLARE_SCALAR_TYPE_FUNCTIONS(short)
+BOOST_COMPUTE_DECLARE_SCALAR_TYPE_FUNCTIONS(ushort)
+BOOST_COMPUTE_DECLARE_SCALAR_TYPE_FUNCTIONS(int)
+BOOST_COMPUTE_DECLARE_SCALAR_TYPE_FUNCTIONS(uint)
+BOOST_COMPUTE_DECLARE_SCALAR_TYPE_FUNCTIONS(long)
+BOOST_COMPUTE_DECLARE_SCALAR_TYPE_FUNCTIONS(ulong)
+BOOST_COMPUTE_DECLARE_SCALAR_TYPE_FUNCTIONS(float)
+BOOST_COMPUTE_DECLARE_SCALAR_TYPE_FUNCTIONS(double)
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_TYPE_TRAITS_SCALAR_TYPE_HPP
diff --git a/boost/compute/type_traits/type_definition.hpp b/boost/compute/type_traits/type_definition.hpp
new file mode 100644
index 0000000000..de9095fbd2
--- /dev/null
+++ b/boost/compute/type_traits/type_definition.hpp
@@ -0,0 +1,39 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TYPE_TRAITS_TYPE_DEFINITION_HPP
+#define BOOST_COMPUTE_TYPE_TRAITS_TYPE_DEFINITION_HPP
+
+#include <string>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class T>
+struct type_definition_trait;
+
+} // end detail namespace
+
+/// Returns the OpenCL type definition for \c T.
+///
+/// \return a string containing the type definition for \c T
+///
+/// \see type_name<T>()
+template<class T>
+inline std::string type_definition()
+{
+ return detail::type_definition_trait<T>::value();
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_TYPE_TRAITS_TYPE_DEFINITION_HPP
diff --git a/boost/compute/type_traits/type_name.hpp b/boost/compute/type_traits/type_name.hpp
new file mode 100644
index 0000000000..86ac7bc8bc
--- /dev/null
+++ b/boost/compute/type_traits/type_name.hpp
@@ -0,0 +1,124 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TYPE_TRAITS_TYPE_NAME_HPP
+#define BOOST_COMPUTE_TYPE_TRAITS_TYPE_NAME_HPP
+
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/stringize.hpp>
+
+#include <boost/compute/types/fundamental.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class T>
+struct type_name_trait;
+
+/// \internal_
+#define BOOST_COMPUTE_DEFINE_SCALAR_TYPE_NAME_FUNCTION(type) \
+ template<> \
+ struct type_name_trait<BOOST_PP_CAT(type, _)> \
+ { \
+ static const char* value() \
+ { \
+ return BOOST_PP_STRINGIZE(type); \
+ } \
+ };
+
+/// \internal_
+#define BOOST_COMPUTE_DEFINE_VECTOR_TYPE_NAME_FUNCTION(scalar, n) \
+ template<> \
+ struct type_name_trait<BOOST_PP_CAT(BOOST_PP_CAT(scalar, n), _)> \
+ { \
+ static const char* value() \
+ { \
+ return BOOST_PP_STRINGIZE(BOOST_PP_CAT(scalar, n)); \
+ } \
+ };
+
+/// \internal_
+#define BOOST_COMPUTE_DEFINE_TYPE_NAME_FUNCTIONS(scalar) \
+ BOOST_COMPUTE_DEFINE_SCALAR_TYPE_NAME_FUNCTION(scalar) \
+ BOOST_COMPUTE_DEFINE_VECTOR_TYPE_NAME_FUNCTION(scalar, 2) \
+ BOOST_COMPUTE_DEFINE_VECTOR_TYPE_NAME_FUNCTION(scalar, 4) \
+ BOOST_COMPUTE_DEFINE_VECTOR_TYPE_NAME_FUNCTION(scalar, 8) \
+ BOOST_COMPUTE_DEFINE_VECTOR_TYPE_NAME_FUNCTION(scalar, 16)
+
+BOOST_COMPUTE_DEFINE_TYPE_NAME_FUNCTIONS(char)
+BOOST_COMPUTE_DEFINE_TYPE_NAME_FUNCTIONS(uchar)
+BOOST_COMPUTE_DEFINE_TYPE_NAME_FUNCTIONS(short)
+BOOST_COMPUTE_DEFINE_TYPE_NAME_FUNCTIONS(ushort)
+BOOST_COMPUTE_DEFINE_TYPE_NAME_FUNCTIONS(int)
+BOOST_COMPUTE_DEFINE_TYPE_NAME_FUNCTIONS(uint)
+BOOST_COMPUTE_DEFINE_TYPE_NAME_FUNCTIONS(long)
+BOOST_COMPUTE_DEFINE_TYPE_NAME_FUNCTIONS(ulong)
+BOOST_COMPUTE_DEFINE_TYPE_NAME_FUNCTIONS(float)
+BOOST_COMPUTE_DEFINE_TYPE_NAME_FUNCTIONS(double)
+
+/// \internal_
+#define BOOST_COMPUTE_DEFINE_BUILTIN_TYPE_NAME_FUNCTION(type) \
+ template<> \
+ struct type_name_trait<type> \
+ { \
+ static const char* value() \
+ { \
+ return #type; \
+ } \
+ };
+
+BOOST_COMPUTE_DEFINE_BUILTIN_TYPE_NAME_FUNCTION(bool)
+BOOST_COMPUTE_DEFINE_BUILTIN_TYPE_NAME_FUNCTION(char)
+BOOST_COMPUTE_DEFINE_BUILTIN_TYPE_NAME_FUNCTION(void)
+
+} // end detail namespace
+
+/// Returns the OpenCL type name for the type \c T as a string.
+///
+/// \return a string containing the type name for \c T
+///
+/// For example:
+/// \code
+/// type_name<float>() == "float"
+/// type_name<float4_>() == "float4"
+/// \endcode
+///
+/// \see type_definition<T>()
+template<class T>
+inline const char* type_name()
+{
+ return detail::type_name_trait<T>::value();
+}
+
+} // end compute namespace
+} // end boost namespace
+
+/// Registers the OpenCL type for the C++ \p type to \p name.
+///
+/// For example, the following will allow Eigen's \c Vector2f type
+/// to be used with Boost.Compute algorithms and containers as the
+/// built-in \c float2 type.
+/// \code
+/// BOOST_COMPUTE_TYPE_NAME(Eigen::Vector2f, float2)
+/// \endcode
+///
+/// This macro should be invoked in the global namespace.
+///
+/// \see type_name()
+#define BOOST_COMPUTE_TYPE_NAME(type, name) \
+ namespace boost { namespace compute { \
+ template<> \
+ inline const char* type_name<type>() \
+ { \
+ return #name; \
+ }}}
+
+#endif // BOOST_COMPUTE_TYPE_TRAITS_TYPE_NAME_HPP
diff --git a/boost/compute/type_traits/vector_size.hpp b/boost/compute/type_traits/vector_size.hpp
new file mode 100644
index 0000000000..c207a6fedd
--- /dev/null
+++ b/boost/compute/type_traits/vector_size.hpp
@@ -0,0 +1,65 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TYPE_TRAITS_VECTOR_SIZE_HPP
+#define BOOST_COMPUTE_TYPE_TRAITS_VECTOR_SIZE_HPP
+
+#include <boost/preprocessor/cat.hpp>
+
+#include <boost/compute/types/fundamental.hpp>
+
+namespace boost {
+namespace compute {
+
+/// Meta-function returning the size (number of components) of a vector type
+/// \p T. For scalar types this function returns \c 1.
+///
+/// For example,
+/// \code
+/// vector_size<float>::value == 1
+/// vector_size<float4_>::value == 4
+/// \endcode
+template<class T>
+struct vector_size
+{
+ /// \internal_
+ BOOST_STATIC_CONSTANT(size_t, value = 1);
+};
+
+/// \internal_
+#define BOOST_COMPUTE_DECLARE_VECTOR_SIZE_FUNCTION(scalar, size) \
+ template<> \
+ struct vector_size<BOOST_PP_CAT(BOOST_PP_CAT(scalar, size), _)> \
+ { \
+ BOOST_STATIC_CONSTANT(size_t, value = size); \
+ };
+
+/// \internal_
+#define BOOST_COMPUTE_DECLARE_VECTOR_SIZE_FUNCTIONS(scalar) \
+ BOOST_COMPUTE_DECLARE_VECTOR_SIZE_FUNCTION(scalar, 2) \
+ BOOST_COMPUTE_DECLARE_VECTOR_SIZE_FUNCTION(scalar, 4) \
+ BOOST_COMPUTE_DECLARE_VECTOR_SIZE_FUNCTION(scalar, 8) \
+ BOOST_COMPUTE_DECLARE_VECTOR_SIZE_FUNCTION(scalar, 16)
+
+BOOST_COMPUTE_DECLARE_VECTOR_SIZE_FUNCTIONS(char)
+BOOST_COMPUTE_DECLARE_VECTOR_SIZE_FUNCTIONS(uchar)
+BOOST_COMPUTE_DECLARE_VECTOR_SIZE_FUNCTIONS(short)
+BOOST_COMPUTE_DECLARE_VECTOR_SIZE_FUNCTIONS(ushort)
+BOOST_COMPUTE_DECLARE_VECTOR_SIZE_FUNCTIONS(int)
+BOOST_COMPUTE_DECLARE_VECTOR_SIZE_FUNCTIONS(uint)
+BOOST_COMPUTE_DECLARE_VECTOR_SIZE_FUNCTIONS(long)
+BOOST_COMPUTE_DECLARE_VECTOR_SIZE_FUNCTIONS(ulong)
+BOOST_COMPUTE_DECLARE_VECTOR_SIZE_FUNCTIONS(float)
+BOOST_COMPUTE_DECLARE_VECTOR_SIZE_FUNCTIONS(double)
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_TYPE_TRAITS_VECTOR_SIZE_HPP
diff --git a/boost/compute/types.hpp b/boost/compute/types.hpp
new file mode 100644
index 0000000000..3d9120b65c
--- /dev/null
+++ b/boost/compute/types.hpp
@@ -0,0 +1,24 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TYPES_HPP
+#define BOOST_COMPUTE_TYPES_HPP
+
+/// \file
+///
+/// Meta-header to include all Boost.Compute types headers.
+
+#include <boost/compute/types/complex.hpp>
+#include <boost/compute/types/fundamental.hpp>
+#include <boost/compute/types/pair.hpp>
+#include <boost/compute/types/struct.hpp>
+#include <boost/compute/types/tuple.hpp>
+
+#endif // BOOST_COMPUTE_TYPES_HPP
diff --git a/boost/compute/types/builtin.hpp b/boost/compute/types/builtin.hpp
new file mode 100644
index 0000000000..dc30f584eb
--- /dev/null
+++ b/boost/compute/types/builtin.hpp
@@ -0,0 +1,12 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+// deprecated, use <boost/compute/types/fundamental.hpp> instead
+#include <boost/compute/types/fundamental.hpp>
diff --git a/boost/compute/types/complex.hpp b/boost/compute/types/complex.hpp
new file mode 100644
index 0000000000..1d60cef9e5
--- /dev/null
+++ b/boost/compute/types/complex.hpp
@@ -0,0 +1,196 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TYPES_COMPLEX_HPP
+#define BOOST_COMPUTE_TYPES_COMPLEX_HPP
+
+#include <complex>
+
+#include <boost/compute/functional.hpp>
+#include <boost/compute/types/fundamental.hpp>
+#include <boost/compute/type_traits/make_vector_type.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class T>
+meta_kernel& operator<<(meta_kernel &kernel, const std::complex<T> &x)
+{
+ typedef typename std::complex<T> value_type;
+
+ kernel << "(" << type_name<value_type>() << ")"
+ << "(" << x.real() << ", " << x.imag() << ")";
+
+ return kernel;
+}
+
+// get<N>() result type specialization for std::complex<>
+template<size_t N, class T>
+struct get_result_type<N, std::complex<T> >
+{
+ typedef T type;
+};
+
+// get<N>() specialization for std::complex<>
+template<size_t N, class Arg, class T>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const invoked_get<N, Arg, std::complex<T> > &expr)
+{
+ BOOST_STATIC_ASSERT(N < 2);
+
+ return kernel << expr.m_arg << (N == 0 ? ".x" : ".y");
+}
+
+} // end detail namespace
+
+// returns the real component of a complex<T>
+template<class T>
+struct real
+{
+ typedef T result_type;
+
+ template<class Arg>
+ detail::invoked_get<0, Arg, std::complex<T> >
+ operator()(const Arg &x) const
+ {
+ return detail::invoked_get<0, Arg, std::complex<T> >(x);
+ }
+};
+
+// returns the imaginary component of a complex<T>
+template<class T>
+struct imag
+{
+ typedef T result_type;
+
+ template<class Arg>
+ detail::invoked_get<1, Arg, std::complex<T> >
+ operator()(const Arg &x) const
+ {
+ return detail::invoked_get<1, Arg, std::complex<T> >(x);
+ }
+};
+
+namespace detail {
+
+template<class Arg1, class Arg2, class T>
+struct invoked_complex_multiplies
+{
+ typedef typename std::complex<T> result_type;
+
+ invoked_complex_multiplies(const Arg1 &x, const Arg2 &y)
+ : m_x(x),
+ m_y(y)
+ {
+ }
+
+ Arg1 m_x;
+ Arg2 m_y;
+};
+
+template<class Arg1, class Arg2, class T>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const invoked_complex_multiplies<Arg1, Arg2, T> &expr)
+{
+ typedef typename std::complex<T> value_type;
+
+ kernel << "(" << type_name<value_type>() << ")"
+ << "(" << expr.m_x << ".x*" << expr.m_y << ".x-"
+ << expr.m_x << ".y*" << expr.m_y << ".y,"
+ << expr.m_x << ".y*" << expr.m_y << ".x+"
+ << expr.m_x << ".x*" << expr.m_y << ".y" << ")";
+
+ return kernel;
+}
+
+template<class Arg, class T>
+struct invoked_complex_conj
+{
+ typedef typename std::complex<T> result_type;
+
+ invoked_complex_conj(const Arg &arg)
+ : m_arg(arg)
+ {
+ }
+
+ Arg m_arg;
+};
+
+template<class Arg, class T>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const invoked_complex_conj<Arg, T> &expr)
+{
+ typedef typename std::complex<T> value_type;
+
+ kernel << "(" << type_name<value_type>() << ")"
+ << "(" << expr.m_arg << ".x" << ", -" << expr.m_arg << ".y" << ")";
+
+ return kernel;
+}
+
+} // end detail namespace
+
+// specialization for multiplies<T>
+template<class T>
+class multiplies<std::complex<T> > :
+ public function<std::complex<T> (std::complex<T>, std::complex<T>)>
+{
+public:
+ multiplies() :
+ function<
+ std::complex<T> (std::complex<T>, std::complex<T>)
+ >("complex_multiplies")
+ {
+ }
+
+ template<class Arg1, class Arg2>
+ detail::invoked_complex_multiplies<Arg1, Arg2, T>
+ operator()(const Arg1 &x, const Arg2 &y) const
+ {
+ return detail::invoked_complex_multiplies<Arg1, Arg2, T>(x, y);
+ }
+};
+
+// returns the complex conjugate of a complex<T>
+template<class T>
+struct conj
+{
+ typedef typename std::complex<T> result_type;
+
+ template<class Arg>
+ detail::invoked_complex_conj<Arg, T>
+ operator()(const Arg &x) const
+ {
+ return detail::invoked_complex_conj<Arg, T>(x);
+ }
+};
+
+namespace detail {
+
+// type_name() specialization for std::complex
+template<class T>
+struct type_name_trait<std::complex<T> >
+{
+ static const char* value()
+ {
+ typedef typename make_vector_type<T, 2>::type vector_type;
+
+ return type_name<vector_type>();
+ }
+};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_TYPES_COMPLEX_HPP
diff --git a/boost/compute/types/fundamental.hpp b/boost/compute/types/fundamental.hpp
new file mode 100644
index 0000000000..c1502e327e
--- /dev/null
+++ b/boost/compute/types/fundamental.hpp
@@ -0,0 +1,172 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TYPES_FUNDAMENTAL_HPP
+#define BOOST_COMPUTE_TYPES_FUNDAMENTAL_HPP
+
+#include <cstring>
+#include <ostream>
+
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/comma.hpp>
+#include <boost/preprocessor/repetition.hpp>
+#include <boost/preprocessor/stringize.hpp>
+
+#include <boost/compute/cl.hpp>
+
+namespace boost {
+namespace compute {
+
+// scalar data types
+typedef cl_char char_;
+typedef cl_uchar uchar_;
+typedef cl_short short_;
+typedef cl_ushort ushort_;
+typedef cl_int int_;
+typedef cl_uint uint_;
+typedef cl_long long_;
+typedef cl_ulong ulong_;
+typedef cl_float float_;
+typedef cl_double double_;
+
+// converts uchar to ::boost::compute::uchar_
+#define BOOST_COMPUTE_MAKE_SCALAR_TYPE(scalar) \
+ BOOST_PP_CAT(::boost::compute::scalar, _)
+
+// converts float, 4 to ::boost::compute::float4_
+#define BOOST_COMPUTE_MAKE_VECTOR_TYPE(scalar, size) \
+ BOOST_PP_CAT(BOOST_PP_CAT(::boost::compute::scalar, size), _)
+
+// vector data types
+template<class Scalar, size_t N>
+class vector_type
+{
+public:
+ typedef Scalar scalar_type;
+
+ vector_type()
+ {
+
+ }
+
+ explicit vector_type(const Scalar scalar)
+ {
+ for(size_t i = 0; i < N; i++)
+ m_value[i] = scalar;
+ }
+
+ vector_type(const vector_type<Scalar, N> &other)
+ {
+ std::memcpy(m_value, other.m_value, sizeof(m_value));
+ }
+
+ vector_type<Scalar, N>&
+ operator=(const vector_type<Scalar, N> &other)
+ {
+ std::memcpy(m_value, other.m_value, sizeof(m_value));
+ return *this;
+ }
+
+ size_t size() const
+ {
+ return N;
+ }
+
+ Scalar& operator[](size_t i)
+ {
+ return m_value[i];
+ }
+
+ Scalar operator[](size_t i) const
+ {
+ return m_value[i];
+ }
+
+ bool operator==(const vector_type<Scalar, N> &other) const
+ {
+ return std::memcmp(m_value, other.m_value, sizeof(m_value)) == 0;
+ }
+
+ bool operator!=(const vector_type<Scalar, N> &other) const
+ {
+ return !(*this == other);
+ }
+
+protected:
+ scalar_type m_value[N];
+};
+
+#define BOOST_COMPUTE_VECTOR_TYPE_CTOR_ARG_FUNCTION(z, i, _) \
+ BOOST_PP_COMMA_IF(i) scalar_type BOOST_PP_CAT(arg, i)
+#define BOOST_COMPUTE_VECTOR_TYPE_DECLARE_CTOR_ARGS(scalar, size) \
+ BOOST_PP_REPEAT(size, BOOST_COMPUTE_VECTOR_TYPE_CTOR_ARG_FUNCTION, _)
+#define BOOST_COMPUTE_VECTOR_TYPE_ASSIGN_CTOR_ARG(z, i, _) \
+ m_value[i] = BOOST_PP_CAT(arg, i);
+#define BOOST_COMPUTE_VECTOR_TYPE_ASSIGN_CTOR_SINGLE_ARG(z, i, _) \
+ m_value[i] = arg;
+
+#define BOOST_COMPUTE_DECLARE_VECTOR_TYPE_CLASS(cl_scalar, size, class_name) \
+ class class_name : public vector_type<cl_scalar, size> \
+ { \
+ public: \
+ class_name() { } \
+ explicit class_name( scalar_type arg ) \
+ { \
+ BOOST_PP_REPEAT(size, BOOST_COMPUTE_VECTOR_TYPE_ASSIGN_CTOR_SINGLE_ARG, _) \
+ } \
+ class_name( \
+ BOOST_PP_REPEAT(size, BOOST_COMPUTE_VECTOR_TYPE_CTOR_ARG_FUNCTION, _) \
+ ) \
+ { \
+ BOOST_PP_REPEAT(size, BOOST_COMPUTE_VECTOR_TYPE_ASSIGN_CTOR_ARG, _) \
+ } \
+ };
+
+#define BOOST_COMPUTE_DECLARE_VECTOR_TYPE(scalar, size) \
+ BOOST_COMPUTE_DECLARE_VECTOR_TYPE_CLASS(BOOST_PP_CAT(cl_, scalar), \
+ size, \
+ BOOST_PP_CAT(BOOST_PP_CAT(scalar, size), _)) \
+ \
+ inline std::ostream& operator<<( \
+ std::ostream &s, \
+ const BOOST_COMPUTE_MAKE_VECTOR_TYPE(scalar, size) &v) \
+ { \
+ s << BOOST_PP_STRINGIZE(BOOST_PP_CAT(scalar, size)) << "("; \
+ for(size_t i = 0; i < size; i++){\
+ s << v[i]; \
+ if(i != size - 1){\
+ s << ", "; \
+ } \
+ } \
+ s << ")"; \
+ return s; \
+ }
+
+#define BOOST_COMPUTE_DECLARE_VECTOR_TYPES(scalar) \
+ BOOST_COMPUTE_DECLARE_VECTOR_TYPE(scalar, 2) \
+ BOOST_COMPUTE_DECLARE_VECTOR_TYPE(scalar, 4) \
+ BOOST_COMPUTE_DECLARE_VECTOR_TYPE(scalar, 8) \
+ BOOST_COMPUTE_DECLARE_VECTOR_TYPE(scalar, 16) \
+
+BOOST_COMPUTE_DECLARE_VECTOR_TYPES(char)
+BOOST_COMPUTE_DECLARE_VECTOR_TYPES(uchar)
+BOOST_COMPUTE_DECLARE_VECTOR_TYPES(short)
+BOOST_COMPUTE_DECLARE_VECTOR_TYPES(ushort)
+BOOST_COMPUTE_DECLARE_VECTOR_TYPES(int)
+BOOST_COMPUTE_DECLARE_VECTOR_TYPES(uint)
+BOOST_COMPUTE_DECLARE_VECTOR_TYPES(long)
+BOOST_COMPUTE_DECLARE_VECTOR_TYPES(ulong)
+BOOST_COMPUTE_DECLARE_VECTOR_TYPES(float)
+BOOST_COMPUTE_DECLARE_VECTOR_TYPES(double)
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_TYPES_FUNDAMENTAL_HPP
diff --git a/boost/compute/types/pair.hpp b/boost/compute/types/pair.hpp
new file mode 100644
index 0000000000..96db6539f1
--- /dev/null
+++ b/boost/compute/types/pair.hpp
@@ -0,0 +1,117 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TYPES_PAIR_HPP
+#define BOOST_COMPUTE_TYPES_PAIR_HPP
+
+#include <string>
+#include <utility>
+
+#include <boost/compute/functional/get.hpp>
+#include <boost/compute/type_traits/type_definition.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+// meta_kernel operator for std::pair literals
+template<class T1, class T2>
+inline meta_kernel&
+operator<<(meta_kernel &kernel, const std::pair<T1, T2> &x)
+{
+ kernel << "(" << type_name<std::pair<T1, T2> >() << ")"
+ << "{" << kernel.make_lit(x.first) << ", "
+ << kernel.make_lit(x.second) << "}";
+
+ return kernel;
+}
+
+// inject_type() specialization for std::pair
+template<class T1, class T2>
+struct inject_type_impl<std::pair<T1, T2> >
+{
+ void operator()(meta_kernel &kernel)
+ {
+ typedef std::pair<T1, T2> pair_type;
+
+ kernel.inject_type<T1>();
+ kernel.inject_type<T2>();
+
+ kernel.add_type_declaration<pair_type>(type_definition<pair_type>());
+ }
+};
+
+// get<N>() result type specialization for std::pair<>
+template<class T1, class T2>
+struct get_result_type<0, std::pair<T1, T2> >
+{
+ typedef T1 type;
+};
+
+template<class T1, class T2>
+struct get_result_type<1, std::pair<T1, T2> >
+{
+ typedef T2 type;
+};
+
+// get<N>() specialization for std::pair<>
+template<size_t N, class Arg, class T1, class T2>
+inline meta_kernel& operator<<(meta_kernel &kernel,
+ const invoked_get<N, Arg, std::pair<T1, T2> > &expr)
+{
+ kernel.inject_type<std::pair<T1, T2> >();
+
+ return kernel << expr.m_arg << (N == 0 ? ".first" : ".second");
+}
+
+} // end detail namespace
+
+namespace detail {
+
+// type_name() specialization for std::pair
+template<class T1, class T2>
+struct type_name_trait<std::pair<T1, T2> >
+{
+ static const char* value()
+ {
+ static std::string name =
+ std::string("_pair_") +
+ type_name<T1>() + "_" + type_name<T2>() +
+ "_t";
+
+ return name.c_str();
+ }
+};
+
+// type_definition() specialization for std::pair
+template<class T1, class T2>
+struct type_definition_trait<std::pair<T1, T2> >
+{
+ static std::string value()
+ {
+ typedef std::pair<T1, T2> pair_type;
+
+ std::stringstream declaration;
+ declaration << "typedef struct {\n"
+ << " " << type_name<T1>() << " first;\n"
+ << " " << type_name<T2>() << " second;\n"
+ << "} " << type_name<pair_type>() << ";\n";
+
+ return declaration.str();
+ }
+};
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_TYPES_PAIR_HPP
diff --git a/boost/compute/types/struct.hpp b/boost/compute/types/struct.hpp
new file mode 100644
index 0000000000..92aeaedf22
--- /dev/null
+++ b/boost/compute/types/struct.hpp
@@ -0,0 +1,173 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TYPES_STRUCT_HPP
+#define BOOST_COMPUTE_TYPES_STRUCT_HPP
+
+#include <sstream>
+
+#include <boost/static_assert.hpp>
+
+#include <boost/preprocessor/expr_if.hpp>
+#include <boost/preprocessor/stringize.hpp>
+#include <boost/preprocessor/seq/fold_left.hpp>
+#include <boost/preprocessor/seq/for_each.hpp>
+#include <boost/preprocessor/seq/transform.hpp>
+
+#include <boost/compute/type_traits/type_definition.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/variadic_macros.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class Struct, class T>
+inline std::string adapt_struct_insert_member(T Struct::*, const char *name)
+{
+ std::stringstream s;
+ s << " " << type_name<T>() << " " << name << ";\n";
+ return s.str();
+}
+
+
+template<class Struct, class T, int N>
+inline std::string adapt_struct_insert_member(T (Struct::*)[N], const char *name)
+{
+ std::stringstream s;
+ s << " " << type_name<T>() << " " << name << "[" << N << "]" << ";\n";
+ return s.str();
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+/// \internal_
+#define BOOST_COMPUTE_DETAIL_ADAPT_STRUCT_INSERT_MEMBER(r, type, member) \
+ << ::boost::compute::detail::adapt_struct_insert_member( \
+ &type::member, BOOST_PP_STRINGIZE(member) \
+ )
+
+/// \internal_
+#define BOOST_COMPUTE_DETAIL_ADAPT_STRUCT_STREAM_MEMBER(r, data, i, elem) \
+ BOOST_PP_EXPR_IF(i, << ", ") << data.elem
+
+/// \internal_
+#define BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE(s, struct_, member_) \
+ sizeof(((struct_ *)0)->member_)
+
+/// \internal_
+#define BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE_ADD(s, x, y) (x+y)
+
+/// \internal_
+#define BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE_SUM(struct_, members_) \
+ BOOST_PP_SEQ_FOLD_LEFT( \
+ BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE_ADD, \
+ 0, \
+ BOOST_PP_SEQ_TRANSFORM( \
+ BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE, struct_, members_ \
+ ) \
+ )
+
+/// \internal_
+///
+/// Returns true if struct_ contains no internal padding bytes (i.e. it is
+/// packed). members_ is a sequence of the names of the struct members.
+#define BOOST_COMPUTE_DETAIL_STRUCT_IS_PACKED(struct_, members_) \
+ (sizeof(struct_) == BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE_SUM(struct_, members_))
+
+/// The BOOST_COMPUTE_ADAPT_STRUCT() macro makes a C++ struct/class available
+/// to OpenCL kernels.
+///
+/// \param type The C++ type.
+/// \param name The OpenCL name.
+/// \param members A tuple of the struct's members.
+///
+/// For example, to adapt a 2D particle struct with position (x, y) and
+/// velocity (dx, dy):
+/// \code
+/// // c++ struct definition
+/// struct Particle
+/// {
+/// float x, y;
+/// float dx, dy;
+/// };
+///
+/// // adapt struct for OpenCL
+/// BOOST_COMPUTE_ADAPT_STRUCT(Particle, Particle, (x, y, dx, dy))
+/// \endcode
+///
+/// After adapting the struct it can be used in Boost.Compute containers
+/// and with Boost.Compute algorithms:
+/// \code
+/// // create vector of particles
+/// boost::compute::vector<Particle> particles = ...
+///
+/// // function to compare particles by their x-coordinate
+/// BOOST_COMPUTE_FUNCTION(bool, sort_by_x, (Particle a, Particle b),
+/// {
+/// return a.x < b.x;
+/// });
+///
+/// // sort particles by their x-coordinate
+/// boost::compute::sort(
+/// particles.begin(), particles.end(), sort_by_x, queue
+/// );
+/// \endcode
+///
+/// Due to differences in struct padding between the host compiler and the
+/// device compiler, the \c BOOST_COMPUTE_ADAPT_STRUCT() macro requires that
+/// the adapted struct is packed (i.e. no padding bytes between members).
+///
+/// \see type_name()
+#define BOOST_COMPUTE_ADAPT_STRUCT(type, name, members) \
+ BOOST_STATIC_ASSERT_MSG( \
+ BOOST_COMPUTE_DETAIL_STRUCT_IS_PACKED(type, BOOST_COMPUTE_PP_TUPLE_TO_SEQ(members)), \
+ "BOOST_COMPUTE_ADAPT_STRUCT() does not support structs with internal padding." \
+ ); \
+ BOOST_COMPUTE_TYPE_NAME(type, name) \
+ namespace boost { namespace compute { \
+ template<> \
+ inline std::string type_definition<type>() \
+ { \
+ std::stringstream declaration; \
+ declaration << "typedef struct __attribute__((packed)) {\n" \
+ BOOST_PP_SEQ_FOR_EACH( \
+ BOOST_COMPUTE_DETAIL_ADAPT_STRUCT_INSERT_MEMBER, \
+ type, \
+ BOOST_COMPUTE_PP_TUPLE_TO_SEQ(members) \
+ ) \
+ << "} " << type_name<type>() << ";\n"; \
+ return declaration.str(); \
+ } \
+ namespace detail { \
+ template<> \
+ struct inject_type_impl<type> \
+ { \
+ void operator()(meta_kernel &kernel) \
+ { \
+ kernel.add_type_declaration<type>(type_definition<type>()); \
+ } \
+ }; \
+ inline meta_kernel& operator<<(meta_kernel &k, type s) \
+ { \
+ return k << "(" << #name << "){" \
+ BOOST_PP_SEQ_FOR_EACH_I( \
+ BOOST_COMPUTE_DETAIL_ADAPT_STRUCT_STREAM_MEMBER, \
+ s, \
+ BOOST_COMPUTE_PP_TUPLE_TO_SEQ(members) \
+ ) \
+ << "}"; \
+ } \
+ }}}
+
+#endif // BOOST_COMPUTE_TYPES_STRUCT_HPP
diff --git a/boost/compute/types/tuple.hpp b/boost/compute/types/tuple.hpp
new file mode 100644
index 0000000000..095bd95448
--- /dev/null
+++ b/boost/compute/types/tuple.hpp
@@ -0,0 +1,220 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TYPES_TUPLE_HPP
+#define BOOST_COMPUTE_TYPES_TUPLE_HPP
+
+#include <string>
+#include <utility>
+
+#include <boost/preprocessor/enum.hpp>
+#include <boost/preprocessor/expr_if.hpp>
+#include <boost/preprocessor/repetition.hpp>
+#include <boost/tuple/tuple.hpp>
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/functional/get.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+
+#ifndef BOOST_COMPUTE_NO_STD_TUPLE
+#include <tuple>
+#endif
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+// meta_kernel operators for boost::tuple literals
+#define BOOST_COMPUTE_PRINT_ELEM(z, n, unused) \
+ BOOST_PP_EXPR_IF(n, << ", ") \
+ << kernel.make_lit(boost::get<n>(x))
+
+#define BOOST_COMPUTE_PRINT_TUPLE(z, n, unused) \
+template<BOOST_PP_ENUM_PARAMS(n, class T)> \
+inline meta_kernel& \
+operator<<(meta_kernel &kernel, \
+ const boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> &x) \
+{ \
+ return kernel \
+ << "(" \
+ << type_name<boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> >() \
+ << ")" \
+ << "{" \
+ BOOST_PP_REPEAT(n, BOOST_COMPUTE_PRINT_ELEM, ~) \
+ << "}"; \
+}
+
+BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_PRINT_TUPLE, ~)
+
+#undef BOOST_COMPUTE_PRINT_TUPLE
+#undef BOOST_COMPUTE_PRINT_ELEM
+
+// inject_type() specializations for boost::tuple
+#define BOOST_COMPUTE_INJECT_TYPE(z, n, unused) \
+ kernel.inject_type<T ## n>();
+
+#define BOOST_COMPUTE_INJECT_DECL(z, n, unused) \
+ << " " << type_name<T ## n>() << " v" #n ";\n"
+
+#define BOOST_COMPUTE_INJECT_IMPL(z, n, unused) \
+template<BOOST_PP_ENUM_PARAMS(n, class T)> \
+struct inject_type_impl<boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> > \
+{ \
+ void operator()(meta_kernel &kernel) \
+ { \
+ typedef boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> tuple_type; \
+ BOOST_PP_REPEAT(n, BOOST_COMPUTE_INJECT_TYPE, ~) \
+ std::stringstream declaration; \
+ declaration << "typedef struct {\n" \
+ BOOST_PP_REPEAT(n, BOOST_COMPUTE_INJECT_DECL, ~) \
+ << "} " << type_name<tuple_type>() << ";\n"; \
+ kernel.add_type_declaration<tuple_type>(declaration.str()); \
+ } \
+};
+
+BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_INJECT_IMPL, ~)
+
+#undef BOOST_COMPUTE_INJECT_IMPL
+#undef BOOST_COMPUTE_INJECT_DECL
+#undef BOOST_COMPUTE_INJECT_TYPE
+
+#ifdef BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
+// type_name() specializations for boost::tuple (without variadic templates)
+#define BOOST_COMPUTE_PRINT_TYPE(z, n, unused) \
+ + type_name<T ## n>() + "_"
+
+#define BOOST_COMPUTE_PRINT_TYPE_NAME(z, n, unused) \
+template<BOOST_PP_ENUM_PARAMS(n, class T)> \
+struct type_name_trait<boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> > \
+{ \
+ static const char* value() \
+ { \
+ static std::string name = \
+ std::string("boost_tuple_") \
+ BOOST_PP_REPEAT(n, BOOST_COMPUTE_PRINT_TYPE, ~) \
+ "t"; \
+ return name.c_str(); \
+ } \
+};
+
+BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_PRINT_TYPE_NAME, ~)
+
+#undef BOOST_COMPUTE_PRINT_TYPE_NAME
+#undef BOOST_COMPUTE_PRINT_TYPE
+
+#else
+template<size_t N, class T, class... Rest>
+struct write_tuple_type_names
+{
+ void operator()(std::ostream &os)
+ {
+ os << type_name<T>() << "_";
+ write_tuple_type_names<N-1, Rest...>()(os);
+ }
+};
+
+template<class T, class... Rest>
+struct write_tuple_type_names<1, T, Rest...>
+{
+ void operator()(std::ostream &os)
+ {
+ os << type_name<T>();
+ }
+};
+
+// type_name<> specialization for boost::tuple<...> (with variadic templates)
+template<class... T>
+struct type_name_trait<boost::tuple<T...>>
+{
+ static const char* value()
+ {
+ static std::string str = make_type_name();
+
+ return str.c_str();
+ }
+
+ static std::string make_type_name()
+ {
+ typedef typename boost::tuple<T...> tuple_type;
+
+ std::stringstream s;
+ s << "boost_tuple_";
+ write_tuple_type_names<
+ boost::tuples::length<tuple_type>::value, T...
+ >()(s);
+ s << "_t";
+ return s.str();
+ }
+};
+#endif // BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
+
+#ifndef BOOST_COMPUTE_NO_STD_TUPLE
+// type_name<> specialization for std::tuple<T...>
+template<class... T>
+struct type_name_trait<std::tuple<T...>>
+{
+ static const char* value()
+ {
+ static std::string str = make_type_name();
+
+ return str.c_str();
+ }
+
+ static std::string make_type_name()
+ {
+ typedef typename std::tuple<T...> tuple_type;
+
+ std::stringstream s;
+ s << "std_tuple_";
+ write_tuple_type_names<
+ std::tuple_size<tuple_type>::value, T...
+ >()(s);
+ s << "_t";
+ return s.str();
+ }
+};
+#endif // BOOST_COMPUTE_NO_STD_TUPLE
+
+// get<N>() result type specialization for boost::tuple<>
+#define BOOST_COMPUTE_GET_RESULT_TYPE(z, n, unused) \
+template<size_t N, BOOST_PP_ENUM_PARAMS(n, class T)> \
+struct get_result_type<N, boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> > \
+{ \
+ typedef typename boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> T; \
+ typedef typename boost::tuples::element<N, T>::type type; \
+};
+
+BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_GET_RESULT_TYPE, ~)
+
+#undef BOOST_COMPUTE_GET_RESULT_TYPE
+
+
+// get<N>() specialization for boost::tuple<>
+#define BOOST_COMPUTE_GET_N(z, n, unused) \
+template<size_t N, class Arg, BOOST_PP_ENUM_PARAMS(n, class T)> \
+inline meta_kernel& operator<<(meta_kernel &kernel, \
+ const invoked_get<N, Arg, boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> > &expr) \
+{ \
+ typedef typename boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> T; \
+ BOOST_STATIC_ASSERT(N < size_t(boost::tuples::length<T>::value)); \
+ kernel.inject_type<T>(); \
+ return kernel << expr.m_arg << ".v" << uint_(N); \
+}
+
+BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_GET_N, ~)
+
+#undef BOOST_COMPUTE_GET_N
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_TYPES_TUPLE_HPP
diff --git a/boost/compute/user_event.hpp b/boost/compute/user_event.hpp
new file mode 100644
index 0000000000..a3fdba033e
--- /dev/null
+++ b/boost/compute/user_event.hpp
@@ -0,0 +1,88 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_USER_EVENT_HPP
+#define BOOST_COMPUTE_USER_EVENT_HPP
+
+#include <boost/compute/event.hpp>
+#include <boost/compute/context.hpp>
+
+namespace boost {
+namespace compute {
+
+#if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+/// \class user_event
+/// \brief An user-created event.
+///
+/// \opencl_version_warning{1,1}
+///
+/// \see event
+class user_event : public event
+{
+public:
+ /// Creates a new user-event object.
+ ///
+ /// \see_opencl_ref{clCreateUserEvent}
+ explicit user_event(const context &context)
+ {
+ cl_int error;
+ m_event = clCreateUserEvent(context.get(), &error);
+ if(!m_event){
+ BOOST_THROW_EXCEPTION(opencl_error(error));
+ }
+ }
+
+ /// Creates a new user-event from \p other.
+ user_event(const user_event &other)
+ : event(other)
+ {
+ }
+
+ /// Copies the user-event from \p other to \c *this.
+ user_event& operator=(const user_event &other)
+ {
+ event::operator=(other);
+
+ return *this;
+ }
+
+ #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+ /// Move-constructs a new user event object from \p other.
+ user_event(user_event&& other) BOOST_NOEXCEPT
+ : event(std::move(other))
+ {
+ }
+
+ /// Move-assigns the user event from \p other to \c *this.
+ user_event& operator=(user_event&& other) BOOST_NOEXCEPT
+ {
+ event::operator=(std::move(other));
+
+ return *this;
+ }
+ #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+ /// Sets the execution status for the user-event.
+ ///
+ /// \see_opencl_ref{clSetUserEventStatus}
+ void set_status(cl_int execution_status)
+ {
+ cl_int ret = clSetUserEventStatus(m_event, execution_status);
+ if(ret != CL_SUCCESS){
+ BOOST_THROW_EXCEPTION(opencl_error(ret));
+ }
+ }
+};
+#endif // CL_VERSION_1_1
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_EVENT_HPP
diff --git a/boost/compute/utility.hpp b/boost/compute/utility.hpp
new file mode 100644
index 0000000000..e6d1f6eab6
--- /dev/null
+++ b/boost/compute/utility.hpp
@@ -0,0 +1,21 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_UTILITY_HPP
+#define BOOST_COMPUTE_UTILITY_HPP
+
+#include <boost/compute/utility/dim.hpp>
+#include <boost/compute/utility/extents.hpp>
+#include <boost/compute/utility/invoke.hpp>
+#include <boost/compute/utility/program_cache.hpp>
+#include <boost/compute/utility/source.hpp>
+#include <boost/compute/utility/wait_list.hpp>
+
+#endif // BOOST_COMPUTE_UTILITY_HPP
diff --git a/boost/compute/utility/dim.hpp b/boost/compute/utility/dim.hpp
new file mode 100644
index 0000000000..210c09cf6e
--- /dev/null
+++ b/boost/compute/utility/dim.hpp
@@ -0,0 +1,76 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_UTILITY_DIM_HPP
+#define BOOST_COMPUTE_UTILITY_DIM_HPP
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/utility/extents.hpp>
+
+namespace boost {
+namespace compute {
+
+#ifndef BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
+/// The variadic \c dim() function provides a concise syntax for creating
+/// \ref extents objects.
+///
+/// For example,
+/// \code
+/// extents<2> region = dim(640, 480); // region == (640, 480)
+/// \endcode
+///
+/// \see \ref extents "extents<N>"
+template<class... Args>
+inline extents<sizeof...(Args)> dim(Args... args)
+{
+ return extents<sizeof...(Args)>({ static_cast<size_t>(args)... });
+}
+
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1800)
+// for some inexplicable reason passing one parameter to 'dim' variadic template
+// generates compile error on msvc 2013 update 4
+template<class T>
+inline extents<1> dim(T arg)
+{
+ return extents<1>(static_cast<size_t>(arg));
+}
+#endif // BOOST_WORKAROUND(BOOST_MSVC, <= 1800)
+
+#else
+// dim() function definitions for non-c++11 compilers
+#define BOOST_COMPUTE_DETAIL_ASSIGN_DIM(z, n, var) \
+ var[n] = BOOST_PP_CAT(e, n);
+
+#define BOOST_COMPUTE_DETAIL_DEFINE_DIM(z, n, var) \
+ inline extents<n> dim(BOOST_PP_ENUM_PARAMS(n, size_t e)) \
+ { \
+ extents<n> exts; \
+ BOOST_PP_REPEAT(n, BOOST_COMPUTE_DETAIL_ASSIGN_DIM, exts) \
+ return exts; \
+ }
+
+BOOST_PP_REPEAT(BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_DETAIL_DEFINE_DIM, ~)
+
+#undef BOOST_COMPUTE_DETAIL_ASSIGN_DIM
+#undef BOOST_COMPUTE_DETAIL_DEFINE_DIM
+
+#endif // BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
+
+/// \internal_
+template<size_t N>
+inline extents<N> dim()
+{
+ return extents<N>();
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_UTILITY_DIM_HPP
diff --git a/boost/compute/utility/extents.hpp b/boost/compute/utility/extents.hpp
new file mode 100644
index 0000000000..9666d47abc
--- /dev/null
+++ b/boost/compute/utility/extents.hpp
@@ -0,0 +1,164 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_UTILITY_EXTENTS_HPP
+#define BOOST_COMPUTE_UTILITY_EXTENTS_HPP
+
+#include <functional>
+#include <numeric>
+
+#include <boost/compute/config.hpp>
+
+#ifndef BOOST_COMPUTE_NO_HDR_INITIALIZER_LIST
+#include <initializer_list>
+#endif
+
+#include <boost/array.hpp>
+
+namespace boost {
+namespace compute {
+
+/// The extents class contains an array of n-dimensional extents.
+///
+/// \see dim()
+template<size_t N>
+class extents
+{
+public:
+ typedef size_t size_type;
+ static const size_type static_size = N;
+ typedef boost::array<size_t, N> array_type;
+ typedef typename array_type::iterator iterator;
+ typedef typename array_type::const_iterator const_iterator;
+
+ /// Creates an extents object with each component set to zero.
+ ///
+ /// For example:
+ /// \code
+ /// extents<3> exts(); // (0, 0, 0)
+ /// \endcode
+ extents()
+ {
+ m_extents.fill(0);
+ }
+
+ /// Creates an extents object with each component set to \p value.
+ ///
+ /// For example:
+ /// \code
+ /// extents<3> exts(1); // (1, 1, 1)
+ /// \endcode
+ explicit extents(size_t value)
+ {
+ m_extents.fill(value);
+ }
+
+ #ifndef BOOST_COMPUTE_NO_HDR_INITIALIZER_LIST
+ /// Creates an extents object with \p values.
+ extents(std::initializer_list<size_t> values)
+ {
+ BOOST_ASSERT(values.size() == N);
+
+ std::copy(values.begin(), values.end(), m_extents.begin());
+ }
+ #endif // BOOST_COMPUTE_NO_HDR_INITIALIZER_LIST
+
+ /// Returns the size (i.e. dimensionality) of the extents array.
+ size_type size() const
+ {
+ return N;
+ }
+
+ /// Returns the linear size of the extents. This is equivalent to the
+ /// product of each extent in each dimension.
+ size_type linear() const
+ {
+ return std::accumulate(
+ m_extents.begin(), m_extents.end(), 1, std::multiplies<size_type>()
+ );
+ }
+
+ /// Returns a pointer to the extents data array.
+ ///
+ /// This is useful for passing the extents data to OpenCL APIs which
+ /// expect an array of \c size_t.
+ size_t* data()
+ {
+ return m_extents.data();
+ }
+
+ /// \overload
+ const size_t* data() const
+ {
+ return m_extents.data();
+ }
+
+ iterator begin()
+ {
+ return m_extents.begin();
+ }
+
+ const_iterator begin() const
+ {
+ return m_extents.begin();
+ }
+
+ const_iterator cbegin() const
+ {
+ return m_extents.cbegin();
+ }
+
+ iterator end()
+ {
+ return m_extents.end();
+ }
+
+ const_iterator end() const
+ {
+ return m_extents.end();
+ }
+
+ const_iterator cend() const
+ {
+ return m_extents.cend();
+ }
+
+ /// Returns a reference to the extent at \p index.
+ size_t& operator[](size_t index)
+ {
+ return m_extents[index];
+ }
+
+ /// \overload
+ const size_t& operator[](size_t index) const
+ {
+ return m_extents[index];
+ }
+
+ /// Returns \c true if the extents in \c *this are the same as \p other.
+ bool operator==(const extents &other) const
+ {
+ return m_extents == other.m_extents;
+ }
+
+ /// Returns \c true if the extents in \c *this are not the same as \p other.
+ bool operator!=(const extents &other) const
+ {
+ return m_extents != other.m_extents;
+ }
+
+private:
+ array_type m_extents;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_UTILITY_EXTENTS_HPP
diff --git a/boost/compute/utility/invoke.hpp b/boost/compute/utility/invoke.hpp
new file mode 100644
index 0000000000..b03162aa2b
--- /dev/null
+++ b/boost/compute/utility/invoke.hpp
@@ -0,0 +1,71 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://kylelutz.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_UTILITY_INVOKE_HPP
+#define BOOST_COMPUTE_UTILITY_INVOKE_HPP
+
+#include <boost/preprocessor/enum.hpp>
+#include <boost/preprocessor/repetition.hpp>
+
+#include <boost/compute/config.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/container/detail/scalar.hpp>
+#include <boost/compute/type_traits/result_of.hpp>
+
+namespace boost {
+namespace compute {
+
+#define BOOST_COMPUTE_DETAIL_INVOKE_ARG(z, n, unused) \
+ BOOST_PP_COMMA_IF(n) k.var<BOOST_PP_CAT(T, n)>("arg" BOOST_PP_STRINGIZE(n))
+
+#define BOOST_COMPUTE_DETAIL_INVOKE_ADD_ARG(z, n, unused) \
+ k.add_set_arg("arg" BOOST_PP_STRINGIZE(n), BOOST_PP_CAT(arg, n));
+
+#define BOOST_COMPUTE_DETAIL_DEFINE_INVOKE(z, n, unused) \
+template<class Function, BOOST_PP_ENUM_PARAMS(n, class T)> \
+inline typename result_of<Function(BOOST_PP_ENUM_PARAMS(n, T))>::type \
+invoke(const Function& function, command_queue& queue, BOOST_PP_ENUM_BINARY_PARAMS(n, const T, &arg)) \
+{ \
+ typedef typename result_of<Function(BOOST_PP_ENUM_PARAMS(n, T))>::type result_type; \
+ detail::meta_kernel k("invoke"); \
+ detail::scalar<result_type> result(queue.get_context()); \
+ const size_t result_arg = k.add_arg<result_type *>(memory_object::global_memory, "result"); \
+ BOOST_PP_REPEAT(n, BOOST_COMPUTE_DETAIL_INVOKE_ADD_ARG, ~) \
+ k << "*result = " << function( \
+ BOOST_PP_REPEAT(n, BOOST_COMPUTE_DETAIL_INVOKE_ARG, ~) \
+ ) << ";"; \
+ k.set_arg(result_arg, result.get_buffer()); \
+ k.exec(queue); \
+ return result.read(queue); \
+}
+
+BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_DETAIL_DEFINE_INVOKE, ~)
+
+#undef BOOST_COMPUTE_DETAIL_INVOKE_ARG
+#undef BOOST_COMPUTE_DETAIL_INVOKE_ADD_ARG
+#undef BOOST_COMPUTE_DETAIL_DEFINE_INVOKE
+
+#ifdef BOOST_COMPUTE_DOXYGEN_INVOKED
+/// Invokes \p function with \p args on \p queue.
+///
+/// For example, to invoke the builtin abs() function:
+/// \code
+/// int result = invoke(abs<int>(), queue, -10); // returns 10
+/// \endcode
+template<class Function, class... Args>
+inline typename result_of<Function(Args...)>::type
+invoke(const Function& function, command_queue& queue, const Args&... args);
+#endif // BOOST_COMPUTE_DOXYGEN_INVOKED
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_UTILITY_INVOKE_HPP
diff --git a/boost/compute/utility/program_cache.hpp b/boost/compute/utility/program_cache.hpp
new file mode 100644
index 0000000000..c80e1a3b1e
--- /dev/null
+++ b/boost/compute/utility/program_cache.hpp
@@ -0,0 +1,172 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_UTILITY_PROGRAM_CACHE_HPP
+#define BOOST_COMPUTE_UTILITY_PROGRAM_CACHE_HPP
+
+#include <string>
+#include <utility>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/noncopyable.hpp>
+
+#include <boost/compute/context.hpp>
+#include <boost/compute/program.hpp>
+#include <boost/compute/detail/lru_cache.hpp>
+#include <boost/compute/detail/global_static.hpp>
+
+namespace boost {
+namespace compute {
+
+/// The program_cache class stores \ref program objects in a LRU cache.
+///
+/// This class can be used to help mitigate the overhead of OpenCL's run-time
+/// kernel compilation model. Commonly used programs can be stored persistently
+/// in the cache and only compiled once on their first use.
+///
+/// Program objects are stored and retreived based on a user-defined cache key
+/// along with the options used to build the program (if any).
+///
+/// For example, to insert a program into the cache:
+/// \code
+/// cache.insert("foo", foo_program);
+/// \endcode
+///
+/// And to retreive the program later:
+/// \code
+/// boost::optional<program> p = cache.get("foo");
+/// if(p){
+/// // program found in cache
+/// }
+/// \endcode
+///
+/// \see program
+class program_cache : boost::noncopyable
+{
+public:
+ /// Creates a new program cache with space for \p capacity number of
+ /// program objects.
+ program_cache(size_t capacity)
+ : m_cache(capacity)
+ {
+ }
+
+ /// Destroys the program cache.
+ ~program_cache()
+ {
+ }
+
+ /// Returns the number of program objects currently stored in the cache.
+ size_t size() const
+ {
+ return m_cache.size();
+ }
+
+ /// Returns the total capacity of the cache.
+ size_t capacity() const
+ {
+ return m_cache.capacity();
+ }
+
+ /// Clears the program cache.
+ void clear()
+ {
+ m_cache.clear();
+ }
+
+ /// Returns the program object with \p key. Returns a null optional if no
+ /// program with \p key exists in the cache.
+ boost::optional<program> get(const std::string &key)
+ {
+ return m_cache.get(std::make_pair(key, std::string()));
+ }
+
+ /// Returns the program object with \p key and \p options. Returns a null
+ /// optional if no program with \p key and \p options exists in the cache.
+ boost::optional<program> get(const std::string &key, const std::string &options)
+ {
+ return m_cache.get(std::make_pair(key, options));
+ }
+
+ /// Inserts \p program into the cache with \p key.
+ void insert(const std::string &key, const program &program)
+ {
+ insert(key, std::string(), program);
+ }
+
+ /// Inserts \p program into the cache with \p key and \p options.
+ void insert(const std::string &key, const std::string &options, const program &program)
+ {
+ m_cache.insert(std::make_pair(key, options), program);
+ }
+
+ /// Loads the program with \p key from the cache if it exists. Otherwise
+ /// builds a new program with \p source and \p options, stores it in the
+ /// cache, and returns it.
+ ///
+ /// This is a convenience function to simplify the common pattern of
+ /// attempting to load a program from the cache and, if not present,
+ /// building the program from source and storing it in the cache.
+ ///
+ /// Equivalent to:
+ /// \code
+ /// boost::optional<program> p = get(key, options);
+ /// if(!p){
+ /// p = program::create_with_source(source, context);
+ /// p->build(options);
+ /// insert(key, options, *p);
+ /// }
+ /// return *p;
+ /// \endcode
+ program get_or_build(const std::string &key,
+ const std::string &options,
+ const std::string &source,
+ const context &context)
+ {
+ boost::optional<program> p = get(key, options);
+ if(!p){
+ p = program::build_with_source(source, context, options);
+
+ insert(key, options, *p);
+ }
+ return *p;
+ }
+
+ /// Returns the global program cache for \p context.
+ ///
+ /// This global cache is used internally by Boost.Compute to store compiled
+ /// program objects used by its algorithms. All Boost.Compute programs are
+ /// stored with a cache key beginning with \c "__boost". User programs
+ /// should avoid using the same prefix in order to prevent collisions.
+ static boost::shared_ptr<program_cache> get_global_cache(const context &context)
+ {
+ typedef detail::lru_cache<cl_context, boost::shared_ptr<program_cache> > cache_map;
+
+ BOOST_COMPUTE_DETAIL_GLOBAL_STATIC(cache_map, caches, (8));
+
+ boost::optional<boost::shared_ptr<program_cache> > cache = caches.get(context.get());
+ if(!cache){
+ cache = boost::make_shared<program_cache>(64);
+
+ caches.insert(context.get(), *cache);
+ }
+
+ return *cache;
+ }
+
+private:
+ detail::lru_cache<std::pair<std::string, std::string>, program> m_cache;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_UTILITY_PROGRAM_CACHE_HPP
diff --git a/boost/compute/utility/source.hpp b/boost/compute/utility/source.hpp
new file mode 100644
index 0000000000..3b073fbc82
--- /dev/null
+++ b/boost/compute/utility/source.hpp
@@ -0,0 +1,39 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_UTILITY_SOURCE_HPP
+#define BOOST_COMPUTE_UTILITY_SOURCE_HPP
+
+/// Stringizes OpenCL source code.
+///
+/// For example, to create a simple kernel which squares each input value:
+/// \code
+/// const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+/// __kernel void square(const float *input, float *output)
+/// {
+/// const uint i = get_global_id(0);
+/// const float x = input[i];
+/// output[i] = x * x;
+/// }
+/// );
+///
+/// // create and build square program
+/// program square_program = program::build_with_source(source, context);
+///
+/// // create square kernel
+/// kernel square_kernel(square_program, "square");
+/// \endcode
+#ifdef BOOST_COMPUTE_DOXYGEN_INVOKED
+#define BOOST_COMPUTE_STRINGIZE_SOURCE(source)
+#else
+#define BOOST_COMPUTE_STRINGIZE_SOURCE(...) #__VA_ARGS__
+#endif
+
+#endif // BOOST_COMPUTE_UTILITY_SOURCE_HPP
diff --git a/boost/compute/utility/wait_list.hpp b/boost/compute/utility/wait_list.hpp
new file mode 100644
index 0000000000..9a7e74bac0
--- /dev/null
+++ b/boost/compute/utility/wait_list.hpp
@@ -0,0 +1,203 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_UTILITY_WAIT_LIST_HPP
+#define BOOST_COMPUTE_UTILITY_WAIT_LIST_HPP
+
+#include <vector>
+
+#include <boost/compute/event.hpp>
+
+namespace boost {
+namespace compute {
+
+template<class T> class future;
+
+/// \class wait_list
+/// \brief Stores a list of events.
+///
+/// The wait_list class stores a set of event objects and can be used to
+/// specify dependencies for OpenCL operations or to wait on the host until
+/// all of the events have completed.
+///
+/// This class also provides convenience fnuctions for interacting with
+/// OpenCL APIs which typically accept event dependencies as a \c cl_event*
+/// pointer and a \c cl_uint size. For example:
+/// \code
+/// wait_list events = ...;
+///
+/// clEnqueueNDRangeKernel(..., events.get_event_ptr(), events.size(), ...);
+/// \endcode
+///
+/// \see event, \ref future "future<T>"
+class wait_list
+{
+public:
+ typedef std::vector<event>::iterator iterator;
+ typedef std::vector<event>::const_iterator const_iterator;
+
+ /// Creates an empty wait-list.
+ wait_list()
+ {
+ }
+
+ /// Creates a wait-list containing \p event.
+ wait_list(const event &event)
+ {
+ insert(event);
+ }
+
+ /// Creates a new wait-list as a copy of \p other.
+ wait_list(const wait_list &other)
+ : m_events(other.m_events)
+ {
+ }
+
+ /// Copies the events in the wait-list from \p other.
+ wait_list& operator=(const wait_list &other)
+ {
+ if(this != &other){
+ m_events = other.m_events;
+ }
+
+ return *this;
+ }
+
+ #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+ /// Move-constructs a new wait list object from \p other.
+ wait_list(wait_list&& other)
+ : m_events(std::move(other.m_events))
+ {
+ }
+
+ /// Move-assigns the wait list from \p other to \c *this.
+ wait_list& operator=(wait_list&& other)
+ {
+ m_events = std::move(other.m_events);
+
+ return *this;
+ }
+ #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+ /// Destroys the wait-list.
+ ~wait_list()
+ {
+ }
+
+ /// Returns \c true if the wait-list is empty.
+ bool empty() const
+ {
+ return m_events.empty();
+ }
+
+ /// Returns the number of events in the wait-list.
+ uint_ size() const
+ {
+ return static_cast<uint_>(m_events.size());
+ }
+
+ /// Removes all of the events from the wait-list.
+ void clear()
+ {
+ m_events.clear();
+ }
+
+ /// Returns a cl_event pointer to the first event in the wait-list.
+ /// Returns \c 0 if the wait-list is empty.
+ ///
+ /// This can be used to pass the wait-list to OpenCL functions which
+ /// expect a \c cl_event pointer to refer to a list of events.
+ const cl_event* get_event_ptr() const
+ {
+ if(empty()){
+ return 0;
+ }
+
+ return reinterpret_cast<const cl_event *>(&m_events[0]);
+ }
+
+ /// Reserves a minimum length of storage for the wait list object.
+ void reserve(size_t new_capacity) {
+ m_events.reserve(new_capacity);
+ }
+
+ /// Inserts \p event into the wait-list.
+ void insert(const event &event)
+ {
+ m_events.push_back(event);
+ }
+
+ /// Inserts the event from \p future into the wait-list.
+ template<class T>
+ void insert(const future<T> &future)
+ {
+ insert(future.get_event());
+ }
+
+ /// Blocks until all of the events in the wait-list have completed.
+ ///
+ /// Does nothing if the wait-list is empty.
+ void wait() const
+ {
+ if(!empty()){
+ BOOST_COMPUTE_ASSERT_CL_SUCCESS(
+ clWaitForEvents(size(), get_event_ptr())
+ );
+ }
+ }
+
+ /// Returns a reference to the event at specified location \p pos.
+ const event& operator[](size_t pos) const {
+ return m_events[pos];
+ }
+
+ /// Returns a reference to the event at specified location \p pos.
+ event& operator[](size_t pos) {
+ return m_events[pos];
+ }
+
+ /// Returns an iterator to the first element of the wait-list.
+ iterator begin() {
+ return m_events.begin();
+ }
+
+ /// Returns an iterator to the first element of the wait-list.
+ const_iterator begin() const {
+ return m_events.begin();
+ }
+
+ /// Returns an iterator to the first element of the wait-list.
+ const_iterator cbegin() const {
+ return m_events.begin();
+ }
+
+ /// Returns an iterator to the element following the last element of the wait-list.
+ iterator end() {
+ return m_events.end();
+ }
+
+ /// Returns an iterator to the element following the last element of the wait-list.
+ const_iterator end() const {
+ return m_events.end();
+ }
+
+ /// Returns an iterator to the element following the last element of the wait-list.
+ const_iterator cend() const {
+ return m_events.end();
+ }
+
+private:
+ std::vector<event> m_events;
+};
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_UTILITY_WAIT_LIST_HPP
diff --git a/boost/compute/version.hpp b/boost/compute/version.hpp
new file mode 100644
index 0000000000..fdf6caeeaf
--- /dev/null
+++ b/boost/compute/version.hpp
@@ -0,0 +1,18 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_VERSION_HPP
+#define BOOST_COMPUTE_VERSION_HPP
+
+#define BOOST_COMPUTE_VERSION_MAJOR 0
+#define BOOST_COMPUTE_VERSION_MINOR 5
+#define BOOST_COMPUTE_VERSION_PATCH 0
+
+#endif // BOOST_COMPUTE_VERSION_HPP
diff --git a/boost/compute/wait_list.hpp b/boost/compute/wait_list.hpp
new file mode 100644
index 0000000000..a6bda45991
--- /dev/null
+++ b/boost/compute/wait_list.hpp
@@ -0,0 +1,12 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@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
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+// deprecated, use <boost/compute/utility/wait_list.hpp> instead
+#include <boost/compute/utility/wait_list.hpp>
diff --git a/boost/config/compiler/clang.hpp b/boost/config/compiler/clang.hpp
index 5481e5ee62..01355bb7d5 100644
--- a/boost/config/compiler/clang.hpp
+++ b/boost/config/compiler/clang.hpp
@@ -57,16 +57,25 @@
#define BOOST_HAS_LONG_LONG
//
-// We disable this if the compiler is really nvcc as it
-// doesn't actually support __int128 as of CUDA_VERSION=5000
+// We disable this if the compiler is really nvcc with C++03 as it
+// doesn't actually support __int128 as of CUDA_VERSION=7500
// even though it defines __SIZEOF_INT128__.
// See https://svn.boost.org/trac/boost/ticket/10418
+// https://svn.boost.org/trac/boost/ticket/11852
// Only re-enable this for nvcc if you're absolutely sure
// of the circumstances under which it's supported.
// Similarly __SIZEOF_INT128__ is defined when targetting msvc
// compatibility even though the required support functions are absent.
//
-#if defined(__SIZEOF_INT128__) && !defined(__CUDACC__) && !defined(_MSC_VER)
+#if defined(__CUDACC__)
+# if defined(BOOST_GCC_CXX11)
+# define BOOST_NVCC_CXX11
+# else
+# define BOOST_NVCC_CXX03
+# endif
+#endif
+
+#if defined(__SIZEOF_INT128__) && !defined(BOOST_NVCC_CXX03) && !defined(_MSC_VER)
# define BOOST_HAS_INT128
#endif
diff --git a/boost/config/compiler/gcc.hpp b/boost/config/compiler/gcc.hpp
index d9dd59dc5f..fbd3dd9c19 100644
--- a/boost/config/compiler/gcc.hpp
+++ b/boost/config/compiler/gcc.hpp
@@ -133,14 +133,23 @@
//
// Recent GCC versions have __int128 when in 64-bit mode.
//
-// We disable this if the compiler is really nvcc as it
-// doesn't actually support __int128 as of CUDA_VERSION=5000
+// We disable this if the compiler is really nvcc with C++03 as it
+// doesn't actually support __int128 as of CUDA_VERSION=7500
// even though it defines __SIZEOF_INT128__.
// See https://svn.boost.org/trac/boost/ticket/8048
+// https://svn.boost.org/trac/boost/ticket/11852
// Only re-enable this for nvcc if you're absolutely sure
// of the circumstances under which it's supported:
//
-#if defined(__SIZEOF_INT128__) && !defined(__CUDACC__)
+#if defined(__CUDACC__)
+# if defined(BOOST_GCC_CXX11)
+# define BOOST_NVCC_CXX11
+# else
+# define BOOST_NVCC_CXX03
+# endif
+#endif
+
+#if defined(__SIZEOF_INT128__) && !defined(BOOST_NVCC_CXX03)
# define BOOST_HAS_INT128
#endif
//
@@ -148,12 +157,16 @@
// include a std lib header to detect this - not ideal, but we'll
// be including <cstddef> later anyway when we select the std lib.
//
+// Nevertheless, as of CUDA 7.5, using __float128 with the host
+// compiler in pre-C++11 mode is still not supported.
+// See https://svn.boost.org/trac/boost/ticket/11852
+//
#ifdef __cplusplus
#include <cstddef>
#else
#include <stddef.h>
#endif
-#if defined(_GLIBCXX_USE_FLOAT128) && !defined(__STRICT_ANSI__)
+#if defined(_GLIBCXX_USE_FLOAT128) && !defined(__STRICT_ANSI__) && !defined(BOOST_NVCC_CXX03)
# define BOOST_HAS_FLOAT128
#endif
diff --git a/boost/config/compiler/intel.hpp b/boost/config/compiler/intel.hpp
index 7789b94464..88ac023acc 100644
--- a/boost/config/compiler/intel.hpp
+++ b/boost/config/compiler/intel.hpp
@@ -514,7 +514,15 @@ template<> struct assert_intrinsic_wchar_t<unsigned short> {};
# define BOOST_HAS_STDINT_H
#endif
-#if defined(__LP64__) && defined(__GNUC__) && (BOOST_INTEL_CXX_VERSION >= 1310) && !defined(__CUDACC__)
+#if defined(__CUDACC__)
+# if defined(BOOST_GCC_CXX11)
+# define BOOST_NVCC_CXX11
+# else
+# define BOOST_NVCC_CXX03
+# endif
+#endif
+
+#if defined(__LP64__) && defined(__GNUC__) && (BOOST_INTEL_CXX_VERSION >= 1310) && !defined(BOOST_NVCC_CXX03)
# define BOOST_HAS_INT128
#endif
diff --git a/boost/config/compiler/nvcc.hpp b/boost/config/compiler/nvcc.hpp
index bbe81f6ee5..5a047070af 100644
--- a/boost/config/compiler/nvcc.hpp
+++ b/boost/config/compiler/nvcc.hpp
@@ -14,3 +14,11 @@
// NVIDIA Specific support
// BOOST_GPU_ENABLED : Flag a function or a method as being enabled on the host and device
#define BOOST_GPU_ENABLED __host__ __device__
+
+// A bug in version 7.0 of CUDA prevents use of variadic templates in some occasions
+// https://svn.boost.org/trac/boost/ticket/11897
+// This is fixed in 7.5. As the following version macro was introduced in 7.5 an existance
+// check is enough to detect versions < 7.5
+#if !defined(__CUDACC_VER__) || (__CUDACC_VER__ < 70500)
+# define BOOST_NO_CXX11_VARIADIC_TEMPLATES
+#endif
diff --git a/boost/config/stdlib/libcpp.hpp b/boost/config/stdlib/libcpp.hpp
index ab5d123544..645bb63bfc 100644
--- a/boost/config/stdlib/libcpp.hpp
+++ b/boost/config/stdlib/libcpp.hpp
@@ -53,19 +53,27 @@
# define BOOST_NO_CXX11_HDR_FUNCTIONAL
# define BOOST_NO_CXX11_STD_ALIGN
# define BOOST_NO_CXX11_ADDRESSOF
-#endif
-
+# define BOOST_NO_CXX11_HDR_ATOMIC
+# define BOOST_NO_CXX11_ATOMIC_SMART_PTR
+# define BOOST_NO_CXX11_HDR_CHRONO
+# define BOOST_NO_CXX11_HDR_TYPE_TRAITS
+# define BOOST_NO_CXX11_HDR_FUTURE
+#elif _LIBCPP_VERSION < 3700
//
// These appear to be unusable/incomplete so far:
//
+# define BOOST_NO_CXX11_HDR_ATOMIC
+# define BOOST_NO_CXX11_ATOMIC_SMART_PTR
# define BOOST_NO_CXX11_HDR_CHRONO
-# define BOOST_NO_CXX11_HDR_FUTURE
# define BOOST_NO_CXX11_HDR_TYPE_TRAITS
-# define BOOST_NO_CXX11_ATOMIC_SMART_PTR
-# define BOOST_NO_CXX11_HDR_ATOMIC
+# define BOOST_NO_CXX11_HDR_FUTURE
+#endif
+
+#if _LIBCPP_VERSION < 3700
// libc++ uses a non-standard messages_base
#define BOOST_NO_STD_MESSAGES
+#endif
#if defined(__has_include)
#if !__has_include(<shared_mutex>)
diff --git a/boost/container/allocator_traits.hpp b/boost/container/allocator_traits.hpp
index b515af6180..e6a882e594 100644
--- a/boost/container/allocator_traits.hpp
+++ b/boost/container/allocator_traits.hpp
@@ -77,6 +77,9 @@ namespace container {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+template<class Allocator>
+class small_vector_allocator;
+
namespace allocator_traits_detail {
BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_max_size, max_size)
@@ -96,6 +99,10 @@ 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< std::allocator<T> > >
+{ static const bool value = true; };
+
template<class Allocator>
struct is_not_std_allocator
{ static const bool value = !is_std_allocator<Allocator>::value; };
diff --git a/boost/container/deque.hpp b/boost/container/deque.hpp
index f53f34ae98..fef28a124f 100644
--- a/boost/container/deque.hpp
+++ b/boost/container/deque.hpp
@@ -619,8 +619,18 @@ class deque : protected deque_base<Allocator>
//! throws or T's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to n.
- deque(size_type n, const value_type& value,
- const allocator_type& a = allocator_type())
+ deque(size_type n, const value_type& value)
+ : Base(n, allocator_type())
+ { this->priv_fill_initialize(value); }
+
+ //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a
+ //! and inserts n copies of value.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ deque(size_type n, const value_type& value, const allocator_type& a)
: Base(n, a)
{ this->priv_fill_initialize(value); }
@@ -632,11 +642,29 @@ class deque : protected deque_base<Allocator>
//!
//! <b>Complexity</b>: Linear to the range [first, last).
template <class InIt>
- deque(InIt first, InIt last, const allocator_type& a = allocator_type()
+ deque(InIt first, InIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- , typename container_detail::enable_if_c
- < !container_detail::is_convertible<InIt, size_type>::value
- >::type * = 0
+ , typename container_detail::disable_if_convertible
+ <InIt, size_type>::type * = 0
+ #endif
+ )
+ : Base(allocator_type())
+ {
+ this->priv_range_initialize(first, last);
+ }
+
+ //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a
+ //! and inserts a copy of the range [first, last) in the deque.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's constructor taking a dereferenced InIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to the range [first, last).
+ template <class InIt>
+ deque(InIt first, InIt last, const allocator_type& a
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::disable_if_convertible
+ <InIt, size_type>::type * = 0
#endif
)
: Base(a)
diff --git a/boost/container/detail/config_begin.hpp b/boost/container/detail/config_begin.hpp
index 7e3e03fa64..4df9e35d8b 100644
--- a/boost/container/detail/config_begin.hpp
+++ b/boost/container/detail/config_begin.hpp
@@ -45,7 +45,9 @@
#pragma warning (disable : 4702) // unreachable code
#pragma warning (disable : 4706) // assignment within conditional expression
#pragma warning (disable : 4710) // function not inlined
+ #pragma warning (disable : 4714) // "function": marked as __forceinline not inlined
#pragma warning (disable : 4711) // function selected for automatic inline expansion
#pragma warning (disable : 4786) // identifier truncated in debug info
#pragma warning (disable : 4996) // "function": was declared deprecated
+
#endif //BOOST_MSVC
diff --git a/boost/container/detail/iterators.hpp b/boost/container/detail/iterators.hpp
index e8cfcf97a4..32ff32f362 100644
--- a/boost/container/detail/iterators.hpp
+++ b/boost/container/detail/iterators.hpp
@@ -377,7 +377,7 @@ class default_init_construct_iterator
template <class T, class Difference = std::ptrdiff_t>
class repeat_iterator
: public ::boost::container::iterator
- <std::random_access_iterator_tag, T, Difference>
+ <std::random_access_iterator_tag, T, Difference, T*, T&>
{
typedef repeat_iterator<T, Difference> this_type;
public:
@@ -493,13 +493,13 @@ class emplace_iterator
public:
typedef Difference difference_type;
- explicit emplace_iterator(EmplaceFunctor&e)
+ BOOST_CONTAINER_FORCEINLINE explicit emplace_iterator(EmplaceFunctor&e)
: m_num(1), m_pe(&e){}
- emplace_iterator()
+ BOOST_CONTAINER_FORCEINLINE emplace_iterator()
: m_num(0), m_pe(0){}
- this_type& operator++()
+ BOOST_CONTAINER_FORCEINLINE this_type& operator++()
{ increment(); return *this; }
this_type operator++(int)
@@ -509,7 +509,7 @@ class emplace_iterator
return result;
}
- this_type& operator--()
+ BOOST_CONTAINER_FORCEINLINE this_type& operator--()
{ decrement(); return *this; }
this_type operator--(int)
@@ -519,29 +519,29 @@ class emplace_iterator
return result;
}
- friend bool operator== (const this_type& i, const this_type& i2)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator== (const this_type& i, const this_type& i2)
{ return i.equal(i2); }
- friend bool operator!= (const this_type& i, const this_type& i2)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator!= (const this_type& i, const this_type& i2)
{ return !(i == i2); }
- friend bool operator< (const this_type& i, const this_type& i2)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator< (const this_type& i, const this_type& i2)
{ return i.less(i2); }
- friend bool operator> (const this_type& i, const this_type& i2)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator> (const this_type& i, const this_type& i2)
{ return i2 < i; }
- friend bool operator<= (const this_type& i, const this_type& i2)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator<= (const this_type& i, const this_type& i2)
{ return !(i > i2); }
- friend bool operator>= (const this_type& i, const this_type& i2)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator>= (const this_type& i, const this_type& i2)
{ return !(i < i2); }
- friend difference_type operator- (const this_type& i, const this_type& i2)
+ BOOST_CONTAINER_FORCEINLINE friend difference_type operator- (const this_type& i, const this_type& i2)
{ return i2.distance_to(i); }
//Arithmetic
- this_type& operator+=(difference_type off)
+ BOOST_CONTAINER_FORCEINLINE this_type& operator+=(difference_type off)
{ this->advance(off); return *this; }
this_type operator+(difference_type off) const
@@ -551,13 +551,13 @@ class emplace_iterator
return other;
}
- friend this_type operator+(difference_type off, const this_type& right)
+ BOOST_CONTAINER_FORCEINLINE friend this_type operator+(difference_type off, const this_type& right)
{ return right + off; }
- this_type& operator-=(difference_type off)
+ BOOST_CONTAINER_FORCEINLINE this_type& operator-=(difference_type off)
{ this->advance(-off); return *this; }
- this_type operator-(difference_type off) const
+ BOOST_CONTAINER_FORCEINLINE this_type operator-(difference_type off) const
{ return *this + (-off); }
//This pseudo-iterator's dereference operations have no sense since value is not
@@ -575,28 +575,28 @@ class emplace_iterator
difference_type m_num;
EmplaceFunctor * m_pe;
- void increment()
+ BOOST_CONTAINER_FORCEINLINE void increment()
{ --m_num; }
- void decrement()
+ BOOST_CONTAINER_FORCEINLINE void decrement()
{ ++m_num; }
- bool equal(const this_type &other) const
+ BOOST_CONTAINER_FORCEINLINE bool equal(const this_type &other) const
{ return m_num == other.m_num; }
- bool less(const this_type &other) const
+ BOOST_CONTAINER_FORCEINLINE bool less(const this_type &other) const
{ return other.m_num < m_num; }
- const T & dereference() const
+ BOOST_CONTAINER_FORCEINLINE const T & dereference() const
{
static T dummy;
return dummy;
}
- void advance(difference_type n)
+ BOOST_CONTAINER_FORCEINLINE void advance(difference_type n)
{ m_num -= n; }
- difference_type distance_to(const this_type &other)const
+ BOOST_CONTAINER_FORCEINLINE difference_type distance_to(const this_type &other)const
{ return difference_type(m_num - other.m_num); }
};
@@ -616,7 +616,7 @@ struct emplace_functor
{ emplace_functor::inplace_impl(a, ptr, index_tuple_t()); }
template<class Allocator, class T, int ...IdxPack>
- void inplace_impl(Allocator &a, T* ptr, const container_detail::index_tuple<IdxPack...>&)
+ BOOST_CONTAINER_FORCEINLINE void inplace_impl(Allocator &a, T* ptr, const container_detail::index_tuple<IdxPack...>&)
{
allocator_traits<Allocator>::construct
(a, ptr, ::boost::forward<Args>(container_detail::get<IdxPack>(args_))...);
@@ -762,54 +762,54 @@ class iterator_from_iiterator
typedef typename types_t::iterator_category iterator_category;
typedef typename types_t::value_type value_type;
- iterator_from_iiterator()
+ BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator()
{}
- explicit iterator_from_iiterator(IIterator iit) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE explicit iterator_from_iiterator(IIterator iit) BOOST_NOEXCEPT_OR_NOTHROW
: m_iit(iit)
{}
- iterator_from_iiterator(iterator_from_iiterator<IIterator, false> const& other) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator(iterator_from_iiterator<IIterator, false> const& other) BOOST_NOEXCEPT_OR_NOTHROW
: m_iit(other.get())
{}
- iterator_from_iiterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
{ ++this->m_iit; return *this; }
- iterator_from_iiterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
{
iterator_from_iiterator result (*this);
++this->m_iit;
return result;
}
- iterator_from_iiterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
{
//If the iterator_from_iiterator is not a bidirectional iterator, operator-- should not exist
BOOST_STATIC_ASSERT((is_bidirectional_iterator<iterator_from_iiterator>::value));
--this->m_iit; return *this;
}
- iterator_from_iiterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW
{
iterator_from_iiterator result (*this);
--this->m_iit;
return result;
}
- friend bool operator== (const iterator_from_iiterator& l, const iterator_from_iiterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE friend bool operator== (const iterator_from_iiterator& l, const iterator_from_iiterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return l.m_iit == r.m_iit; }
- friend bool operator!= (const iterator_from_iiterator& l, const iterator_from_iiterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE friend bool operator!= (const iterator_from_iiterator& l, const iterator_from_iiterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return !(l == r); }
- reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
{ return this->m_iit->get_data(); }
- pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
{ return ::boost::intrusive::pointer_traits<pointer>::pointer_to(this->operator*()); }
- const IIterator &get() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const IIterator &get() const BOOST_NOEXCEPT_OR_NOTHROW
{ return this->m_iit; }
private:
diff --git a/boost/container/detail/node_alloc_holder.hpp b/boost/container/detail/node_alloc_holder.hpp
index 3b632a677d..1b7c4d76dc 100644
--- a/boost/container/detail/node_alloc_holder.hpp
+++ b/boost/container/detail/node_alloc_holder.hpp
@@ -60,14 +60,17 @@ struct node_alloc_holder
{
//If the intrusive container is an associative container, obtain the predicate, which will
//be of type node_compare<>. If not an associative container value_compare will be a "nat" type.
- typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, ICont,
- value_compare, container_detail::nat) intrusive_value_compare;
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
+ ( boost::container::container_detail::
+ , ICont, value_compare, container_detail::nat) intrusive_value_compare;
//In that case obtain the value predicate from the node predicate via predicate_type
//if intrusive_value_compare is node_compare<>, nat otherwise
- typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, intrusive_value_compare,
- predicate_type, container_detail::nat) value_compare;
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
+ ( boost::container::container_detail::
+ , intrusive_value_compare
+ , predicate_type, container_detail::nat) value_compare;
- typedef allocator_traits<Allocator> allocator_traits_type;
+ typedef allocator_traits<Allocator> allocator_traits_type;
typedef typename allocator_traits_type::value_type value_type;
typedef ICont intrusive_container;
typedef typename ICont::value_type Node;
@@ -75,19 +78,19 @@ struct node_alloc_holder
portable_rebind_alloc<Node>::type NodeAlloc;
typedef allocator_traits<NodeAlloc> node_allocator_traits_type;
typedef container_detail::allocator_version_traits<NodeAlloc> node_allocator_version_traits_type;
- typedef Allocator ValAlloc;
+ typedef Allocator ValAlloc;
typedef typename node_allocator_traits_type::pointer NodePtr;
typedef container_detail::scoped_deallocator<NodeAlloc> Deallocator;
typedef typename node_allocator_traits_type::size_type size_type;
typedef typename node_allocator_traits_type::difference_type difference_type;
typedef container_detail::integral_constant<unsigned,
boost::container::container_detail::
- version<NodeAlloc>::value> alloc_version;
- typedef typename ICont::iterator icont_iterator;
- typedef typename ICont::const_iterator icont_citerator;
- typedef allocator_destroyer<NodeAlloc> Destroyer;
- typedef allocator_traits<NodeAlloc> NodeAllocTraits;
- typedef allocator_version_traits<NodeAlloc> AllocVersionTraits;
+ version<NodeAlloc>::value> alloc_version;
+ typedef typename ICont::iterator icont_iterator;
+ typedef typename ICont::const_iterator icont_citerator;
+ typedef allocator_destroyer<NodeAlloc> Destroyer;
+ typedef allocator_traits<NodeAlloc> NodeAllocTraits;
+ typedef allocator_version_traits<NodeAlloc> AllocVersionTraits;
private:
BOOST_COPYABLE_AND_MOVABLE(node_alloc_holder)
@@ -208,6 +211,29 @@ struct node_alloc_holder
return (p);
}
+ template<class KeyConvertible>
+ NodePtr create_node_from_key(BOOST_FWD_REF(KeyConvertible) key)
+ {
+ NodePtr p = this->allocate_one();
+ NodeAlloc &na = this->node_alloc();
+ Deallocator node_deallocator(p, this->node_alloc());
+ node_allocator_traits_type::construct
+ (na, container_detail::addressof(p->m_data.first), boost::forward<KeyConvertible>(key));
+ BOOST_TRY{
+ node_allocator_traits_type::construct(na, container_detail::addressof(p->m_data.second));
+ }
+ BOOST_CATCH(...){
+ node_allocator_traits_type::destroy(na, container_detail::addressof(p->m_data.first));
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ node_deallocator.release();
+ //This does not throw
+ typedef typename Node::hook_type hook_type;
+ ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;
+ return (p);
+ }
+
void destroy_node(const NodePtr &nodep)
{
allocator_traits<NodeAlloc>::destroy(this->node_alloc(), container_detail::to_raw_pointer(nodep));
diff --git a/boost/container/detail/pair.hpp b/boost/container/detail/pair.hpp
index 17766f35cb..134760e1e6 100644
--- a/boost/container/detail/pair.hpp
+++ b/boost/container/detail/pair.hpp
@@ -317,6 +317,16 @@ struct is_class_or_union< ::boost::container::container_detail::pair<T1, T2> >
static const bool value = true;
};
+template <class T1, class T2>
+struct is_class_or_union< std::pair<T1, T2> >
+//This specialization is needed to avoid instantiation of pair in
+//is_class, and allow recursive maps.
+{
+ static const bool value = true;
+};
+
+
+
} //namespace move_detail{
diff --git a/boost/container/detail/tree.hpp b/boost/container/detail/tree.hpp
index c2d6b1d17d..0fd6097650 100644
--- a/boost/container/detail/tree.hpp
+++ b/boost/container/detail/tree.hpp
@@ -50,6 +50,7 @@
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#include <boost/move/detail/fwd_macros.hpp>
#endif
+#include <boost/move/detail/move_helpers.hpp>
// other
#include <boost/core/no_exceptions_support.hpp>
@@ -136,13 +137,13 @@ struct tree_node
typedef tree_node< T, VoidPointer
, tree_type_value, OptimizeSize> node_type;
- T &get_data()
+ BOOST_CONTAINER_FORCEINLINE T &get_data()
{
T* ptr = reinterpret_cast<T*>(&this->m_data);
return *ptr;
}
- const T &get_data() const
+ BOOST_CONTAINER_FORCEINLINE const T &get_data() const
{
const T* ptr = reinterpret_cast<const T*>(&this->m_data);
return *ptr;
@@ -151,39 +152,39 @@ struct tree_node
internal_type m_data;
template<class T1, class T2>
- void do_assign(const std::pair<const T1, T2> &p)
+ BOOST_CONTAINER_FORCEINLINE void do_assign(const std::pair<const T1, T2> &p)
{
const_cast<T1&>(m_data.first) = p.first;
m_data.second = p.second;
}
template<class T1, class T2>
- void do_assign(const pair<const T1, T2> &p)
+ BOOST_CONTAINER_FORCEINLINE void do_assign(const pair<const T1, T2> &p)
{
const_cast<T1&>(m_data.first) = p.first;
m_data.second = p.second;
}
template<class V>
- void do_assign(const V &v)
+ BOOST_CONTAINER_FORCEINLINE void do_assign(const V &v)
{ m_data = v; }
template<class T1, class T2>
- void do_move_assign(std::pair<const T1, T2> &p)
+ BOOST_CONTAINER_FORCEINLINE void do_move_assign(std::pair<const T1, T2> &p)
{
const_cast<T1&>(m_data.first) = ::boost::move(p.first);
m_data.second = ::boost::move(p.second);
}
template<class T1, class T2>
- void do_move_assign(pair<const T1, T2> &p)
+ BOOST_CONTAINER_FORCEINLINE void do_move_assign(pair<const T1, T2> &p)
{
const_cast<T1&>(m_data.first) = ::boost::move(p.first);
m_data.second = ::boost::move(p.second);
}
template<class V>
- void do_move_assign(V &v)
+ BOOST_CONTAINER_FORCEINLINE void do_move_assign(V &v)
{ m_data = ::boost::move(v); }
};
@@ -526,12 +527,12 @@ class tree
const const_iterator end_it(this->cend());
if(unique_insertion){
for ( ; first != last; ++first){
- this->insert_unique(end_it, *first);
+ this->insert_unique_convertible(end_it, *first);
}
}
else{
for ( ; first != last; ++first){
- this->insert_equal(end_it, *first);
+ this->insert_equal_convertible(end_it, *first);
}
}
}
@@ -555,7 +556,7 @@ class tree
//for the constructor
const const_iterator end_it(this->cend());
for ( ; first != last; ++first){
- this->insert_unique(end_it, *first);
+ this->insert_unique_convertible(end_it, *first);
}
}
else{
@@ -983,19 +984,8 @@ class tree
#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- iterator insert_unique(const_iterator hint, const value_type& v)
- {
- BOOST_ASSERT((priv_is_linked)(hint));
- insert_commit_data data;
- std::pair<iterator,bool> ret =
- this->insert_unique_check(hint, KeyOfValue()(v), data);
- if(!ret.second)
- return ret.first;
- return this->insert_unique_commit(v, data);
- }
-
template<class MovableConvertible>
- iterator insert_unique(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v)
+ iterator insert_unique_convertible(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v)
{
BOOST_ASSERT((priv_is_linked)(hint));
insert_commit_data data;
@@ -1006,6 +996,8 @@ class tree
return this->insert_unique_commit(boost::forward<MovableConvertible>(v), data);
}
+ BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_unique, value_type, iterator, this->insert_unique_convertible, const_iterator, const_iterator)
+
template <class InputIterator>
void insert_unique(InputIterator first, InputIterator last)
{
@@ -1032,18 +1024,8 @@ class tree
return ret;
}
- iterator insert_equal(const_iterator hint, const value_type& v)
- {
- BOOST_ASSERT((priv_is_linked)(hint));
- NodePtr tmp(AllocHolder::create_node(v));
- scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
- iterator ret(this->icont().insert_equal(hint.get(), *tmp));
- destroy_deallocator.release();
- return ret;
- }
-
template<class MovableConvertible>
- iterator insert_equal(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v)
+ iterator insert_equal_convertible(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v)
{
BOOST_ASSERT((priv_is_linked)(hint));
NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(v)));
@@ -1053,6 +1035,8 @@ class tree
return ret;
}
+ BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_equal, value_type, iterator, this->insert_equal_convertible, const_iterator, const_iterator)
+
template <class InputIterator>
void insert_equal(InputIterator first, InputIterator last)
{
@@ -1060,6 +1044,29 @@ class tree
this->insert_equal(*first);
}
+ template<class KeyConvertible>
+ iterator insert_from_key(BOOST_FWD_REF(KeyConvertible) key)
+ {
+ insert_commit_data data;
+ const key_type & k = key; //Support emulated rvalue references
+ std::pair<iiterator, bool> ret =
+ this->icont().insert_unique_check(k, KeyNodeCompare(value_comp()), data);
+ return ret.second
+ ? this->insert_unique_key_commit(boost::forward<KeyConvertible>(key), data)
+ : iterator(ret.first);
+ }
+
+ template<class KeyConvertible>
+ iterator insert_unique_key_commit
+ (BOOST_FWD_REF(KeyConvertible) key, insert_commit_data &data)
+ {
+ NodePtr tmp = AllocHolder::create_node_from_key(boost::forward<KeyConvertible>(key));
+ scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
+ iterator ret(this->icont().insert_unique_commit(*tmp, data));
+ destroy_deallocator.release();
+ return ret;
+ }
+
iterator erase(const_iterator position)
{
BOOST_ASSERT(position != this->cend() && (priv_is_linked)(position));
diff --git a/boost/container/detail/workaround.hpp b/boost/container/detail/workaround.hpp
index e1f6156964..ae9151c32d 100644
--- a/boost/container/detail/workaround.hpp
+++ b/boost/container/detail/workaround.hpp
@@ -76,4 +76,17 @@
#define BOOST_CONTAINER_DECL
#endif /* DYN_LINK */
+//#define BOOST_CONTAINER_DISABLE_FORCEINLINE
+
+#if defined(BOOST_CONTAINER_DISABLE_FORCEINLINE)
+ #define BOOST_CONTAINER_FORCEINLINE inline
+#elif defined(BOOST_CONTAINER_FORCEINLINE_IS_BOOST_FORCELINE)
+ #define BOOST_CONTAINER_FORCEINLINE BOOST_FORCEINLINE
+#elif defined(BOOST_MSVC) && defined(_DEBUG)
+ //"__forceinline" and MSVC seems to have some bugs in debug mode
+ #define BOOST_CONTAINER_FORCEINLINE inline
+#else
+ #define BOOST_CONTAINER_FORCEINLINE BOOST_FORCEINLINE
+#endif
+
#endif //#ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
diff --git a/boost/container/map.hpp b/boost/container/map.hpp
index 8173181221..87cc183c8e 100644
--- a/boost/container/map.hpp
+++ b/boost/container/map.hpp
@@ -596,7 +596,7 @@ class map
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
iterator insert(const_iterator p, BOOST_RV_REF(nonconst_value_type) x)
- { return this->base_t::insert_unique(p, boost::move(x)); }
+ { return this->base_t::insert_unique_convertible(p, boost::move(x)); }
//! <b>Effects</b>: Move constructs a new value from x if and only if there is
//! no element in the container with key equivalent to the key of x.
@@ -608,7 +608,7 @@ class map
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x)
- { return this->base_t::insert_unique(p, boost::move(x)); }
+ { return this->base_t::insert_unique_convertible(p, boost::move(x)); }
//! <b>Effects</b>: Inserts a copy of x in the container.
//! p is a hint pointing to where the insert should start to search.
@@ -617,7 +617,7 @@ class map
//!
//! <b>Complexity</b>: Logarithmic.
iterator insert(const_iterator p, const nonconst_value_type& x)
- { return this->base_t::insert_unique(p, x); }
+ { return this->base_t::insert_unique_convertible(p, x); }
//! <b>Effects</b>: Inserts an element move constructed from x in the container.
//! p is a hint pointing to where the insert should start to search.
@@ -847,31 +847,10 @@ class map
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
- mapped_type& priv_subscript(const key_type &k)
+ template<class KeyConvertible>
+ mapped_type& priv_subscript(BOOST_FWD_REF(KeyConvertible) k)
{
- //we can optimize this
- iterator i = this->lower_bound(k);
- // i->first is greater than or equivalent to k.
- if (i == this->end() || this->key_comp()(k, (*i).first)){
- container_detail::value_init<mapped_type> m;
- movable_value_type val(k, boost::move(m.m_t));
- i = insert(i, boost::move(val));
- }
- return (*i).second;
- }
-
- mapped_type& priv_subscript(BOOST_RV_REF(key_type) mk)
- {
- key_type &k = mk;
- //we can optimize this
- iterator i = this->lower_bound(k);
- // i->first is greater than or equivalent to k.
- if (i == this->end() || this->key_comp()(k, (*i).first)){
- container_detail::value_init<mapped_type> m;
- movable_value_type val(boost::move(k), boost::move(m.m_t));
- i = insert(i, boost::move(val));
- }
- return (*i).second;
+ return this->insert_from_key(boost::forward<KeyConvertible>(k))->second;
}
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -1312,7 +1291,7 @@ class multimap
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
iterator insert(const_iterator p, const nonconst_value_type& x)
- { return this->base_t::insert_equal(p, x); }
+ { return this->base_t::insert_equal_convertible(p, x); }
//! <b>Effects</b>: Inserts a new value move constructed from x in the container.
//! p is a hint pointing to where the insert should start to search.
@@ -1323,7 +1302,7 @@ class multimap
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
iterator insert(const_iterator p, BOOST_RV_REF(nonconst_value_type) x)
- { return this->base_t::insert_equal(p, boost::move(x)); }
+ { return this->base_t::insert_equal_convertible(p, boost::move(x)); }
//! <b>Effects</b>: Inserts a new value move constructed from x in the container.
//! p is a hint pointing to where the insert should start to search.
@@ -1334,7 +1313,7 @@ class multimap
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x)
- { return this->base_t::insert_equal(p, boost::move(x)); }
+ { return this->base_t::insert_equal_convertible(p, boost::move(x)); }
//! <b>Requires</b>: first, last are not iterators into *this.
//!
diff --git a/boost/container/small_vector.hpp b/boost/container/small_vector.hpp
index 4dab684764..9759d2fa0e 100644
--- a/boost/container/small_vector.hpp
+++ b/boost/container/small_vector.hpp
@@ -91,10 +91,10 @@ class small_vector_allocator
BOOST_COPYABLE_AND_MOVABLE(small_vector_allocator)
- const Allocator &as_base() const
+ BOOST_CONTAINER_FORCEINLINE const Allocator &as_base() const
{ return static_cast<const Allocator&>(*this); }
- Allocator &as_base()
+ BOOST_CONTAINER_FORCEINLINE Allocator &as_base()
{ return static_cast<Allocator&>(*this); }
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -135,13 +135,13 @@ class small_vector_allocator
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//!Constructor from arbitrary arguments
template<class ...Args>
- explicit small_vector_allocator(BOOST_FWD_REF(Args) ...args)
+ BOOST_CONTAINER_FORCEINLINE explicit small_vector_allocator(BOOST_FWD_REF(Args) ...args)
: Allocator(::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 \
- explicit small_vector_allocator(BOOST_MOVE_UREF##N)\
+ BOOST_CONTAINER_FORCEINLINE explicit small_vector_allocator(BOOST_MOVE_UREF##N)\
: Allocator(BOOST_MOVE_FWD##N)\
{}\
//
@@ -151,54 +151,62 @@ class small_vector_allocator
//!Constructor from other small_vector_allocator.
//!Never throws
- small_vector_allocator(const small_vector_allocator &other) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE small_vector_allocator
+ (const small_vector_allocator &other) BOOST_NOEXCEPT_OR_NOTHROW
: Allocator(other.as_base())
{}
//!Move constructor from small_vector_allocator.
//!Never throws
- small_vector_allocator(BOOST_RV_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE small_vector_allocator
+ (BOOST_RV_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW
: Allocator(::boost::move(other.as_base()))
{}
//!Constructor from related small_vector_allocator.
//!Never throws
template<class OtherAllocator>
- small_vector_allocator(const small_vector_allocator<OtherAllocator> &other) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE small_vector_allocator
+ (const small_vector_allocator<OtherAllocator> &other) BOOST_NOEXCEPT_OR_NOTHROW
: Allocator(other.as_base())
{}
//!Move constructor from related small_vector_allocator.
//!Never throws
template<class OtherAllocator>
- small_vector_allocator(BOOST_RV_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE small_vector_allocator
+ (BOOST_RV_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW
: Allocator(::boost::move(other.as_base()))
{}
//!Assignment from other small_vector_allocator.
//!Never throws
- small_vector_allocator & operator=(BOOST_COPY_ASSIGN_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW
+ 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::operator=(other.as_base())); }
//!Move constructor from other small_vector_allocator.
//!Never throws
- small_vector_allocator & operator=(BOOST_RV_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE small_vector_allocator &
+ operator=(BOOST_RV_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW
{ return static_cast<small_vector_allocator&>(this->Allocator::operator=(::boost::move(other.as_base()))); }
//!Assignment from related small_vector_allocator.
//!Never throws
template<class OtherAllocator>
- small_vector_allocator & operator=(BOOST_COPY_ASSIGN_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE small_vector_allocator &
+ operator=(BOOST_COPY_ASSIGN_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW
{ return static_cast<small_vector_allocator&>(this->Allocator::operator=(other.as_base())); }
//!Move assignment from related small_vector_allocator.
//!Never throws
template<class OtherAllocator>
- small_vector_allocator & operator=(BOOST_RV_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE small_vector_allocator &
+ operator=(BOOST_RV_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW
{ return static_cast<small_vector_allocator&>(this->Allocator::operator=(::boost::move(other.as_base()))); }
//!Allocates storage from the standard-conforming allocator
- pointer allocate(size_type count, const_void_pointer hint = const_void_pointer())
+ 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); }
//!Deallocates previously allocated memory.
@@ -211,7 +219,7 @@ class small_vector_allocator
//!Returns the maximum number of elements that could be allocated.
//!Never throws
- size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
{ return allocator_traits_type::max_size(this->as_base()); }
small_vector_allocator select_on_container_copy_construction() const
@@ -222,17 +230,17 @@ class small_vector_allocator
//!Swaps two allocators, does nothing
//!because this small_vector_allocator is stateless
- friend void swap(small_vector_allocator &l, small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE friend void swap(small_vector_allocator &l, small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW
{ boost::adl_move_swap(l.as_base(), r.as_base()); }
//!An small_vector_allocator always compares to true, as memory allocated with one
//!instance can be deallocated by another instance (except for unpropagable storage)
- friend bool operator==(const small_vector_allocator &l, const small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE friend bool operator==(const small_vector_allocator &l, const small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW
{ return allocator_traits_type::equal(l.as_base(), r.as_base()); }
//!An small_vector_allocator always compares to false, as memory allocated with one
//!instance can be deallocated by another instance
- friend bool operator!=(const small_vector_allocator &l, const small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const small_vector_allocator &l, const small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW
{ return !(l == r); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -268,7 +276,7 @@ class small_vector_allocator
using Allocator::allocate_many;
using Allocator::deallocate_many;*/
- bool is_internal_storage(pointer p) const
+ BOOST_CONTAINER_FORCEINLINE bool is_internal_storage(pointer p) const
{ return this->internal_storage() == p; }
pointer internal_storage() const
@@ -287,7 +295,7 @@ class small_vector_allocator
};
//! This class consists of common code from all small_vector<T, N> types that don't depend on the
-//! "N" template parameter. This class is non-copyable and non-destructible, so this class tipically
+//! "N" template parameter. This class is non-copyable and non-destructible, so this class typically
//! used as reference argument to functions that read or write small vectors. Since `small_vector<T, N>`
//! derives from `small_vector_base<T>`, the conversion to `small_vector_base` is implicit
//! <pre>
@@ -295,7 +303,7 @@ class small_vector_allocator
//! //Clients can pass any small_vector<Foo, N>.
//! void read_any_small_vector_of_foo(const small_vector_base<Foo> &in_parameter);
//!
-//! void modify_any_small_vector_of_foo(small_vector_base<Foo> &out_parameter);
+//! void modify_any_small_vector_of_foo(small_vector_base<Foo> &in_out_parameter);
//!
//! void some_function()
//! {
@@ -344,19 +352,16 @@ class small_vector_base
protected:
typedef typename base_type::initial_capacity_t initial_capacity_t;
- explicit small_vector_base(initial_capacity_t, std::size_t initial_capacity)
+ BOOST_CONTAINER_FORCEINLINE explicit small_vector_base(initial_capacity_t, std::size_t initial_capacity)
: base_type(initial_capacity_t(), this->internal_storage(), initial_capacity)
{}
template<class AllocFwd>
- explicit small_vector_base(initial_capacity_t, std::size_t capacity, BOOST_FWD_REF(AllocFwd) a)
+ BOOST_CONTAINER_FORCEINLINE explicit small_vector_base(initial_capacity_t, std::size_t capacity, BOOST_FWD_REF(AllocFwd) a)
: base_type(initial_capacity_t(), this->internal_storage(), capacity, ::boost::forward<AllocFwd>(a))
{}
- ~small_vector_base(){}
-
- using base_type::is_propagable_from;
- using base_type::steal_resources;
+ //~small_vector_base(){}
private:
//The only member
@@ -365,14 +370,29 @@ class small_vector_base
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
- small_vector_base& operator=(BOOST_COPY_ASSIGN_REF(small_vector_base) other)
+ BOOST_CONTAINER_FORCEINLINE small_vector_base& operator=(BOOST_COPY_ASSIGN_REF(small_vector_base) other)
{ return static_cast<small_vector_base&>(this->base_type::operator=(static_cast<base_type const&>(other))); }
- small_vector_base& operator=(BOOST_RV_REF(small_vector_base) other)
+ BOOST_CONTAINER_FORCEINLINE small_vector_base& operator=(BOOST_RV_REF(small_vector_base) other)
{ return static_cast<small_vector_base&>(this->base_type::operator=(BOOST_MOVE_BASE(base_type, other))); }
- void swap(small_vector_base &other)
+ BOOST_CONTAINER_FORCEINLINE void swap(small_vector_base &other)
{ return this->base_type::swap(other); }
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ protected:
+ void move_construct_impl(base_type &x, const allocator_type &a)
+ {
+ if(base_type::is_propagable_from(x.get_stored_allocator(), x.data(), a, true)){
+ this->steal_resources(x);
+ }
+ else{
+ this->assign( boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.begin()))
+ , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.end ()))
+ );
+ }
+ }
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -477,76 +497,110 @@ class small_vector : public small_vector_base<T, Allocator>
typedef typename base_type::size_type size_type;
typedef typename base_type::value_type value_type;
- static std::size_t internal_capacity()
+ BOOST_CONTAINER_FORCEINLINE static std::size_t internal_capacity()
{ return (sizeof(small_vector) - storage_test::s_start)/sizeof(T); }
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
- small_vector()
+ BOOST_CONTAINER_FORCEINLINE small_vector()
: base_type(initial_capacity_t(), internal_capacity())
{}
- explicit small_vector(size_type n)
+ BOOST_CONTAINER_FORCEINLINE explicit small_vector(const allocator_type &a)
+ : base_type(initial_capacity_t(), internal_capacity(), a)
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE explicit small_vector(size_type n)
: base_type(initial_capacity_t(), internal_capacity())
{ this->resize(n); }
- explicit small_vector(const allocator_type &a)
+ BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, const allocator_type &a)
: base_type(initial_capacity_t(), internal_capacity(), a)
- {}
+ { this->resize(n); }
- small_vector(size_type n, const allocator_type &a)
+ BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, default_init_t)
+ : base_type(initial_capacity_t(), internal_capacity())
+ { this->resize(n, default_init_t()); }
+
+ BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, default_init_t, const allocator_type &a)
: base_type(initial_capacity_t(), internal_capacity(), a)
- { this->resize(n); }
+ { this->resize(n, default_init_t()); }
+
+ BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, const value_type &v)
+ : base_type(initial_capacity_t(), internal_capacity())
+ { this->resize(n, v); }
+
+ small_vector(size_type n, const value_type &v, const allocator_type &a)
+ : base_type(initial_capacity_t(), internal_capacity(), a)
+ { this->resize(n, v); }
+
+ template <class InIt>
+ small_vector(InIt first, InIt last
+ BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::disable_if_c
+ < container_detail::is_convertible<InIt BOOST_MOVE_I size_type>::value
+ BOOST_MOVE_I container_detail::nat >::type * = 0)
+ )
+ : base_type(initial_capacity_t(), internal_capacity())
+ { this->assign(first, last); }
+
+ template <class InIt>
+ BOOST_CONTAINER_FORCEINLINE small_vector(InIt first, InIt last, const allocator_type& a
+ BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::disable_if_c
+ < container_detail::is_convertible<InIt BOOST_MOVE_I size_type>::value
+ BOOST_MOVE_I container_detail::nat >::type * = 0)
+ )
+ : base_type(initial_capacity_t(), internal_capacity(), a)
+ { this->assign(first, last); }
- small_vector(const small_vector &other)
+ BOOST_CONTAINER_FORCEINLINE small_vector(const small_vector &other)
: base_type( initial_capacity_t(), internal_capacity()
, allocator_traits_type::select_on_container_copy_construction(other.get_stored_allocator()))
{ this->assign(other.cbegin(), other.cend()); }
- small_vector(const small_vector &other, const allocator_type &a)
+ BOOST_CONTAINER_FORCEINLINE small_vector(const small_vector &other, const allocator_type &a)
: base_type(initial_capacity_t(), internal_capacity(), a)
{ this->assign(other.cbegin(), other.cend()); }
- small_vector(BOOST_RV_REF(small_vector) other)
+ BOOST_CONTAINER_FORCEINLINE explicit small_vector(const base_type &other)
+ : base_type( initial_capacity_t(), internal_capacity()
+ , allocator_traits_type::select_on_container_copy_construction(other.get_stored_allocator()))
+ { this->assign(other.cbegin(), other.cend()); }
+
+ BOOST_CONTAINER_FORCEINLINE explicit small_vector(BOOST_RV_REF(base_type) other)
: base_type(initial_capacity_t(), internal_capacity(), ::boost::move(other.get_stored_allocator()))
{ this->move_construct_impl(other, other.get_stored_allocator()); }
- small_vector(BOOST_RV_REF(small_vector) other, const allocator_type &a)
+ BOOST_CONTAINER_FORCEINLINE small_vector(BOOST_RV_REF(small_vector) other)
+ : base_type(initial_capacity_t(), internal_capacity(), ::boost::move(other.get_stored_allocator()))
+ { this->move_construct_impl(other, other.get_stored_allocator()); }
+
+ BOOST_CONTAINER_FORCEINLINE small_vector(BOOST_RV_REF(small_vector) other, const allocator_type &a)
: base_type(initial_capacity_t(), internal_capacity(), a)
{ this->move_construct_impl(other, a); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
- small_vector(std::initializer_list<value_type> il, const allocator_type& a = allocator_type())
+ BOOST_CONTAINER_FORCEINLINE small_vector(std::initializer_list<value_type> il, const allocator_type& a = allocator_type())
: base_type(initial_capacity_t(), internal_capacity(), a)
{
this->assign(il.begin(), il.end());
}
#endif
- small_vector& operator=(BOOST_COPY_ASSIGN_REF(small_vector) other)
+ BOOST_CONTAINER_FORCEINLINE small_vector& operator=(BOOST_COPY_ASSIGN_REF(small_vector) other)
{ return static_cast<small_vector&>(this->base_type::operator=(static_cast<base_type const&>(other))); }
- small_vector& operator=(BOOST_RV_REF(small_vector) other)
+ BOOST_CONTAINER_FORCEINLINE small_vector& operator=(BOOST_RV_REF(small_vector) other)
{ return static_cast<small_vector&>(this->base_type::operator=(BOOST_MOVE_BASE(base_type, other))); }
- void swap(small_vector &other)
- { return this->base_type::swap(other); }
+ BOOST_CONTAINER_FORCEINLINE small_vector& operator=(const base_type &other)
+ { return static_cast<small_vector&>(this->base_type::operator=(other)); }
- #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
- private:
- void move_construct_impl(small_vector &x, const allocator_type &a)
- {
- if(base_type::is_propagable_from(x.get_stored_allocator(), x.data(), a, true)){
- this->steal_resources(x);
- }
- else{
- this->assign( boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.begin()))
- , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.end ()))
- );
- }
- }
- #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ BOOST_CONTAINER_FORCEINLINE small_vector& operator=(BOOST_RV_REF(base_type) other)
+ { return static_cast<small_vector&>(this->base_type::operator=(boost::move(other))); }
+
+ BOOST_CONTAINER_FORCEINLINE void swap(small_vector &other)
+ { return this->base_type::swap(other); }
};
}}
diff --git a/boost/container/static_vector.hpp b/boost/container/static_vector.hpp
index 69540dcc7b..a37c16572c 100644
--- a/boost/container/static_vector.hpp
+++ b/boost/container/static_vector.hpp
@@ -41,29 +41,32 @@ class static_storage_allocator
public:
typedef T value_type;
- static_storage_allocator() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE static_storage_allocator() BOOST_NOEXCEPT_OR_NOTHROW
{}
- static_storage_allocator(const static_storage_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE static_storage_allocator(const static_storage_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
{}
- static_storage_allocator & operator=(const static_storage_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE static_storage_allocator & operator=(const static_storage_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
{ return *this; }
- T* internal_storage() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE T* internal_storage() const BOOST_NOEXCEPT_OR_NOTHROW
{ return const_cast<T*>(static_cast<const T*>(static_cast<const void*>(&storage))); }
- T* internal_storage() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE T* internal_storage() BOOST_NOEXCEPT_OR_NOTHROW
{ return static_cast<T*>(static_cast<void*>(&storage)); }
static const std::size_t internal_capacity = N;
+ std::size_t max_size() const
+ { return N; }
+
typedef boost::container::container_detail::version_type<static_storage_allocator, 0> version;
- friend bool operator==(const static_storage_allocator &, const static_storage_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE friend bool operator==(const static_storage_allocator &, const static_storage_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
{ return false; }
- friend bool operator!=(const static_storage_allocator &, const static_storage_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const static_storage_allocator &, const static_storage_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
{ return true; }
private:
@@ -143,7 +146,7 @@ public:
//!
//! @par Complexity
//! Constant O(1).
- static_vector() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE static_vector() BOOST_NOEXCEPT_OR_NOTHROW
: base_t()
{}
@@ -158,7 +161,7 @@ public:
//!
//! @par Complexity
//! Linear O(N).
- explicit static_vector(size_type count)
+ BOOST_CONTAINER_FORCEINLINE explicit static_vector(size_type count)
: base_t(count)
{}
@@ -176,7 +179,7 @@ public:
//!
//! @par Note
//! Non-standard extension
- static_vector(size_type count, default_init_t)
+ BOOST_CONTAINER_FORCEINLINE static_vector(size_type count, default_init_t)
: base_t(count, default_init_t())
{}
@@ -192,7 +195,7 @@ public:
//!
//! @par Complexity
//! Linear O(N).
- static_vector(size_type count, value_type const& value)
+ BOOST_CONTAINER_FORCEINLINE static_vector(size_type count, value_type const& value)
: base_t(count, value)
{}
@@ -211,7 +214,7 @@ public:
//! @par Complexity
//! Linear O(N).
template <typename Iterator>
- static_vector(Iterator first, Iterator last)
+ BOOST_CONTAINER_FORCEINLINE static_vector(Iterator first, Iterator last)
: base_t(first, last)
{}
@@ -228,7 +231,7 @@ public:
//!
//! @par Complexity
//! Linear O(N).
- static_vector(std::initializer_list<value_type> il)
+ BOOST_CONTAINER_FORCEINLINE static_vector(std::initializer_list<value_type> il)
: base_t(il)
{}
#endif
@@ -242,7 +245,7 @@ public:
//!
//! @par Complexity
//! Linear O(N).
- static_vector(static_vector const& other)
+ BOOST_CONTAINER_FORCEINLINE static_vector(static_vector const& other)
: base_t(other)
{}
@@ -258,7 +261,7 @@ public:
//! @par Complexity
//! Linear O(N).
template <std::size_t C>
- static_vector(static_vector<value_type, C> const& other)
+ BOOST_CONTAINER_FORCEINLINE static_vector(static_vector<value_type, C> const& other)
: base_t(other)
{}
@@ -272,7 +275,7 @@ public:
//!
//! @par Complexity
//! Linear O(N).
- static_vector(BOOST_RV_REF(static_vector) other)
+ BOOST_CONTAINER_FORCEINLINE static_vector(BOOST_RV_REF(static_vector) other)
: base_t(BOOST_MOVE_BASE(base_t, other))
{}
@@ -289,7 +292,7 @@ public:
//! @par Complexity
//! Linear O(N).
template <std::size_t C>
- static_vector(BOOST_RV_REF_BEG static_vector<value_type, C> BOOST_RV_REF_END other)
+ 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))
{}
@@ -302,7 +305,7 @@ public:
//!
//! @par Complexity
//! Linear O(N).
- static_vector & operator=(BOOST_COPY_ASSIGN_REF(static_vector) other)
+ BOOST_CONTAINER_FORCEINLINE static_vector & operator=(BOOST_COPY_ASSIGN_REF(static_vector) other)
{
return static_cast<static_vector&>(base_t::operator=(static_cast<base_t const&>(other)));
}
@@ -317,7 +320,7 @@ public:
//!
//! @par Complexity
//! Linear O(N).
- static_vector & operator=(std::initializer_list<value_type> il)
+ BOOST_CONTAINER_FORCEINLINE static_vector & operator=(std::initializer_list<value_type> il)
{ return static_cast<static_vector&>(base_t::operator=(il)); }
#endif
@@ -333,7 +336,7 @@ public:
//! @par Complexity
//! Linear O(N).
template <std::size_t C>
- static_vector & operator=(static_vector<value_type, C> const& other)
+ BOOST_CONTAINER_FORCEINLINE static_vector & operator=(static_vector<value_type, C> const& other)
{
return static_cast<static_vector&>(base_t::operator=
(static_cast<typename static_vector<value_type, C>::base_t const&>(other)));
@@ -349,7 +352,7 @@ public:
//!
//! @par Complexity
//! Linear O(N).
- static_vector & operator=(BOOST_RV_REF(static_vector) other)
+ BOOST_CONTAINER_FORCEINLINE static_vector & operator=(BOOST_RV_REF(static_vector) other)
{
return static_cast<static_vector&>(base_t::operator=(BOOST_MOVE_BASE(base_t, other)));
}
@@ -367,7 +370,7 @@ public:
//! @par Complexity
//! Linear O(N).
template <std::size_t C>
- static_vector & operator=(BOOST_RV_REF_BEG static_vector<value_type, C> BOOST_RV_REF_END other)
+ BOOST_CONTAINER_FORCEINLINE static_vector & operator=(BOOST_RV_REF_BEG static_vector<value_type, C> 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)));
@@ -578,7 +581,6 @@ public:
template <typename Iterator>
iterator insert(const_iterator p, Iterator first, Iterator last);
-#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! @pre
//! @li \c p must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
//! @li <tt>distance(il.begin(), il.end()) <= capacity()</tt>
@@ -594,7 +596,6 @@ public:
//! @par Complexity
//! Linear O(N).
iterator insert(const_iterator p, std::initializer_list<value_type> il);
-#endif
//! @pre \c p must be a valid iterator of \c *this in range <tt>[begin(), end())</tt>
//!
@@ -640,7 +641,6 @@ public:
template <typename Iterator>
void assign(Iterator first, Iterator last);
-#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! @pre <tt>distance(il.begin(), il.end()) <= capacity()</tt>
//!
//! @brief Assigns a range <tt>[il.begin(), il.end())</tt> of Values to this container.
@@ -653,7 +653,6 @@ public:
//! @par Complexity
//! Linear O(N).
void assign(std::initializer_list<value_type> il);
-#endif
//! @pre <tt>count <= capacity()</tt>
//!
@@ -1095,7 +1094,7 @@ public:
bool empty() const BOOST_NOEXCEPT_OR_NOTHROW;
#else
- friend void swap(static_vector &x, static_vector &y)
+ BOOST_CONTAINER_FORCEINLINE friend void swap(static_vector &x, static_vector &y)
{
x.swap(y);
}
diff --git a/boost/container/throw_exception.hpp b/boost/container/throw_exception.hpp
index 2c893e95c8..118cc399b8 100644
--- a/boost/container/throw_exception.hpp
+++ b/boost/container/throw_exception.hpp
@@ -24,6 +24,7 @@
#ifndef BOOST_NO_EXCEPTIONS
#include <stdexcept> //for std exception types
+ #include <string> //for implicit std::string conversion
#include <new> //for std::bad_alloc
#else
#include <boost/assert.hpp>
diff --git a/boost/container/vector.hpp b/boost/container/vector.hpp
index e3bc1068aa..fabe92df88 100644
--- a/boost/container/vector.hpp
+++ b/boost/container/vector.hpp
@@ -96,13 +96,13 @@ class vec_iterator
Pointer m_ptr;
public:
- const Pointer &get_ptr() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const Pointer &get_ptr() const BOOST_NOEXCEPT_OR_NOTHROW
{ return m_ptr; }
- Pointer &get_ptr() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE Pointer &get_ptr() BOOST_NOEXCEPT_OR_NOTHROW
{ return m_ptr; }
- explicit vec_iterator(Pointer ptr) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE explicit vec_iterator(Pointer ptr) BOOST_NOEXCEPT_OR_NOTHROW
: m_ptr(ptr)
{}
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -110,73 +110,73 @@ class vec_iterator
public:
//Constructors
- vec_iterator() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE vec_iterator() BOOST_NOEXCEPT_OR_NOTHROW
: m_ptr() //Value initialization to achieve "null iterators" (N3644)
{}
- vec_iterator(vec_iterator<Pointer, false> const& other) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE vec_iterator(vec_iterator<Pointer, false> const& other) BOOST_NOEXCEPT_OR_NOTHROW
: m_ptr(other.get_ptr())
{}
//Pointer like operators
- reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
{ return *m_ptr; }
- pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
{ return ::boost::intrusive::pointer_traits<pointer>::pointer_to(this->operator*()); }
- reference operator[](difference_type off) const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE reference operator[](difference_type off) const BOOST_NOEXCEPT_OR_NOTHROW
{ return m_ptr[off]; }
//Increment / Decrement
- vec_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE vec_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
{ ++m_ptr; return *this; }
- vec_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE vec_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
{ return vec_iterator(m_ptr++); }
- vec_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE vec_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
{ --m_ptr; return *this; }
- vec_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE vec_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW
{ return vec_iterator(m_ptr--); }
//Arithmetic
- vec_iterator& operator+=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE vec_iterator& operator+=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
{ m_ptr += off; return *this; }
- vec_iterator& operator-=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE vec_iterator& operator-=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
{ m_ptr -= off; return *this; }
- friend vec_iterator operator+(const vec_iterator &x, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE friend vec_iterator operator+(const vec_iterator &x, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
{ return vec_iterator(x.m_ptr+off); }
- friend vec_iterator operator+(difference_type off, vec_iterator right) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE friend vec_iterator operator+(difference_type off, vec_iterator right) BOOST_NOEXCEPT_OR_NOTHROW
{ right.m_ptr += off; return right; }
- friend vec_iterator operator-(vec_iterator left, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE friend vec_iterator operator-(vec_iterator left, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
{ left.m_ptr -= off; return left; }
- friend difference_type operator-(const vec_iterator &left, const vec_iterator& right) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE friend difference_type operator-(const vec_iterator &left, const vec_iterator& right) BOOST_NOEXCEPT_OR_NOTHROW
{ return left.m_ptr - right.m_ptr; }
//Comparison operators
- friend bool operator== (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE friend bool operator== (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return l.m_ptr == r.m_ptr; }
- friend bool operator!= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE friend bool operator!= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return l.m_ptr != r.m_ptr; }
- friend bool operator< (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE friend bool operator< (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return l.m_ptr < r.m_ptr; }
- friend bool operator<= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE friend bool operator<= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return l.m_ptr <= r.m_ptr; }
- friend bool operator> (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE friend bool operator> (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return l.m_ptr > r.m_ptr; }
- friend bool operator>= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE friend bool operator>= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return l.m_ptr >= r.m_ptr; }
};
@@ -186,7 +186,7 @@ struct vector_insert_ordered_cursor
typedef typename iterator_traits<BiDirPosConstIt>::value_type size_type;
typedef typename iterator_traits<BiDirValueIt>::reference reference;
- vector_insert_ordered_cursor(BiDirPosConstIt posit, BiDirValueIt valueit)
+ BOOST_CONTAINER_FORCEINLINE vector_insert_ordered_cursor(BiDirPosConstIt posit, BiDirValueIt valueit)
: last_position_it(posit), last_value_it(valueit)
{}
@@ -200,10 +200,10 @@ struct vector_insert_ordered_cursor
}
}
- size_type get_pos() const
+ BOOST_CONTAINER_FORCEINLINE size_type get_pos() const
{ return *last_position_it; }
- reference get_val()
+ BOOST_CONTAINER_FORCEINLINE reference get_val()
{ return *last_value_it; }
BiDirPosConstIt last_position_it;
@@ -216,7 +216,7 @@ struct vector_merge_cursor
typedef SizeType size_type;
typedef typename iterator_traits<BiDirValueIt>::reference reference;
- vector_merge_cursor(T *pbeg, T *plast, BiDirValueIt valueit, Comp &cmp)
+ BOOST_CONTAINER_FORCEINLINE vector_merge_cursor(T *pbeg, T *plast, BiDirValueIt valueit, Comp &cmp)
: m_pbeg(pbeg), m_pcur(--plast), m_valueit(valueit), m_cmp(cmp)
{}
@@ -232,10 +232,10 @@ struct vector_merge_cursor
}
}
- size_type get_pos() const
+ BOOST_CONTAINER_FORCEINLINE size_type get_pos() const
{ return static_cast<size_type>((m_pcur + 1) - m_pbeg); }
- reference get_val()
+ BOOST_CONTAINER_FORCEINLINE reference get_val()
{ return *m_valueit; }
T *const m_pbeg;
@@ -247,11 +247,11 @@ struct vector_merge_cursor
} //namespace container_detail {
template<class Pointer, bool IsConst>
-const Pointer &vector_iterator_get_ptr(const container_detail::vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
+BOOST_CONTAINER_FORCEINLINE const Pointer &vector_iterator_get_ptr(const container_detail::vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
{ return it.get_ptr(); }
template<class Pointer, bool IsConst>
-Pointer &get_ptr(container_detail::vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
+BOOST_CONTAINER_FORCEINLINE Pointer &get_ptr(container_detail::vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
{ return it.get_ptr(); }
namespace container_detail {
@@ -270,7 +270,7 @@ struct vector_get_ptr_pointer_to_non_const
typedef typename pointer_traits_t
::template rebind_pointer<non_const_element_type>::type return_type;
- static return_type get_ptr(const const_pointer &ptr) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE static return_type get_ptr(const const_pointer &ptr) BOOST_NOEXCEPT_OR_NOTHROW
{ return boost::intrusive::pointer_traits<return_type>::const_cast_from(ptr); }
};
@@ -278,14 +278,14 @@ template<class Pointer>
struct vector_get_ptr_pointer_to_non_const<Pointer, false>
{
typedef const Pointer & return_type;
- static return_type get_ptr(const Pointer &ptr) BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE static return_type get_ptr(const Pointer &ptr) BOOST_NOEXCEPT_OR_NOTHROW
{ return ptr; }
};
} //namespace container_detail {
template<class MaybeConstPointer>
-typename container_detail::vector_get_ptr_pointer_to_non_const<MaybeConstPointer>::return_type
+BOOST_CONTAINER_FORCEINLINE typename container_detail::vector_get_ptr_pointer_to_non_const<MaybeConstPointer>::return_type
vector_iterator_get_ptr(const MaybeConstPointer &ptr) BOOST_NOEXCEPT_OR_NOTHROW
{
return container_detail::vector_get_ptr_pointer_to_non_const<MaybeConstPointer>::get_ptr(ptr);
@@ -451,14 +451,14 @@ struct vector_alloc_holder
, m_capacity(n)
{}
- ~vector_alloc_holder() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE ~vector_alloc_holder() BOOST_NOEXCEPT_OR_NOTHROW
{
if(this->m_capacity){
this->alloc().deallocate(this->m_start, this->m_capacity);
}
}
- pointer allocation_command(boost::container::allocation_type command,
+ BOOST_CONTAINER_FORCEINLINE pointer allocation_command(boost::container::allocation_type command,
size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse)
{
typedef typename container_detail::version<Allocator>::type alloc_version;
@@ -482,7 +482,7 @@ struct vector_alloc_holder
return success;
}
- size_type next_capacity(size_type additional_objects) const
+ BOOST_CONTAINER_FORCEINLINE size_type next_capacity(size_type additional_objects) const
{
return next_capacity_calculator
<size_type, NextCapacityDouble //NextCapacity60Percent
@@ -510,10 +510,10 @@ struct vector_alloc_holder
x.m_size = x.m_capacity = 0;
}
- Allocator &alloc() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE Allocator &alloc() BOOST_NOEXCEPT_OR_NOTHROW
{ return *this; }
- const Allocator &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const Allocator &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
{ return *this; }
const pointer &start() const BOOST_NOEXCEPT_OR_NOTHROW { return m_start; }
@@ -534,7 +534,7 @@ struct vector_alloc_holder
}
}
- pointer priv_allocation_command(version_1, boost::container::allocation_type command,
+ BOOST_CONTAINER_FORCEINLINE pointer priv_allocation_command(version_1, boost::container::allocation_type command,
size_type ,
size_type &prefer_in_recvd_out_size,
pointer &reuse)
@@ -624,14 +624,14 @@ struct vector_alloc_holder<Allocator, version_0>
(this->alloc(), container_detail::to_raw_pointer(holder.start()), n, container_detail::to_raw_pointer(this->start()));
}
- void priv_first_allocation(size_type cap)
+ BOOST_CONTAINER_FORCEINLINE void priv_first_allocation(size_type cap)
{
if(cap > Allocator::internal_capacity){
throw_bad_alloc();
}
}
- void deep_swap(vector_alloc_holder &x)
+ BOOST_CONTAINER_FORCEINLINE void deep_swap(vector_alloc_holder &x)
{
this->priv_deep_swap(x);
}
@@ -645,28 +645,28 @@ struct vector_alloc_holder<Allocator, version_0>
this->priv_deep_swap(x);
}
- void swap_resources(vector_alloc_holder &) BOOST_NOEXCEPT_OR_NOTHROW
+ 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();
}
- void steal_resources(vector_alloc_holder &)
+ 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();
}
- Allocator &alloc() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE Allocator &alloc() BOOST_NOEXCEPT_OR_NOTHROW
{ return *this; }
- const Allocator &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const Allocator &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
{ return *this; }
- bool try_expand_fwd(size_type at_least)
+ BOOST_CONTAINER_FORCEINLINE bool try_expand_fwd(size_type at_least)
{ return !at_least; }
- pointer start() const BOOST_NOEXCEPT_OR_NOTHROW { return Allocator::internal_storage(); }
- size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW { return Allocator::internal_capacity; }
+ BOOST_CONTAINER_FORCEINLINE pointer start() const BOOST_NOEXCEPT_OR_NOTHROW { return Allocator::internal_storage(); }
+ BOOST_CONTAINER_FORCEINLINE size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW { return Allocator::internal_capacity; }
size_type m_size;
private:
@@ -765,16 +765,16 @@ class vector
protected:
- void steal_resources(vector &x)
+ BOOST_CONTAINER_FORCEINLINE void steal_resources(vector &x)
{ return this->m_holder.steal_resources(x.m_holder); }
struct initial_capacity_t{};
template<class AllocFwd>
- vector(initial_capacity_t, pointer initial_memory, size_type capacity, BOOST_FWD_REF(AllocFwd) a)
+ BOOST_CONTAINER_FORCEINLINE vector(initial_capacity_t, pointer initial_memory, size_type capacity, BOOST_FWD_REF(AllocFwd) a)
: m_holder(initial_memory, capacity, ::boost::forward<AllocFwd>(a))
{}
- vector(initial_capacity_t, pointer initial_memory, size_type capacity)
+ BOOST_CONTAINER_FORCEINLINE vector(initial_capacity_t, pointer initial_memory, size_type capacity)
: m_holder(initial_memory, capacity)
{}
@@ -822,38 +822,38 @@ class vector
}
//! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
- //! and inserts n default initialized values.
+ //! and inserts n value initialized values.
//!
//! <b>Throws</b>: If allocator_type's allocation
- //! throws or T's default initialization throws.
+ //! throws or T's value initialization throws.
//!
//! <b>Complexity</b>: Linear to n.
- //!
- //! <b>Note</b>: Non-standard extension
- vector(size_type n, default_init_t)
- : m_holder(container_detail::uninitialized_size, n)
+ explicit vector(size_type n, const allocator_type &a)
+ : m_holder(container_detail::uninitialized_size, a, n)
{
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
this->num_alloc += n != 0;
#endif
- boost::container::uninitialized_default_init_alloc_n
+ boost::container::uninitialized_value_init_alloc_n
(this->m_holder.alloc(), n, this->priv_raw_begin());
}
//! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
- //! and inserts n value initialized values.
+ //! and inserts n default initialized values.
//!
//! <b>Throws</b>: If allocator_type's allocation
- //! throws or T's value initialization throws.
+ //! throws or T's default initialization throws.
//!
//! <b>Complexity</b>: Linear to n.
- explicit vector(size_type n, const allocator_type &a)
- : m_holder(container_detail::uninitialized_size, a, n)
+ //!
+ //! <b>Note</b>: Non-standard extension
+ vector(size_type n, default_init_t)
+ : m_holder(container_detail::uninitialized_size, n)
{
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
this->num_alloc += n != 0;
#endif
- boost::container::uninitialized_value_init_alloc_n
+ boost::container::uninitialized_default_init_alloc_n
(this->m_holder.alloc(), n, this->priv_raw_begin());
}
@@ -918,7 +918,11 @@ class vector
//!
//! <b>Complexity</b>: Linear to the range [first, last).
template <class InIt>
- vector(InIt first, InIt last)
+ vector(InIt first, InIt last
+ BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::disable_if_c
+ < container_detail::is_convertible<InIt BOOST_MOVE_I size_type>::value
+ BOOST_MOVE_I container_detail::nat >::type * = 0)
+ )
: m_holder()
{ this->assign(first, last); }
@@ -930,7 +934,11 @@ class vector
//!
//! <b>Complexity</b>: Linear to the range [first, last).
template <class InIt>
- vector(InIt first, InIt last, const allocator_type& a)
+ vector(InIt first, InIt last, const allocator_type& a
+ BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::disable_if_c
+ < container_detail::is_convertible<InIt BOOST_MOVE_I size_type>::value
+ BOOST_MOVE_I container_detail::nat >::type * = 0)
+ )
: m_holder(a)
{ this->assign(first, last); }
@@ -1063,7 +1071,7 @@ class vector
//! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment throws.
//!
//! <b>Complexity</b>: Linear to the number of elements in x.
- vector& operator=(BOOST_COPY_ASSIGN_REF(vector) x)
+ BOOST_CONTAINER_FORCEINLINE vector& operator=(BOOST_COPY_ASSIGN_REF(vector) x)
{
if (&x != this){
this->priv_copy_assign(x);
@@ -1075,7 +1083,7 @@ class vector
//! <b>Effects</b>: Make *this container contains elements from il.
//!
//! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
- vector& operator=(std::initializer_list<value_type> il)
+ BOOST_CONTAINER_FORCEINLINE vector& operator=(std::initializer_list<value_type> il)
{
this->assign(il.begin(), il.end());
return *this;
@@ -1093,7 +1101,7 @@ class vector
//! <b>Complexity</b>: Constant if allocator_traits_type::
//! propagate_on_container_move_assignment is true or
//! this->get>allocator() == x.get_allocator(). Linear otherwise.
- vector& operator=(BOOST_RV_REF(vector) x)
+ BOOST_CONTAINER_FORCEINLINE vector& operator=(BOOST_RV_REF(vector) x)
BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
|| allocator_traits_type::is_always_equal::value)
{
@@ -1115,7 +1123,7 @@ class vector
//!
//! <b>Note</b>: Non-standard extension to support static_vector
template<class OtherAllocator>
- typename container_detail::enable_if_and
+ BOOST_CONTAINER_FORCEINLINE typename container_detail::enable_if_and
< vector&
, container_detail::is_version<OtherAllocator, 0>
, container_detail::is_different<OtherAllocator, allocator_type>
@@ -1137,7 +1145,7 @@ class vector
//!
//! <b>Note</b>: Non-standard extension to support static_vector
template<class OtherAllocator>
- typename container_detail::enable_if_and
+ BOOST_CONTAINER_FORCEINLINE typename container_detail::enable_if_and
< vector&
, container_detail::is_version<OtherAllocator, 0>
, container_detail::is_different<OtherAllocator, allocator_type>
@@ -1193,7 +1201,7 @@ class vector
//! <b>Throws</b>: If memory allocation throws or
//! T's constructor from dereferencing iniializer_list iterator throws.
//!
- void assign(std::initializer_list<T> il)
+ BOOST_CONTAINER_FORCEINLINE void assign(std::initializer_list<T> il)
{
this->assign(il.begin(), il.end());
}
@@ -1269,7 +1277,7 @@ class vector
//! T's copy/move constructor/assignment throws.
//!
//! <b>Complexity</b>: Linear to n.
- void assign(size_type n, const value_type& val)
+ BOOST_CONTAINER_FORCEINLINE void assign(size_type n, const value_type& val)
{ this->assign(cvalue_iterator(val, n), cvalue_iterator()); }
//! <b>Effects</b>: Returns a copy of the internal allocator.
@@ -1287,7 +1295,7 @@ class vector
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
- stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
{ return this->m_holder.alloc(); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -1297,7 +1305,7 @@ class vector
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Non-standard extension.
- const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
{ return this->m_holder.alloc(); }
//////////////////////////////////////////////
@@ -1311,7 +1319,7 @@ class vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
{ return iterator(this->m_holder.start()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
@@ -1319,7 +1327,7 @@ class vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
{ return const_iterator(this->m_holder.start()); }
//! <b>Effects</b>: Returns an iterator to the end of the vector.
@@ -1327,7 +1335,7 @@ class vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- iterator end() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE iterator end() BOOST_NOEXCEPT_OR_NOTHROW
{ return iterator(this->m_holder.start() + this->m_holder.m_size); }
//! <b>Effects</b>: Returns a const_iterator to the end of the vector.
@@ -1335,7 +1343,7 @@ class vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
{ return this->cend(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
@@ -1344,7 +1352,7 @@ class vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
{ return reverse_iterator(this->end()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -1353,7 +1361,7 @@ class vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
{ return this->crbegin(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
@@ -1362,7 +1370,7 @@ class vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
{ return reverse_iterator(this->begin()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -1371,7 +1379,7 @@ class vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
{ return this->crend(); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
@@ -1379,7 +1387,7 @@ class vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
{ return const_iterator(this->m_holder.start()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the vector.
@@ -1387,7 +1395,7 @@ class vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
{ return const_iterator(this->m_holder.start() + this->m_holder.m_size); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -1396,7 +1404,7 @@ class vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
{ return const_reverse_iterator(this->end());}
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -1405,7 +1413,7 @@ class vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
{ return const_reverse_iterator(this->begin()); }
//////////////////////////////////////////////
@@ -1419,7 +1427,7 @@ class vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
{ return !this->m_holder.m_size; }
//! <b>Effects</b>: Returns the number of the elements contained in the vector.
@@ -1427,7 +1435,7 @@ class vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
{ return this->m_holder.m_size; }
//! <b>Effects</b>: Returns the largest possible size of the vector.
@@ -1435,7 +1443,7 @@ class vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
{ return allocator_traits_type::max_size(this->m_holder.alloc()); }
//! <b>Effects</b>: Inserts or erases elements at the end such that
@@ -1473,7 +1481,7 @@ class vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
+ BOOST_CONTAINER_FORCEINLINE size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
{ return this->m_holder.capacity(); }
//! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
@@ -1482,7 +1490,7 @@ class vector
//! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
//!
//! <b>Throws</b>: If memory allocation allocation throws or T's copy/move constructor throws.
- void reserve(size_type new_cap)
+ BOOST_CONTAINER_FORCEINLINE void reserve(size_type new_cap)
{
if (this->capacity() < new_cap){
this->priv_reserve_no_capacity(new_cap, alloc_version());
@@ -1495,7 +1503,7 @@ class vector
//! <b>Throws</b>: If memory allocation throws, or T's copy/move constructor throws.
//!
//! <b>Complexity</b>: Linear to size().
- void shrink_to_fit()
+ BOOST_CONTAINER_FORCEINLINE void shrink_to_fit()
{ this->priv_shrink_to_fit(alloc_version()); }
//////////////////////////////////////////////
@@ -1722,7 +1730,7 @@ class vector
//!
//! <b>Complexity</b>: Amortized constant time.
template<class ...Args>
- void emplace_back(BOOST_FWD_REF(Args)...args)
+ BOOST_CONTAINER_FORCEINLINE void emplace_back(BOOST_FWD_REF(Args)...args)
{
if (BOOST_LIKELY(this->room_enough())){
//There is more memory, just construct a new object at the end
@@ -1745,7 +1753,7 @@ class vector
//!
//! <b>Note</b>: Non-standard extension.
template<class ...Args>
- bool stable_emplace_back(BOOST_FWD_REF(Args)...args)
+ BOOST_CONTAINER_FORCEINLINE bool stable_emplace_back(BOOST_FWD_REF(Args)...args)
{
const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u));
if (BOOST_LIKELY(is_room_enough)){
@@ -1780,7 +1788,7 @@ class vector
#define BOOST_CONTAINER_VECTOR_EMPLACE_CODE(N) \
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
- void emplace_back(BOOST_MOVE_UREF##N)\
+ BOOST_CONTAINER_FORCEINLINE void emplace_back(BOOST_MOVE_UREF##N)\
{\
if (BOOST_LIKELY(this->room_enough())){\
allocator_traits_type::construct (this->m_holder.alloc()\
@@ -1795,7 +1803,7 @@ class vector
}\
\
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
- bool stable_emplace_back(BOOST_MOVE_UREF##N)\
+ BOOST_CONTAINER_FORCEINLINE bool stable_emplace_back(BOOST_MOVE_UREF##N)\
{\
const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u));\
if (BOOST_LIKELY(is_room_enough)){\
@@ -1837,7 +1845,7 @@ class vector
//! <b>Complexity</b>: Amortized constant time.
void push_back(T &&x);
#else
- BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
+ BOOST_CONTAINER_FORCEINLINE BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
#endif
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -3098,7 +3106,10 @@ class vector
old_values_destroyer.shrink_forward(new_size-s_before);
this->m_holder.m_size = new_size;
//Now move remaining last objects in the old buffer begin
- ::boost::container::move(pos + raw_gap, old_finish, old_start);
+ T * const remaining_pos = pos + raw_gap;
+ if(remaining_pos != old_start){ //Make sure data has to be moved
+ ::boost::container::move(remaining_pos, old_finish, old_start);
+ }
//Once moved, avoid calling the destructors if trivial after move
if(value_traits::trivial_dctr_after_move){
old_values_destroyer.release();
@@ -3238,8 +3249,9 @@ class vector
const size_type rest_new = n - mid_n;
insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), old_start, rest_new);
T* const move_start = old_start + rest_new;
- //Displace old_end
- T* const move_end = ::boost::container::move(pos, old_finish, move_start);
+ //Displace old_end, but make sure data has to be moved
+ T* const move_end = move_start != pos ? ::boost::container::move(pos, old_finish, move_start)
+ : old_finish;
//Destroy remaining moved elements from old_end except if they
//have trivial destructor after being moved
size_type n_destroy = s_before - n;
diff --git a/boost/context/all.hpp b/boost/context/all.hpp
index 152f299089..44b734cdb8 100644
--- a/boost/context/all.hpp
+++ b/boost/context/all.hpp
@@ -4,10 +4,10 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#include <boost/context/fcontext.hpp>
+#include <boost/context/execution_context.hpp>
#include <boost/context/fixedsize_stack.hpp>
+#include <boost/context/pooled_fixedsize_stack.hpp>
#include <boost/context/protected_fixedsize_stack.hpp>
#include <boost/context/segmented_stack.hpp>
#include <boost/context/stack_context.hpp>
#include <boost/context/stack_traits.hpp>
-#include <boost/context/execution_context.hpp>
diff --git a/boost/context/detail/apply.hpp b/boost/context/detail/apply.hpp
new file mode 100644
index 0000000000..54db844b9e
--- /dev/null
+++ b/boost/context/detail/apply.hpp
@@ -0,0 +1,55 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONTEXT_DETAIL_APPLY_H
+#define BOOST_CONTEXT_DETAIL_APPLY_H
+
+#include <functional>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include <boost/config.hpp>
+
+#include <boost/context/detail/config.hpp>
+#include <boost/context/detail/invoke.hpp>
+#include <boost/context/detail/index_sequence.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+template< typename Fn, typename Tpl, std::size_t ... I >
+auto
+apply_impl( Fn && fn, Tpl && tpl, index_sequence< I ... >)
+ -> decltype( invoke( std::forward< Fn >( fn), std::get< I >( std::forward< Tpl >( tpl) ) ... ) )
+{
+ return invoke( std::forward< Fn >( fn), std::get< I >( std::forward< Tpl >( tpl) ) ... );
+}
+
+template< typename Fn, typename Tpl >
+auto
+apply( Fn && fn, Tpl && tpl)
+ -> decltype( apply_impl( std::forward< Fn >( fn),
+ std::forward< Tpl >( tpl),
+ make_index_sequence< std::tuple_size< typename std::decay< Tpl >::type >::value >{}) )
+{
+ return apply_impl( std::forward< Fn >( fn),
+ std::forward< Tpl >( tpl),
+ make_index_sequence< std::tuple_size< typename std::decay< Tpl >::type >::value >{});
+}
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_DETAIL_APPLY_H
diff --git a/boost/context/detail/config.hpp b/boost/context/detail/config.hpp
index 0d5fa757fa..84dd238100 100644
--- a/boost/context/detail/config.hpp
+++ b/boost/context/detail/config.hpp
@@ -57,32 +57,51 @@
# define BOOST_CONTEXT_SEGMENTS 10
#endif
-#undef BOOST_CONTEXT_NO_EXECUTION_CONTEXT
-#if defined(BOOST_NO_CXX11_CONSTEXPR) || \
- defined(BOOST_NO_CXX11_DECLTYPE) || \
- defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || \
- defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) || \
+
+#define BOOST_CONTEXT_NO_CXX14_INTEGER_SEQUENCE
+// use rd6 macros for std::integer_sequence
+#if defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence >= 201304
+# undef BOOST_CONTEXT_NO_CXX14_INTEGER_SEQUENCE
+#endif
+// workaroud: MSVC 14 does not provide macros to test for compile-time integer sequence
+#if _MSC_VER > 1800 // _MSC_VER == 1800 -> MS Visual Studio 2013
+# undef BOOST_CONTEXT_NO_INDEX_SEQUENCE
+#endif
+// workaround: Xcode clang feature detection
+#if ! defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence >= 201304
+# if _LIBCPP_STD_VER > 11
+# undef BOOST_CONTEXT_NO_CXX14_INTEGER_SEQUENCE
+# endif
+#endif
+
+// workaroud: MSVC 14 does support constexpr
+#if _MSC_VER > 1800 // _MSC_VER == 1800 -> MS Visual Studio 2013
+# undef BOOST_NO_CXX11_CONSTEXPR
+#endif
+
+#undef BOOST_CONTEXT_NO_CXX11
+#if defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) || \
+ defined(BOOST_NO_CXX11_CONSTEXPR) || \
+ defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || \
+ defined(BOOST_NO_CXX11_FINAL) || \
defined(BOOST_NO_CXX11_HDR_TUPLE) || \
- defined(BOOST_NO_CXX11_LAMBDAS) || \
defined(BOOST_NO_CXX11_NOEXCEPT) || \
defined(BOOST_NO_CXX11_NULLPTR) || \
- defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) || \
defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \
- defined(BOOST_NO_CXX11_VARIADIC_MACROS) || \
+ defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) || \
+ defined(BOOST_NO_CXX11_UNIFIED_INITIALISATION_SYNTAX) || \
defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \
- defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES) || \
- ! defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence < 201304
-# define BOOST_CONTEXT_NO_EXECUTION_CONTEXT
-#endif
-// workaroud: MSVC 14 does not provide macros to test for compile-time integer sequence
-#if _MSC_VER > 1800 // _MSC_VER == 1800 -> MS Visual Studio 2013
-# undef BOOST_CONTEXT_NO_EXECUTION_CONTEXT
+ defined(BOOST_NO_HDR_ATOMIC) || \
+ defined(BOOST_NO_HDR_TUPLE)
+# define BOOST_CONTEXT_NO_CXX11
#endif
-// workaround: Xcode clang feature detection
-#if ! defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence < 201304
-# if _LIBCPP_STD_VER > 11
-# undef BOOST_CONTEXT_NO_EXECUTION_CONTEXT
-# endif
+
+#if ! defined(BOOST_EXECUTION_CONTEXT)
+# if defined(BOOST_USE_SEGMENTED_STACKS)
+# define BOOST_EXECUTION_CONTEXT 1
+# else
+# define BOOST_EXECUTION_CONTEXT 2
+# endif
#endif
#endif // BOOST_CONTEXT_DETAIL_CONFIG_H
diff --git a/boost/context/detail/disable_overload.hpp b/boost/context/detail/disable_overload.hpp
new file mode 100644
index 0000000000..c88f916e39
--- /dev/null
+++ b/boost/context/detail/disable_overload.hpp
@@ -0,0 +1,40 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONTEXT_DETAIL_DISABLE_OVERLOAD_H
+#define BOOST_CONTEXT_DETAIL_DISABLE_OVERLOAD_H
+
+#include <type_traits>
+
+#include <boost/config.hpp>
+
+#include <boost/context/detail/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+// http://ericniebler.com/2013/08/07/universal-references-and-the-copy-constructo/
+template< typename X, typename Y >
+using disable_overload =
+ typename std::enable_if<
+ ! std::is_base_of<
+ X,
+ typename std::decay< Y >::type
+ >::value
+ >::type;
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_DETAIL_DISABLE_OVERLOAD_H
diff --git a/boost/context/detail/exception.hpp b/boost/context/detail/exception.hpp
new file mode 100644
index 0000000000..8ffff6780a
--- /dev/null
+++ b/boost/context/detail/exception.hpp
@@ -0,0 +1,36 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONTEXT_DETAIL_EXCEPTION_H
+#define BOOST_CONTEXT_DETAIL_EXCEPTION_H
+
+#include <boost/config.hpp>
+
+#include <boost/context/detail/fcontext.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+struct forced_unwind {
+ fcontext_t fctx;
+
+ forced_unwind( fcontext_t fctx_) :
+ fctx( fctx_) {
+ }
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_DETAIL_EXCEPTION_H
diff --git a/boost/context/detail/exchange.hpp b/boost/context/detail/exchange.hpp
new file mode 100644
index 0000000000..c5ee91284e
--- /dev/null
+++ b/boost/context/detail/exchange.hpp
@@ -0,0 +1,36 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONTEXT_DETAIL_EXCHANGE_H
+#define BOOST_CONTEXT_DETAIL_EXCHANGE_H
+
+#include <algorithm>
+#include <utility>
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+template< typename T, typename U = T >
+T exchange( T & t, U && nv) {
+ T ov = std::move( t);
+ t = std::forward< U >( nv);
+ return ov;
+}
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_DETAIL_EXCHANGE_H
diff --git a/boost/context/fcontext.hpp b/boost/context/detail/fcontext.hpp
index 2ebcd46e38..00cb24d941 100644
--- a/boost/context/fcontext.hpp
+++ b/boost/context/detail/fcontext.hpp
@@ -4,16 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_CONTEXT_FCONTEXT_H
-#define BOOST_CONTEXT_FCONTEXT_H
-
-#if defined(__PGI)
-#include <stdint.h>
-#endif
-
-#if defined(_WIN32_WCE)
-typedef int intptr_t;
-#endif
+#ifndef BOOST_CONTEXT_DETAIL_FCONTEXT_H
+#define BOOST_CONTEXT_DETAIL_FCONTEXT_H
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
@@ -26,20 +18,29 @@ typedef int intptr_t;
namespace boost {
namespace context {
+namespace detail {
typedef void* fcontext_t;
+struct transfer_t {
+ fcontext_t fctx;
+ void * data;
+};
+
+extern "C" BOOST_CONTEXT_DECL
+transfer_t BOOST_CONTEXT_CALLDECL jump_fcontext( fcontext_t const to, void * vp);
extern "C" BOOST_CONTEXT_DECL
-intptr_t BOOST_CONTEXT_CALLDECL jump_fcontext( fcontext_t * ofc, fcontext_t nfc,
- intptr_t vp, bool preserve_fpu = false);
+fcontext_t BOOST_CONTEXT_CALLDECL make_fcontext( void * sp, std::size_t size, void (* fn)( transfer_t) );
+
+// based on an idea of Giovanni Derreta
extern "C" BOOST_CONTEXT_DECL
-fcontext_t BOOST_CONTEXT_CALLDECL make_fcontext( void * sp, std::size_t size, void (* fn)( intptr_t) );
+transfer_t BOOST_CONTEXT_CALLDECL ontop_fcontext( fcontext_t const to, void * vp, transfer_t (* fn)( transfer_t) );
-}}
+}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_CONTEXT_FCONTEXT_H
+#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_H
diff --git a/boost/context/detail/index_sequence.hpp b/boost/context/detail/index_sequence.hpp
new file mode 100644
index 0000000000..2d484ba062
--- /dev/null
+++ b/boost/context/detail/index_sequence.hpp
@@ -0,0 +1,72 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONTEXT_DETAIL_INDEX_SEQUENCE_H
+#define BOOST_CONTEXT_DETAIL_INDEX_SEQUENCE_H
+
+#include <cstddef>
+
+#include <boost/config.hpp>
+
+#include <boost/context/detail/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+#if ! defined(BOOST_CONTEXT_NO_CXX14_INTEGER_SEQUENCE)
+template< std::size_t ... I >
+using index_sequence = std::index_sequence< I ... >;
+template< std::size_t I >
+using make_index_sequence = std::make_index_sequence< I >;
+template< typename ... T >
+using index_sequence_for = std::index_sequence_for< T ... >;
+#else
+//http://stackoverflow.com/questions/17424477/implementation-c14-make-integer-sequence
+
+template< std::size_t ... I >
+struct index_sequence {
+ using type = index_sequence;
+ using value_type = std::size_t;
+ static constexpr std::size_t size() {
+ return sizeof ... (I);
+ }
+};
+
+template< typename Seq1, typename Seq2 >
+struct concat_sequence;
+
+template< std::size_t ... I1, std::size_t ... I2 >
+struct concat_sequence< index_sequence< I1 ... >, index_sequence< I2 ... > > : public index_sequence< I1 ..., (sizeof ... (I1)+I2) ... > {
+};
+
+template< std::size_t I >
+struct make_index_sequence : public concat_sequence< typename make_index_sequence< I/2 >::type,
+ typename make_index_sequence< I-I/2 >::type > {
+};
+
+template<>
+struct make_index_sequence< 0 > : public index_sequence<> {
+};
+template<>
+struct make_index_sequence< 1 > : public index_sequence< 0 > {
+};
+
+template< typename ... T >
+using index_sequence_for = make_index_sequence< sizeof ... (T) >;
+#endif
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_DETAIL_INDEX_SEQUENCE_H
diff --git a/boost/context/detail/invoke.hpp b/boost/context/detail/invoke.hpp
index f63d22c3ff..5ec54800e3 100644
--- a/boost/context/detail/invoke.hpp
+++ b/boost/context/detail/invoke.hpp
@@ -13,6 +13,8 @@
#include <boost/config.hpp>
+#include <boost/context/detail/config.hpp>
+
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
@@ -21,61 +23,27 @@ namespace boost {
namespace context {
namespace detail {
-# if _MSC_VER > 1800
+#if _MSC_VER > 1800
using std::invoke;
-# else
-template< typename Fn, typename ... Args >
-typename std::enable_if<
- ( ! std::is_member_pointer< Fn >::value &&
- ! std::is_function< Fn >::value &&
- ! std::is_function< typename std::remove_pointer< Fn >::type >::value
- ),
- typename std::result_of< Fn( Args ... ) >::type
->::type
-invoke( Fn & fn, Args && ... args) {
- return fn( std::forward< Args >( args) ... );
-}
-
+#else
template< typename Fn, typename ... Args >
typename std::enable_if<
- ( std::is_member_pointer< Fn >::value &&
- ! std::is_function< Fn >::value &&
- ! std::is_function< typename std::remove_pointer< Fn >::type >::value
- ),
- typename std::result_of< Fn( Args ... ) >::type
+ std::is_member_pointer< typename std::decay< Fn >::type >::value,
+ typename std::result_of< Fn &&( Args && ... ) >::type
>::type
-invoke( Fn & fn, Args && ... args) {
- return std::mem_fn( fn)( std::forward< Args >( args) ... );
+invoke( Fn && fn, Args && ... args) {
+ return std::mem_fn( fn)( std::forward< Args >( args) ... );
}
template< typename Fn, typename ... Args >
typename std::enable_if<
- ( std::is_pointer< Fn >::value &&
- std::is_function< typename std::remove_pointer< Fn >::type >::value
- ),
- typename std::result_of< Fn( Args ... ) >::type
+ ! std::is_member_pointer< typename std::decay< Fn >::type >::value,
+ typename std::result_of< Fn &&( Args && ... ) >::type
>::type
-invoke( Fn fn, Args && ... args) {
- return fn( std::forward< Args >( args) ... );
-}
-# endif
-
-template< typename Fn, typename Tpl, std::size_t... I >
-decltype( auto) do_invoke( Fn && fn, Tpl && tpl, std::index_sequence< I ... >) {
- return invoke( fn,
- // std::tuple_element<> does not perfect forwarding
- std::forward< decltype( std::get< I >( std::declval< typename std::decay< Tpl >::type >() ) ) >(
- std::get< I >( std::forward< typename std::decay< Tpl >::type >( tpl) ) ) ... );
-}
-
-
-template< typename Fn, typename Tpl >
-decltype( auto) do_invoke( Fn && fn, Tpl && tpl) {
- constexpr auto Size = std::tuple_size< typename std::decay< Tpl >::type >::value;
- return do_invoke( std::forward< Fn >( fn),
- std::forward< Tpl >( tpl),
- std::make_index_sequence< Size >{});
+invoke( Fn && fn, Args && ... args) {
+ return std::forward< Fn >( fn)( std::forward< Args >( args) ... );
}
+#endif
}}}
diff --git a/boost/context/detail/tuple.hpp b/boost/context/detail/tuple.hpp
new file mode 100644
index 0000000000..e1b2f867a7
--- /dev/null
+++ b/boost/context/detail/tuple.hpp
@@ -0,0 +1,129 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONTEXT_DETAIL_TUPLE_H
+#define BOOST_CONTEXT_DETAIL_TUPLE_H
+
+#include <tuple>
+#include <utility>
+
+#include <boost/config.hpp>
+
+#include <boost/context/detail/config.hpp>
+#include <boost/context/detail/index_sequence.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+template< typename ... S, typename ... T, std::size_t ... I >
+void
+head_impl( std::tuple< S ... > & s,
+ std::tuple< T ... > & t, index_sequence< I ... >) {
+ t = std::tuple< T ... >{ std::get< I >( s) ... };
+}
+
+template< typename ... S, typename ... T, std::size_t ... I >
+void
+head_impl( std::tuple< S ... > && s,
+ std::tuple< T ... > & t, index_sequence< I ... >) {
+ t = std::tuple< T ... >{ std::get< I >( std::move( s) ) ... };
+}
+
+template< typename ... S, std::size_t ... I1, typename ... T, std::size_t ... I2 >
+void
+tail_impl( std::tuple< S ... > & s, index_sequence< I1 ... >,
+ std::tuple< T ... > & t, index_sequence< I2 ... >) {
+ constexpr std::size_t Idx = (sizeof...(I1)) - (sizeof...(I2));
+ t = std::tuple< T ... >{ std::get< (Idx + I2) >( s) ... };
+}
+
+template< typename ... S, std::size_t ... I1, typename ... T, std::size_t ... I2 >
+void
+tail_impl( std::tuple< S ... > && s, index_sequence< I1 ... >,
+ std::tuple< T ... > & t, index_sequence< I2 ... >) {
+ constexpr std::size_t Idx = (sizeof...(I1)) - (sizeof...(I2));
+ t = std::tuple< T ... >{ std::get< (Idx + I2) >( std::move( s) ) ... };
+}
+
+template< typename ... T >
+class tuple_head;
+
+template< typename ... T >
+class tuple_head< std::tuple< T ... > > {
+private:
+ std::tuple< T ... > & t_;
+
+public:
+ tuple_head( std::tuple< T ... > & t) noexcept :
+ t_( t) {
+ }
+
+ template< typename ... S >
+ void operator=( std::tuple< S ... > & s) {
+ static_assert((sizeof...(T)) <= (sizeof...(S)), "invalid tuple size");
+ head_impl( s,
+ t_, index_sequence_for< T ... >{} );
+ }
+ template< typename ... S >
+ void operator=( std::tuple< S ... > && s) {
+ static_assert((sizeof...(T)) <= (sizeof...(S)), "invalid tuple size");
+ head_impl( std::move( s),
+ t_, index_sequence_for< T ... >{} );
+ }
+};
+
+template< typename ... T >
+class tuple_tail;
+
+template< typename ... T >
+class tuple_tail< std::tuple< T ... > > {
+private:
+ std::tuple< T ... > & t_;
+
+public:
+ tuple_tail( std::tuple< T ... > & t) noexcept :
+ t_( t) {
+ }
+
+ template< typename ... S >
+ void operator=( std::tuple< S ... > & s) {
+ static_assert((sizeof...(T)) <= (sizeof...(S)), "invalid tuple size");
+ tail_impl( s, index_sequence_for< S ... >{},
+ t_, index_sequence_for< T ... >{} );
+ }
+
+ template< typename ... S >
+ void operator=( std::tuple< S ... > && s) {
+ static_assert((sizeof...(T)) <= (sizeof...(S)), "invalid tuple size");
+ tail_impl( std::move( s), index_sequence_for< S ... >{},
+ t_, index_sequence_for< T ... >{} );
+ }
+};
+
+template< typename ... T >
+detail::tuple_head< std::tuple< T ... > >
+head( std::tuple< T ... > & tpl) {
+ return tuple_head< std::tuple< T ... > >{ tpl };
+}
+
+template< typename ... T >
+detail::tuple_tail< std::tuple< T ... > >
+tail( std::tuple< T ... > & tpl) {
+ return tuple_tail< std::tuple< T ... > >{ tpl };
+}
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_DETAIL_TUPLE_H
diff --git a/boost/context/execution_context.hpp b/boost/context/execution_context.hpp
index 97b1d4e70a..9d9294f91d 100644
--- a/boost/context/execution_context.hpp
+++ b/boost/context/execution_context.hpp
@@ -4,8 +4,12 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#if defined(BOOST_USE_WINFIBERS)
-#include <boost/context/execution_context_winfib.ipp>
-#else
-#include <boost/context/execution_context.ipp>
+#include <boost/context/detail/config.hpp>
+
+#if ! defined(BOOST_CONTEXT_NO_CXX11)
+# if (defined(BOOST_EXECUTION_CONTEXT) && (BOOST_EXECUTION_CONTEXT == 1))
+# include <boost/context/execution_context_v1.hpp>
+# else
+# include <boost/context/execution_context_v2.hpp>
+# endif
#endif
diff --git a/boost/context/execution_context.ipp b/boost/context/execution_context.ipp
deleted file mode 100644
index ec5443297f..0000000000
--- a/boost/context/execution_context.ipp
+++ /dev/null
@@ -1,452 +0,0 @@
-
-// Copyright Oliver Kowalke 2014.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_CONTEXT_EXECUTION_CONTEXT_H
-#define BOOST_CONTEXT_EXECUTION_CONTEXT_H
-
-#include <boost/context/detail/config.hpp>
-
-#if ! defined(BOOST_CONTEXT_NO_EXECUTION_CONTEXT)
-
-# include <algorithm>
-# include <atomic>
-# include <cstddef>
-# include <cstdint>
-# include <cstdlib>
-# include <functional>
-# include <memory>
-# include <ostream>
-# include <tuple>
-# include <utility>
-
-# include <boost/assert.hpp>
-# include <boost/config.hpp>
-# include <boost/context/fcontext.hpp>
-# include <boost/intrusive_ptr.hpp>
-
-# include <boost/context/detail/invoke.hpp>
-# include <boost/context/fixedsize_stack.hpp>
-# include <boost/context/stack_context.hpp>
-# include <boost/context/segmented_stack.hpp>
-
-# ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-# endif
-
-# if defined(BOOST_USE_SEGMENTED_STACKS)
-extern "C" {
-
-void __splitstack_getcontext( void * [BOOST_CONTEXT_SEGMENTS]);
-
-void __splitstack_setcontext( void * [BOOST_CONTEXT_SEGMENTS]);
-
-}
-# endif
-
-namespace boost {
-namespace context {
-namespace detail {
-
-struct activation_record {
- typedef boost::intrusive_ptr< activation_record > ptr_t;
-
- enum flag_t {
- flag_main_ctx = 1 << 1,
- flag_preserve_fpu = 1 << 2
- };
-
- thread_local static ptr_t current_rec;
-
- std::atomic< std::size_t > use_count;
- fcontext_t fctx;
- stack_context sctx;
- int flags;
-
- // used for toplevel-context
- // (e.g. main context, thread-entry context)
- activation_record() noexcept :
- use_count( 0),
- fctx( nullptr),
- sctx(),
- flags( flag_main_ctx) {
- }
-
- activation_record( fcontext_t fctx_, stack_context sctx_) noexcept :
- use_count( 0),
- fctx( fctx_),
- sctx( sctx_),
- flags( 0) {
- }
-
- virtual ~activation_record() noexcept = default;
-
- void * resume( void * vp, bool fpu) noexcept {
- // store current activation record in local variable
- activation_record * from = current_rec.get();
- // store `this` in static, thread local pointer
- // `this` will become the active (running) context
- // returned by execution_context::current()
- current_rec = this;
- // set FPU flag
- if (fpu) {
- from->flags |= flag_preserve_fpu;
- this->flags |= flag_preserve_fpu;
- } else {
- from->flags &= ~flag_preserve_fpu;
- this->flags &= ~flag_preserve_fpu;
- }
-# if defined(BOOST_USE_SEGMENTED_STACKS)
- // adjust segmented stack properties
- __splitstack_getcontext( from->sctx.segments_ctx);
- __splitstack_setcontext( sctx.segments_ctx);
-# endif
- // context switch from parent context to `this`-context
- intptr_t ret = jump_fcontext( & from->fctx, fctx, reinterpret_cast< intptr_t >( vp), fpu);
- // parent context resumed
- return reinterpret_cast< void * >( ret);
- }
-
- virtual void deallocate() {
- delete this;
- }
-
- friend void intrusive_ptr_add_ref( activation_record * ar) {
- ++ar->use_count;
- }
-
- friend void intrusive_ptr_release( activation_record * ar) {
- BOOST_ASSERT( nullptr != ar);
-
- if ( 0 == --ar->use_count) {
- ar->deallocate();
- }
- }
-};
-
-struct activation_record_initializer {
- activation_record_initializer();
- ~activation_record_initializer();
-};
-
-template< typename Fn, typename Tpl, typename StackAlloc >
-class capture_record : public activation_record {
-private:
- StackAlloc salloc_;
- Fn fn_;
- Tpl tpl_;
- activation_record * caller_;
-
- static void destroy( capture_record * p) {
- StackAlloc salloc( p->salloc_);
- stack_context sctx( p->sctx);
- // deallocate activation record
- p->~capture_record();
- // destroy stack with stack allocator
- salloc.deallocate( sctx);
- }
-
-public:
- explicit capture_record(
- stack_context sctx, StackAlloc const& salloc,
- fcontext_t fctx,
- Fn && fn, Tpl && tpl,
- activation_record * caller) noexcept :
- activation_record( fctx, sctx),
- salloc_( salloc),
- fn_( std::forward< Fn >( fn) ),
- tpl_( std::forward< Tpl >( tpl) ),
- caller_( caller) {
- }
-
- void deallocate() override final {
- destroy( this);
- }
-
- void run() noexcept {
- try {
- void * vp = caller_->resume( caller_, true);
- do_invoke( fn_, std::tuple_cat( tpl_, std::tie( vp) ) );
- } catch (...) {
- std::terminate();
- }
- BOOST_ASSERT( 0 == (flags & flag_main_ctx) );
- }
-};
-
-}
-
-struct preallocated {
- void * sp;
- std::size_t size;
- stack_context sctx;
-
- preallocated( void * sp_, std::size_t size_, stack_context sctx_) noexcept :
- sp( sp_), size( size_), sctx( sctx_) {
- }
-};
-
-class BOOST_CONTEXT_DECL execution_context {
-private:
- // tampoline function
- // entered if the execution context
- // is resumed for the first time
- template< typename AR >
- static void entry_func( intptr_t p) noexcept {
- BOOST_ASSERT( 0 != p);
-
- AR * ar( reinterpret_cast< AR * >( p) );
- BOOST_ASSERT( nullptr != ar);
-
- // start execution of toplevel context-function
- ar->run();
- }
-
- typedef boost::intrusive_ptr< detail::activation_record > ptr_t;
-
- ptr_t ptr_;
-
- template< typename StackAlloc, typename Fn ,typename Tpl >
- static detail::activation_record * create_context(
- StackAlloc salloc,
- Fn && fn, Tpl && tpl) {
- typedef detail::capture_record< Fn, Tpl, StackAlloc > capture_t;
-
- stack_context sctx( salloc.allocate() );
- // reserve space for control structure
-#if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
- std::size_t size = sctx.size - sizeof( capture_t);
- void * sp = static_cast< char * >( sctx.sp) - sizeof( capture_t);
-#else
- constexpr std::size_t func_alignment = 64; // alignof( capture_t);
- constexpr std::size_t func_size = sizeof( capture_t);
- // reserve space on stack
- void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
- // align sp pointer
- std::size_t space = func_size + func_alignment;
- sp = std::align( func_alignment, func_size, sp, space);
- BOOST_ASSERT( nullptr != sp);
- // calculate remaining size
- std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
-#endif
- // create fast-context
- fcontext_t fctx = make_fcontext( sp, size, & execution_context::entry_func< capture_t >);
- BOOST_ASSERT( nullptr != fctx);
- // get current activation record
- ptr_t curr = execution_context::current().ptr_;
- // placment new for control structure on fast-context stack
- return new ( sp) capture_t(
- sctx, salloc, fctx, std::forward< Fn >( fn), std::forward< Tpl >( tpl), curr.get() );
- }
-
- template< typename StackAlloc, typename Fn , typename Tpl >
- static detail::activation_record * create_context(
- preallocated palloc, StackAlloc salloc,
- Fn && fn, Tpl && tpl) {
- typedef detail::capture_record< Fn, Tpl, StackAlloc > capture_t;
-
- // reserve space for control structure
-#if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
- std::size_t size = palloc.size - sizeof( capture_t);
- void * sp = static_cast< char * >( palloc.sp) - sizeof( capture_t);
-#else
- constexpr std::size_t func_alignment = 64; // alignof( capture_t);
- constexpr std::size_t func_size = sizeof( capture_t);
- // reserve space on stack
- void * sp = static_cast< char * >( palloc.sp) - func_size - func_alignment;
- // align sp pointer
- std::size_t space = func_size + func_alignment;
- sp = std::align( func_alignment, func_size, sp, space);
- BOOST_ASSERT( nullptr != sp);
- // calculate remaining size
- std::size_t size = palloc.size - ( static_cast< char * >( palloc.sp) - static_cast< char * >( sp) );
-#endif
- // create fast-context
- fcontext_t fctx = make_fcontext( sp, size, & execution_context::entry_func< capture_t >);
- BOOST_ASSERT( nullptr != fctx);
- // get current activation record
- ptr_t curr = execution_context::current().ptr_;
- // placment new for control structure on fast-context stack
- return new ( sp) capture_t(
- palloc.sctx, salloc, fctx, std::forward< Fn >( fn), std::forward< Tpl >( tpl), curr.get() );
- }
-
- execution_context() :
- // default constructed with current activation_record
- ptr_( detail::activation_record::current_rec) {
- }
-
-public:
- static execution_context current() noexcept;
-
-# if defined(BOOST_USE_SEGMENTED_STACKS)
- template< typename Fn, typename ... Args >
- explicit execution_context( Fn && fn, Args && ... args) :
- // deferred execution of fn and its arguments
- // arguments are stored in std::tuple<>
- // non-type template parameter pack via std::index_sequence_for<>
- // preserves the number of arguments
- // used to extract the function arguments from std::tuple<>
- ptr_( create_context( segmented_stack(),
- std::forward< Fn >( fn),
- std::make_tuple( std::forward< Args >( args) ...) ) ) {
- ptr_->resume( ptr_.get(), true);
- }
-
- template< typename Fn, typename ... Args >
- explicit execution_context( std::allocator_arg_t, segmented_stack salloc, Fn && fn, Args && ... args) :
- // deferred execution of fn and its arguments
- // arguments are stored in std::tuple<>
- // non-type template parameter pack via std::index_sequence_for<>
- // preserves the number of arguments
- // used to extract the function arguments from std::tuple<>
- ptr_( create_context( salloc,
- std::forward< Fn >( fn),
- std::make_tuple( std::forward< Args >( args) ...) ) ) {
- ptr_->resume( ptr_.get(), true);
- }
-
- template< typename Fn, typename ... Args >
- explicit execution_context( std::allocator_arg_t, preallocated palloc, segmented_stack salloc, Fn && fn, Args && ... args) :
- // deferred execution of fn and its arguments
- // arguments are stored in std::tuple<>
- // non-type template parameter pack via std::index_sequence_for<>
- // preserves the number of arguments
- // used to extract the function arguments from std::tuple<>
- ptr_( create_context( palloc, salloc,
- std::forward< Fn >( fn),
- std::make_tuple( std::forward< Args >( args) ...) ) ) {
- ptr_->resume( ptr_.get(), true);
- }
-# else
- template< typename Fn, typename ... Args >
- explicit execution_context( Fn && fn, Args && ... args) :
- // deferred execution of fn and its arguments
- // arguments are stored in std::tuple<>
- // non-type template parameter pack via std::index_sequence_for<>
- // preserves the number of arguments
- // used to extract the function arguments from std::tuple<>
- ptr_( create_context( fixedsize_stack(),
- std::forward< Fn >( fn),
- std::make_tuple( std::forward< Args >( args) ...) ) ) {
- ptr_->resume( ptr_.get(), true);
- }
-
- template< typename StackAlloc, typename Fn, typename ... Args >
- explicit execution_context( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Args && ... args) :
- // deferred execution of fn and its arguments
- // arguments are stored in std::tuple<>
- // non-type template parameter pack via std::index_sequence_for<>
- // preserves the number of arguments
- // used to extract the function arguments from std::tuple<>
- ptr_( create_context( salloc,
- std::forward< Fn >( fn),
- std::make_tuple( std::forward< Args >( args) ...) ) ) {
- ptr_->resume( ptr_.get(), true);
- }
-
- template< typename StackAlloc, typename Fn, typename ... Args >
- explicit execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Args && ... args) :
- // deferred execution of fn and its arguments
- // arguments are stored in std::tuple<>
- // non-type template parameter pack via std::index_sequence_for<>
- // preserves the number of arguments
- // used to extract the function arguments from std::tuple<>
- ptr_( create_context( palloc, salloc,
- std::forward< Fn >( fn),
- std::make_tuple( std::forward< Args >( args) ...) ) ) {
- ptr_->resume( ptr_.get(), true);
- }
-# endif
-
- execution_context( execution_context const& other) noexcept :
- ptr_( other.ptr_) {
- }
-
- execution_context( execution_context && other) noexcept :
- ptr_( other.ptr_) {
- other.ptr_.reset();
- }
-
- execution_context & operator=( execution_context const& other) noexcept {
- if ( this != & other) {
- ptr_ = other.ptr_;
- }
- return * this;
- }
-
- execution_context & operator=( execution_context && other) noexcept {
- if ( this != & other) {
- ptr_ = other.ptr_;
- other.ptr_.reset();
- }
- return * this;
- }
-
- void * operator()( void * vp = nullptr, bool preserve_fpu = false) noexcept {
- return ptr_->resume( vp, preserve_fpu);
- }
-
- explicit operator bool() const noexcept {
- return nullptr != ptr_.get();
- }
-
- bool operator!() const noexcept {
- return nullptr == ptr_.get();
- }
-
- bool operator==( execution_context const& other) const noexcept {
- return ptr_ == other.ptr_;
- }
-
- bool operator!=( execution_context const& other) const noexcept {
- return ptr_ != other.ptr_;
- }
-
- bool operator<( execution_context const& other) const noexcept {
- return ptr_ < other.ptr_;
- }
-
- bool operator>( execution_context const& other) const noexcept {
- return other.ptr_ < ptr_;
- }
-
- bool operator<=( execution_context const& other) const noexcept {
- return ! ( * this > other);
- }
-
- bool operator>=( execution_context const& other) const noexcept {
- return ! ( * this < other);
- }
-
- template< typename charT, class traitsT >
- friend std::basic_ostream< charT, traitsT > &
- operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other) {
- if ( nullptr != other.ptr_) {
- return os << other.ptr_;
- } else {
- return os << "{not-valid}";
- }
- }
-
- void swap( execution_context & other) noexcept {
- ptr_.swap( other.ptr_);
- }
-};
-
-inline
-void swap( execution_context & l, execution_context & r) noexcept {
- l.swap( r);
-}
-
-}}
-
-# ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-# endif
-
-#endif
-
-#endif // BOOST_CONTEXT_EXECUTION_CONTEXT_H
diff --git a/boost/context/execution_context_v1.hpp b/boost/context/execution_context_v1.hpp
new file mode 100644
index 0000000000..6881354c88
--- /dev/null
+++ b/boost/context/execution_context_v1.hpp
@@ -0,0 +1,487 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONTEXT_EXECUTION_CONTEXT_H
+#define BOOST_CONTEXT_EXECUTION_CONTEXT_H
+
+#include <boost/context/detail/config.hpp>
+
+#include <algorithm>
+#include <atomic>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <functional>
+#include <memory>
+#include <ostream>
+#include <tuple>
+#include <utility>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/intrusive_ptr.hpp>
+
+#include <boost/context/detail/apply.hpp>
+#include <boost/context/detail/disable_overload.hpp>
+#include <boost/context/detail/fcontext.hpp>
+#include <boost/context/fixedsize_stack.hpp>
+#include <boost/context/flags.hpp>
+#include <boost/context/preallocated.hpp>
+#include <boost/context/segmented_stack.hpp>
+#include <boost/context/stack_context.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+extern "C" {
+void __splitstack_getcontext( void * [BOOST_CONTEXT_SEGMENTS]);
+void __splitstack_setcontext( void * [BOOST_CONTEXT_SEGMENTS]);
+}
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+template< typename Fn >
+transfer_t context_ontop( transfer_t);
+
+struct activation_record;
+
+struct data_t {
+ activation_record * from;
+ void * data;
+};
+
+struct activation_record {
+ typedef boost::intrusive_ptr< activation_record > ptr_t;
+
+ thread_local static ptr_t current_rec;
+
+ std::atomic< std::size_t > use_count{ 0 };
+ fcontext_t fctx{ nullptr };
+ stack_context sctx{};
+ bool main_ctx{ true };
+
+ // used for toplevel-context
+ // (e.g. main context, thread-entry context)
+ constexpr activation_record() = default;
+
+ activation_record( fcontext_t fctx_, stack_context sctx_) noexcept :
+ fctx{ fctx_ },
+ sctx( sctx_ ), // sctx{ sctx_ } - clang-3.6: no viable conversion from 'boost::context::stack_context' to 'std::size_t'
+ main_ctx{ false } {
+ }
+
+ virtual ~activation_record() = default;
+
+ bool is_main_context() const noexcept {
+ return main_ctx;
+ }
+
+ void * resume( void * vp) {
+ // store current activation record in local variable
+ auto from = current_rec.get();
+ // store `this` in static, thread local pointer
+ // `this` will become the active (running) context
+ // returned by execution_context::current()
+ current_rec = this;
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+ // adjust segmented stack properties
+ __splitstack_getcontext( from->sctx.segments_ctx);
+ __splitstack_setcontext( sctx.segments_ctx);
+#endif
+ data_t d = { from, vp };
+ // context switch from parent context to `this`-context
+ transfer_t t = jump_fcontext( fctx, & d);
+ data_t * dp = reinterpret_cast< data_t * >( t.data);
+ dp->from->fctx = t.fctx;
+ // parent context resumed
+ return dp->data;
+ }
+
+ template< typename Fn >
+ void * resume_ontop( void * data, Fn && fn) {
+ // store current activation record in local variable
+ activation_record * from = current_rec.get();
+ // store `this` in static, thread local pointer
+ // `this` will become the active (running) context
+ // returned by execution_context::current()
+ current_rec = this;
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+ // adjust segmented stack properties
+ __splitstack_getcontext( from->sctx.segments_ctx);
+ __splitstack_setcontext( sctx.segments_ctx);
+#endif
+ std::tuple< void *, Fn > p = std::forward_as_tuple( data, fn);
+ data_t d = { from, & p };
+ // context switch from parent context to `this`-context
+ // execute Fn( Tpl) on top of `this`
+ transfer_t t = ontop_fcontext( fctx, & d, context_ontop< Fn >);
+ data_t * dp = reinterpret_cast< data_t * >( t.data);
+ dp->from->fctx = t.fctx;
+ // parent context resumed
+ return dp->data;
+ }
+
+ virtual void deallocate() noexcept {
+ }
+
+ friend void intrusive_ptr_add_ref( activation_record * ar) noexcept {
+ ++ar->use_count;
+ }
+
+ friend void intrusive_ptr_release( activation_record * ar) noexcept {
+ BOOST_ASSERT( nullptr != ar);
+ if ( 0 == --ar->use_count) {
+ ar->deallocate();
+ }
+ }
+};
+
+struct activation_record_initializer {
+ activation_record_initializer() noexcept;
+ ~activation_record_initializer();
+};
+
+template< typename Fn >
+transfer_t context_ontop( transfer_t t) {
+ data_t * dp = reinterpret_cast< data_t * >( t.data);
+ dp->from->fctx = t.fctx;
+ auto tpl = reinterpret_cast< std::tuple< void *, Fn > * >( dp->data);
+ BOOST_ASSERT( nullptr != tpl);
+ auto data = std::get< 0 >( * tpl);
+ typename std::decay< Fn >::type fn = std::forward< Fn >( std::get< 1 >( * tpl) );
+ dp->data = apply( fn, std::tie( data) );
+ return { t.fctx, dp };
+}
+
+template< typename StackAlloc, typename Fn, typename ... Args >
+class capture_record : public activation_record {
+private:
+ StackAlloc salloc_;
+ typename std::decay< Fn >::type fn_;
+ std::tuple< typename std::decay< Args >::type ... > args_;
+ activation_record * caller_;
+
+ static void destroy( capture_record * p) noexcept {
+ StackAlloc salloc = p->salloc_;
+ stack_context sctx = p->sctx;
+ // deallocate activation record
+ p->~capture_record();
+ // destroy stack with stack allocator
+ salloc.deallocate( sctx);
+ }
+
+public:
+ capture_record( stack_context sctx, StackAlloc const& salloc,
+ fcontext_t fctx,
+ activation_record * caller,
+ Fn && fn, Args && ... args) noexcept :
+ activation_record{ fctx, sctx },
+ salloc_{ salloc },
+ fn_( std::forward< Fn >( fn) ),
+ args_( std::forward< Args >( args) ... ),
+ caller_{ caller } {
+ }
+
+ void deallocate() noexcept override final {
+ destroy( this);
+ }
+
+ void run() {
+ auto data = caller_->resume( nullptr);
+ apply( fn_, std::tuple_cat( args_, std::tie( data) ) );
+ BOOST_ASSERT_MSG( ! main_ctx, "main-context does not execute activation-record::run()");
+ }
+};
+
+}
+
+class BOOST_CONTEXT_DECL execution_context {
+private:
+ // tampoline function
+ // entered if the execution context
+ // is resumed for the first time
+ template< typename AR >
+ static void entry_func( detail::transfer_t t) noexcept {
+ detail::data_t * dp = reinterpret_cast< detail::data_t * >( t.data);
+ AR * ar = static_cast< AR * >( dp->data);
+ BOOST_ASSERT( nullptr != ar);
+ dp->from->fctx = t.fctx;
+ // start execution of toplevel context-function
+ ar->run();
+ }
+
+ typedef boost::intrusive_ptr< detail::activation_record > ptr_t;
+
+ ptr_t ptr_;
+
+ template< typename StackAlloc, typename Fn, typename ... Args >
+ static detail::activation_record * create_context( StackAlloc salloc,
+ Fn && fn, Args && ... args) {
+ typedef detail::capture_record<
+ StackAlloc, Fn, Args ...
+ > capture_t;
+
+ auto sctx = salloc.allocate();
+ // reserve space for control structure
+#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
+ const std::size_t size = sctx.size - sizeof( capture_t);
+ void * sp = static_cast< char * >( sctx.sp) - sizeof( capture_t);
+#else
+ constexpr std::size_t func_alignment = 64; // alignof( capture_t);
+ constexpr std::size_t func_size = sizeof( capture_t);
+ // reserve space on stack
+ void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
+ // align sp pointer
+ std::size_t space = func_size + func_alignment;
+ sp = std::align( func_alignment, func_size, sp, space);
+ BOOST_ASSERT( nullptr != sp);
+ // calculate remaining size
+ const std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
+#endif
+ // create fast-context
+ const detail::fcontext_t fctx = detail::make_fcontext( sp, size, & execution_context::entry_func< capture_t >);
+ BOOST_ASSERT( nullptr != fctx);
+ // get current activation record
+ auto curr = execution_context::current().ptr_;
+ // placment new for control structure on fast-context stack
+ return ::new ( sp) capture_t{
+ sctx, salloc, fctx, curr.get(), std::forward< Fn >( fn), std::forward< Args >( args) ... };
+ }
+
+ template< typename StackAlloc, typename Fn, typename ... Args >
+ static detail::activation_record * create_context( preallocated palloc, StackAlloc salloc,
+ Fn && fn, Args && ... args) {
+ typedef detail::capture_record<
+ StackAlloc, Fn, Args ...
+ > capture_t;
+
+ // reserve space for control structure
+#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
+ const std::size_t size = palloc.size - sizeof( capture_t);
+ void * sp = static_cast< char * >( palloc.sp) - sizeof( capture_t);
+#else
+ constexpr std::size_t func_alignment = 64; // alignof( capture_t);
+ constexpr std::size_t func_size = sizeof( capture_t);
+ // reserve space on stack
+ void * sp = static_cast< char * >( palloc.sp) - func_size - func_alignment;
+ // align sp pointer
+ std::size_t space = func_size + func_alignment;
+ sp = std::align( func_alignment, func_size, sp, space);
+ BOOST_ASSERT( nullptr != sp);
+ // calculate remaining size
+ const std::size_t size = palloc.size - ( static_cast< char * >( palloc.sp) - static_cast< char * >( sp) );
+#endif
+ // create fast-context
+ const detail::fcontext_t fctx = detail::make_fcontext( sp, size, & execution_context::entry_func< capture_t >);
+ BOOST_ASSERT( nullptr != fctx);
+ // get current activation record
+ auto curr = execution_context::current().ptr_;
+ // placment new for control structure on fast-context stack
+ return ::new ( sp) capture_t{
+ palloc.sctx, salloc, fctx, curr.get(), std::forward< Fn >( fn), std::forward< Args >( args) ... };
+ }
+
+ execution_context() noexcept :
+ // default constructed with current activation_record
+ ptr_{ detail::activation_record::current_rec } {
+ }
+
+public:
+ static execution_context current() noexcept;
+
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+ template< typename Fn,
+ typename ... Args,
+ typename = detail::disable_overload< execution_context, Fn >
+ >
+ execution_context( Fn && fn, Args && ... args) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ ptr_{ create_context( segmented_stack(),
+ std::forward< Fn >( fn),
+ std::forward< Args >( args) ...) } {
+ ptr_->resume( ptr_.get() );
+ }
+
+ template< typename Fn,
+ typename ... Args
+ >
+ execution_context( std::allocator_arg_t, segmented_stack salloc, Fn && fn, Args && ... args) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ ptr_{ create_context( salloc,
+ std::forward< Fn >( fn),
+ std::forward< Args >( args) ...) } {
+ ptr_->resume( ptr_.get() );
+ }
+
+ template< typename Fn,
+ typename ... Args
+ >
+ execution_context( std::allocator_arg_t, preallocated palloc, segmented_stack salloc, Fn && fn, Args && ... args) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ ptr_{ create_context( palloc, salloc,
+ std::forward< Fn >( fn),
+ std::forward< Args >( args) ...) } {
+ ptr_->resume( ptr_.get() );
+ }
+#else
+ template< typename Fn,
+ typename ... Args,
+ typename = detail::disable_overload< execution_context, Fn >
+ >
+ execution_context( Fn && fn, Args && ... args) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ ptr_{ create_context( fixedsize_stack(),
+ std::forward< Fn >( fn),
+ std::forward< Args >( args) ...) } {
+ ptr_->resume( ptr_.get() );
+ }
+
+ template< typename StackAlloc,
+ typename Fn,
+ typename ... Args
+ >
+ execution_context( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Args && ... args) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ ptr_{ create_context( salloc,
+ std::forward< Fn >( fn),
+ std::forward< Args >( args) ...) } {
+ ptr_->resume( ptr_.get() );
+ }
+
+ template< typename StackAlloc,
+ typename Fn,
+ typename ... Args
+ >
+ execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Args && ... args) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ ptr_{ create_context( palloc, salloc,
+ std::forward< Fn >( fn),
+ std::forward< Args >( args) ...) } {
+ ptr_->resume( ptr_.get() );
+ }
+#endif
+
+ execution_context( execution_context const& other) noexcept :
+ ptr_{ other.ptr_ } {
+ }
+
+ execution_context( execution_context && other) noexcept :
+ ptr_{ other.ptr_ } {
+ other.ptr_.reset();
+ }
+
+ execution_context & operator=( execution_context const& other) noexcept {
+ // intrusive_ptr<> does not test for self-assignment
+ if ( this == & other) return * this;
+ ptr_ = other.ptr_;
+ return * this;
+ }
+
+ execution_context & operator=( execution_context && other) noexcept {
+ if ( this == & other) return * this;
+ execution_context tmp{ std::move( other) };
+ swap( tmp);
+ return * this;
+ }
+
+ void * operator()( void * vp = nullptr) {
+ return ptr_->resume( vp);
+ }
+
+ template< typename Fn >
+ void * operator()( exec_ontop_arg_t, Fn && fn, void * vp = nullptr) {
+ return ptr_->resume_ontop( vp,
+ std::forward< Fn >( fn) );
+ }
+
+ explicit operator bool() const noexcept {
+ return nullptr != ptr_.get();
+ }
+
+ bool operator!() const noexcept {
+ return nullptr == ptr_.get();
+ }
+
+ bool operator==( execution_context const& other) const noexcept {
+ return ptr_ == other.ptr_;
+ }
+
+ bool operator!=( execution_context const& other) const noexcept {
+ return ptr_ != other.ptr_;
+ }
+
+ bool operator<( execution_context const& other) const noexcept {
+ return ptr_ < other.ptr_;
+ }
+
+ bool operator>( execution_context const& other) const noexcept {
+ return other.ptr_ < ptr_;
+ }
+
+ bool operator<=( execution_context const& other) const noexcept {
+ return ! ( * this > other);
+ }
+
+ bool operator>=( execution_context const& other) const noexcept {
+ return ! ( * this < other);
+ }
+
+ template< typename charT, class traitsT >
+ friend std::basic_ostream< charT, traitsT > &
+ operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other) {
+ if ( nullptr != other.ptr_) {
+ return os << other.ptr_;
+ } else {
+ return os << "{not-a-context}";
+ }
+ }
+
+ void swap( execution_context & other) noexcept {
+ ptr_.swap( other.ptr_);
+ }
+};
+
+inline
+void swap( execution_context & l, execution_context & r) noexcept {
+ l.swap( r);
+}
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_EXECUTION_CONTEXT_H
diff --git a/boost/context/execution_context_v2.hpp b/boost/context/execution_context_v2.hpp
new file mode 100644
index 0000000000..1bc5f868d0
--- /dev/null
+++ b/boost/context/execution_context_v2.hpp
@@ -0,0 +1,395 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONTEXT_EXECUTION_CONTEXT_H
+#define BOOST_CONTEXT_EXECUTION_CONTEXT_H
+
+#include <boost/context/detail/config.hpp>
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <functional>
+#include <memory>
+#include <ostream>
+#include <tuple>
+#include <utility>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/intrusive_ptr.hpp>
+
+#include <boost/context/detail/apply.hpp>
+#include <boost/context/detail/disable_overload.hpp>
+#include <boost/context/detail/exception.hpp>
+#include <boost/context/detail/exchange.hpp>
+#include <boost/context/detail/fcontext.hpp>
+#include <boost/context/detail/tuple.hpp>
+#include <boost/context/fixedsize_stack.hpp>
+#include <boost/context/flags.hpp>
+#include <boost/context/preallocated.hpp>
+#include <boost/context/segmented_stack.hpp>
+#include <boost/context/stack_context.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+namespace detail {
+
+inline
+transfer_t context_unwind( transfer_t t) {
+ throw forced_unwind( t.fctx);
+ return { nullptr, nullptr };
+}
+
+template< typename Rec >
+transfer_t context_exit( transfer_t t) noexcept {
+ Rec * rec = static_cast< Rec * >( t.data);
+ // destroy context stack
+ rec->deallocate();
+ return { nullptr, nullptr };
+}
+
+template< typename Rec >
+void context_entry( transfer_t t_) noexcept {
+ // transfer control structure to the context-stack
+ Rec * rec = static_cast< Rec * >( t_.data);
+ BOOST_ASSERT( nullptr != rec);
+ transfer_t t = { nullptr, nullptr };
+ try {
+ // jump back to `context_create()`
+ t = jump_fcontext( t_.fctx, nullptr);
+ // start executing
+ t = rec->run( t);
+ } catch ( forced_unwind const& e) {
+ t = { e.fctx, nullptr };
+ }
+ BOOST_ASSERT( nullptr != t.fctx);
+ // destroy context-stack of `this`context on next context
+ ontop_fcontext( t.fctx, rec, context_exit< Rec >);
+ BOOST_ASSERT_MSG( false, "context already terminated");
+}
+
+template< typename Ctx, typename Fn, typename ... Args >
+transfer_t context_ontop( transfer_t t) {
+ auto tpl = static_cast< std::tuple< Fn, std::tuple< Args ... > > * >( t.data);
+ BOOST_ASSERT( nullptr != tpl);
+ typename std::decay< Fn >::type fn = std::forward< Fn >( std::get< 0 >( * tpl) );
+ auto args = std::move( std::get< 1 >( * tpl) );
+ Ctx ctx{ t.fctx };
+ // execute function
+ auto result = apply(
+ fn,
+ std::tuple_cat(
+ std::forward_as_tuple( std::move( ctx) ),
+ std::move( args) ) );
+ ctx = std::move( std::get< 0 >( result) );
+ // apply returned data
+ detail::tail( args) = std::move( result);
+ std::get< 1 >( * tpl) = std::move( args);
+ return { exchange( ctx.fctx_, nullptr), & std::get< 1 >( * tpl) };
+}
+
+template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+class record {
+private:
+ StackAlloc salloc_;
+ stack_context sctx_;
+ typename std::decay< Fn >::type fn_;
+ std::tuple< typename std::decay< Params >::type ... > params_;
+
+ static void destroy( record * p) noexcept {
+ StackAlloc salloc = p->salloc_;
+ stack_context sctx = p->sctx_;
+ // deallocate record
+ p->~record();
+ // destroy stack with stack allocator
+ salloc.deallocate( sctx);
+ }
+
+public:
+ record( stack_context sctx, StackAlloc const& salloc,
+ Fn && fn, Params && ... params) noexcept :
+ salloc_( salloc),
+ sctx_( sctx),
+ fn_( std::forward< Fn >( fn) ),
+ params_( std::forward< Params >( params) ... ) {
+ }
+
+ record( record const&) = delete;
+ record & operator=( record const&) = delete;
+
+ void deallocate() noexcept {
+ destroy( this);
+ }
+
+ transfer_t run( transfer_t t) {
+ Ctx from{ t.fctx };
+ typename Ctx::args_tpl_t args = std::move( * static_cast< typename Ctx::args_tpl_t * >( t.data) );
+ auto tpl = std::tuple_cat(
+ params_,
+ std::forward_as_tuple( std::move( from) ),
+ std::move( args) );
+ // invoke context-function
+ Ctx cc = apply( std::move( fn_), std::move( tpl) );
+ return { exchange( cc.fctx_, nullptr), nullptr };
+ }
+};
+
+template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+fcontext_t context_create( StackAlloc salloc, Fn && fn, Params && ... params) {
+ typedef record< Ctx, StackAlloc, Fn, Params ... > record_t;
+
+ auto sctx = salloc.allocate();
+ // reserve space for control structure
+#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
+ const std::size_t size = sctx.size - sizeof( record_t);
+ void * sp = static_cast< char * >( sctx.sp) - sizeof( record_t);
+#else
+ constexpr std::size_t func_alignment = 64; // alignof( record_t);
+ constexpr std::size_t func_size = sizeof( record_t);
+ // reserve space on stack
+ void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
+ // align sp pointer
+ std::size_t space = func_size + func_alignment;
+ sp = std::align( func_alignment, func_size, sp, space);
+ BOOST_ASSERT( nullptr != sp);
+ // calculate remaining size
+ const std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
+#endif
+ // create fast-context
+ const fcontext_t fctx = make_fcontext( sp, size, & context_entry< record_t >);
+ BOOST_ASSERT( nullptr != fctx);
+ // placment new for control structure on context-stack
+ auto rec = ::new ( sp) record_t{
+ sctx, salloc, std::forward< Fn >( fn), std::forward< Params >( params) ... };
+ // transfer control structure to context-stack
+ return jump_fcontext( fctx, rec).fctx;
+}
+
+template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+fcontext_t context_create( preallocated palloc, StackAlloc salloc, Fn && fn, Params && ... params) {
+ typedef record< Ctx, StackAlloc, Fn, Params ... > record_t;
+
+ // reserve space for control structure
+#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
+ const std::size_t size = palloc.size - sizeof( record_t);
+ void * sp = static_cast< char * >( palloc.sp) - sizeof( record_t);
+#else
+ constexpr std::size_t func_alignment = 64; // alignof( record_t);
+ constexpr std::size_t func_size = sizeof( record_t);
+ // reserve space on stack
+ void * sp = static_cast< char * >( palloc.sp) - func_size - func_alignment;
+ // align sp pointer
+ std::size_t space = func_size + func_alignment;
+ sp = std::align( func_alignment, func_size, sp, space);
+ BOOST_ASSERT( nullptr != sp);
+ // calculate remaining size
+ const std::size_t size = palloc.size - ( static_cast< char * >( palloc.sp) - static_cast< char * >( sp) );
+#endif
+ // create fast-context
+ const fcontext_t fctx = make_fcontext( sp, size, & context_entry< record_t >);
+ BOOST_ASSERT( nullptr != fctx);
+ // placment new for control structure on context-stack
+ auto rec = ::new ( sp) record_t{
+ palloc.sctx, salloc, std::forward< Fn >( fn), std::forward< Params >( params) ... };
+ // transfer control structure to context-stack
+ return jump_fcontext( fctx, rec).fctx;
+}
+
+}
+
+template< typename ... Args >
+class execution_context {
+private:
+ typedef std::tuple< Args ... > args_tpl_t;
+ typedef std::tuple< execution_context, typename std::decay< Args >::type ... > ret_tpl_t;
+
+ template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+ friend class detail::record;
+
+ template< typename Ctx, typename Fn, typename ... ArgsT >
+ friend detail::transfer_t detail::context_ontop( detail::transfer_t);
+
+ detail::fcontext_t fctx_{ nullptr };
+
+ execution_context( detail::fcontext_t fctx) noexcept :
+ fctx_( fctx) {
+ }
+
+public:
+ constexpr execution_context() noexcept = default;
+
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+ // segmented-stack requires to preserve the segments of the `current` context
+ // which is not possible (no global pointer to current context)
+ template< typename Fn, typename ... Params >
+ execution_context( std::allocator_arg_t, segmented_stack, Fn &&, Params && ...) = delete;
+
+ template< typename Fn, typename ... Params >
+ execution_context( std::allocator_arg_t, preallocated, segmented_stack, Fn &&, Params && ...) = delete;
+#else
+ template< typename Fn,
+ typename ... Params,
+ typename = detail::disable_overload< execution_context, Fn >
+ >
+ execution_context( Fn && fn, Params && ... params) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ fctx_( detail::context_create< execution_context >(
+ fixedsize_stack(),
+ std::forward< Fn >( fn),
+ std::forward< Params >( params) ... ) ) {
+ }
+
+ template< typename StackAlloc,
+ typename Fn,
+ typename ... Params
+ >
+ execution_context( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Params && ... params) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ fctx_( detail::context_create< execution_context >(
+ salloc,
+ std::forward< Fn >( fn),
+ std::forward< Params >( params) ... ) ) {
+ }
+
+ template< typename StackAlloc,
+ typename Fn,
+ typename ... Params
+ >
+ execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Params && ... params) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ fctx_( detail::context_create< execution_context >(
+ palloc, salloc,
+ std::forward< Fn >( fn),
+ std::forward< Params >( params) ... ) ) {
+ }
+#endif
+
+ ~execution_context() {
+ if ( nullptr != fctx_) {
+ detail::ontop_fcontext( detail::exchange( fctx_, nullptr), nullptr, detail::context_unwind);
+ }
+ }
+
+ execution_context( execution_context && other) noexcept :
+ fctx_( other.fctx_) {
+ other.fctx_ = nullptr;
+ }
+
+ execution_context & operator=( execution_context && other) noexcept {
+ if ( this != & other) {
+ execution_context tmp = std::move( other);
+ swap( tmp);
+ }
+ return * this;
+ }
+
+ execution_context( execution_context const& other) noexcept = delete;
+ execution_context & operator=( execution_context const& other) noexcept = delete;
+
+ ret_tpl_t operator()( Args ... args) {
+ BOOST_ASSERT( nullptr != fctx_);
+ args_tpl_t data( std::forward< Args >( args) ... );
+ detail::transfer_t t = detail::jump_fcontext( detail::exchange( fctx_, nullptr), & data);
+ if ( nullptr != t.data) {
+ data = std::move( * static_cast< args_tpl_t * >( t.data) );
+ }
+ return std::tuple_cat( std::forward_as_tuple( execution_context( t.fctx) ), std::move( data) );
+ }
+
+ template< typename Fn >
+ ret_tpl_t operator()( exec_ontop_arg_t, Fn && fn, Args ... args) {
+ BOOST_ASSERT( nullptr != fctx_);
+ args_tpl_t data{ std::forward< Args >( args) ... };
+ auto p = std::make_tuple( fn, std::move( data) );
+ detail::transfer_t t = detail::ontop_fcontext(
+ detail::exchange( fctx_, nullptr),
+ & p,
+ detail::context_ontop< execution_context, Fn, Args ... >);
+ if ( nullptr != t.data) {
+ data = std::move( * static_cast< args_tpl_t * >( t.data) );
+ }
+ return std::tuple_cat( std::forward_as_tuple( execution_context( t.fctx) ), std::move( data) );
+ }
+
+ explicit operator bool() const noexcept {
+ return nullptr != fctx_;
+ }
+
+ bool operator!() const noexcept {
+ return nullptr == fctx_;
+ }
+
+ bool operator==( execution_context const& other) const noexcept {
+ return fctx_ == other.fctx_;
+ }
+
+ bool operator!=( execution_context const& other) const noexcept {
+ return fctx_ != other.fctx_;
+ }
+
+ bool operator<( execution_context const& other) const noexcept {
+ return fctx_ < other.fctx_;
+ }
+
+ bool operator>( execution_context const& other) const noexcept {
+ return other.fctx_ < fctx_;
+ }
+
+ bool operator<=( execution_context const& other) const noexcept {
+ return ! ( * this > other);
+ }
+
+ bool operator>=( execution_context const& other) const noexcept {
+ return ! ( * this < other);
+ }
+
+ template< typename charT, class traitsT >
+ friend std::basic_ostream< charT, traitsT > &
+ operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other) {
+ if ( nullptr != other.fctx_) {
+ return os << other.fctx_;
+ } else {
+ return os << "{not-a-context}";
+ }
+ }
+
+ void swap( execution_context & other) noexcept {
+ std::swap( fctx_, other.fctx_);
+ }
+};
+
+#include <boost/context/execution_context_v2_void.ipp>
+
+template< typename ... Args >
+void swap( execution_context< Args ... > & l, execution_context< Args ... > & r) noexcept {
+ l.swap( r);
+}
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_EXECUTION_CONTEXT_H
diff --git a/boost/context/execution_context_v2_void.ipp b/boost/context/execution_context_v2_void.ipp
new file mode 100644
index 0000000000..d0659beafb
--- /dev/null
+++ b/boost/context/execution_context_v2_void.ipp
@@ -0,0 +1,290 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+namespace detail {
+
+template< typename Ctx, typename Fn >
+transfer_t context_ontop_void( transfer_t t) {
+ auto tpl = static_cast< std::tuple< Fn > * >( t.data);
+ BOOST_ASSERT( nullptr != tpl);
+ typename std::decay< Fn >::type fn = std::forward< Fn >( std::get< 0 >( * tpl) );
+ Ctx ctx{ t.fctx };
+ // execute function
+ ctx = apply(
+ fn,
+ std::forward_as_tuple( std::move( ctx) ) );
+ return { exchange( ctx.fctx_, nullptr), nullptr };
+}
+
+template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+class record_void {
+private:
+ StackAlloc salloc_;
+ stack_context sctx_;
+ typename std::decay< Fn >::type fn_;
+ std::tuple< typename std::decay< Params >::type ... > params_;
+
+ static void destroy( record_void * p) noexcept {
+ StackAlloc salloc = p->salloc_;
+ stack_context sctx = p->sctx_;
+ // deallocate record
+ p->~record_void();
+ // destroy stack with stack allocator
+ salloc.deallocate( sctx);
+ }
+
+public:
+ record_void( stack_context sctx, StackAlloc const& salloc,
+ Fn && fn, Params && ... params) noexcept :
+ salloc_( salloc),
+ sctx_( sctx),
+ fn_( std::forward< Fn >( fn) ),
+ params_( std::forward< Params >( params) ... ) {
+ }
+
+ record_void( record_void const&) = delete;
+ record_void & operator=( record_void const&) = delete;
+
+ void deallocate() noexcept {
+ destroy( this);
+ }
+
+ transfer_t run( transfer_t t) {
+ Ctx from{ t.fctx };
+ // invoke context-function
+ Ctx cc = apply(
+ fn_,
+ std::tuple_cat(
+ params_,
+ std::forward_as_tuple( std::move( from) ) ) );
+ return { exchange( cc.fctx_, nullptr), nullptr };
+ }
+};
+
+template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+fcontext_t context_create_void( StackAlloc salloc, Fn && fn, Params && ... params) {
+ typedef record_void< Ctx, StackAlloc, Fn, Params ... > record_t;
+
+ auto sctx = salloc.allocate();
+ // reserve space for control structure
+#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
+ const std::size_t size = sctx.size - sizeof( record_t);
+ void * sp = static_cast< char * >( sctx.sp) - sizeof( record_t);
+#else
+ constexpr std::size_t func_alignment = 64; // alignof( record_t);
+ constexpr std::size_t func_size = sizeof( record_t);
+ // reserve space on stack
+ void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
+ // align sp pointer
+ std::size_t space = func_size + func_alignment;
+ sp = std::align( func_alignment, func_size, sp, space);
+ BOOST_ASSERT( nullptr != sp);
+ // calculate remaining size
+ const std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
+#endif
+ // create fast-context
+ const fcontext_t fctx = make_fcontext( sp, size, & context_entry< record_t >);
+ BOOST_ASSERT( nullptr != fctx);
+ // placment new for control structure on context-stack
+ auto rec = ::new ( sp) record_t{
+ sctx, salloc, std::forward< Fn >( fn), std::forward< Params >( params) ... };
+ // transfer control structure to context-stack
+ return jump_fcontext( fctx, rec).fctx;
+}
+
+template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+fcontext_t context_create_void( preallocated palloc, StackAlloc salloc, Fn && fn, Params && ... params) {
+ typedef record_void< Ctx, StackAlloc, Fn, Params ... > record_t;
+
+ // reserve space for control structure
+#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
+ const std::size_t size = palloc.size - sizeof( record_t);
+ void * sp = static_cast< char * >( palloc.sp) - sizeof( record_t);
+#else
+ constexpr std::size_t func_alignment = 64; // alignof( record_t);
+ constexpr std::size_t func_size = sizeof( record_t);
+ // reserve space on stack
+ void * sp = static_cast< char * >( palloc.sp) - func_size - func_alignment;
+ // align sp pointer
+ std::size_t space = func_size + func_alignment;
+ sp = std::align( func_alignment, func_size, sp, space);
+ BOOST_ASSERT( nullptr != sp);
+ // calculate remaining size
+ const std::size_t size = palloc.size - ( static_cast< char * >( palloc.sp) - static_cast< char * >( sp) );
+#endif
+ // create fast-context
+ const fcontext_t fctx = make_fcontext( sp, size, & context_entry< record_t >);
+ BOOST_ASSERT( nullptr != fctx);
+ // placment new for control structure on context-stack
+ auto rec = ::new ( sp) record_t{
+ palloc.sctx, salloc, std::forward< Fn >( fn), std::forward< Params >( params) ... };
+ // transfer control structure to context-stack
+ return jump_fcontext( fctx, rec).fctx;
+}
+
+}
+
+template<>
+class execution_context< void > {
+private:
+ template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
+ friend class detail::record_void;
+
+ template< typename Ctx, typename Fn >
+ friend detail::transfer_t detail::context_ontop_void( detail::transfer_t);
+
+ detail::fcontext_t fctx_{ nullptr };
+
+ execution_context( detail::fcontext_t fctx) noexcept :
+ fctx_( fctx) {
+ }
+
+public:
+ constexpr execution_context() noexcept = default;
+
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+ // segmented-stack requires to preserve the segments of the `current` context
+ // which is not possible (no global pointer to current context)
+ template< typename Fn, typename ... Params >
+ execution_context( std::allocator_arg_t, segmented_stack, Fn &&, Params && ...) = delete;
+
+ template< typename Fn, typename ... Params >
+ execution_context( std::allocator_arg_t, preallocated, segmented_stack, Fn &&, Params && ...) = delete;
+#else
+ template< typename Fn,
+ typename ... Params,
+ typename = detail::disable_overload< execution_context, Fn >
+ >
+ execution_context( Fn && fn, Params && ... params) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ fctx_( detail::context_create_void< execution_context >(
+ fixedsize_stack(),
+ std::forward< Fn >( fn),
+ std::forward< Params >( params) ... ) ) {
+ }
+
+ template< typename StackAlloc,
+ typename Fn,
+ typename ... Params
+ >
+ execution_context( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Params && ... params) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ fctx_( detail::context_create_void< execution_context >(
+ salloc,
+ std::forward< Fn >( fn),
+ std::forward< Params >( params) ... ) ) {
+ }
+
+ template< typename StackAlloc,
+ typename Fn,
+ typename ... Params
+ >
+ execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Params && ... params) :
+ // deferred execution of fn and its arguments
+ // arguments are stored in std::tuple<>
+ // non-type template parameter pack via std::index_sequence_for<>
+ // preserves the number of arguments
+ // used to extract the function arguments from std::tuple<>
+ fctx_( detail::context_create_void< execution_context >(
+ palloc, salloc,
+ std::forward< Fn >( fn),
+ std::forward< Params >( params) ... ) ) {
+ }
+#endif
+
+ ~execution_context() {
+ if ( nullptr != fctx_) {
+ detail::ontop_fcontext( detail::exchange( fctx_, nullptr), nullptr, detail::context_unwind);
+ }
+ }
+
+ execution_context( execution_context && other) noexcept :
+ fctx_( other.fctx_) {
+ other.fctx_ = nullptr;
+ }
+
+ execution_context & operator=( execution_context && other) noexcept {
+ if ( this != & other) {
+ execution_context tmp = std::move( other);
+ swap( tmp);
+ }
+ return * this;
+ }
+
+ execution_context( execution_context const& other) noexcept = delete;
+ execution_context & operator=( execution_context const& other) noexcept = delete;
+
+ execution_context operator()() {
+ BOOST_ASSERT( nullptr != fctx_);
+ detail::transfer_t t = detail::jump_fcontext( detail::exchange( fctx_, nullptr), nullptr);
+ return execution_context( t.fctx);
+ }
+
+ template< typename Fn >
+ execution_context operator()( exec_ontop_arg_t, Fn && fn) {
+ BOOST_ASSERT( nullptr != fctx_);
+ std::tuple< Fn > p = std::forward_as_tuple( fn);
+ detail::transfer_t t = detail::ontop_fcontext(
+ detail::exchange( fctx_, nullptr),
+ & p,
+ detail::context_ontop_void< execution_context, Fn >);
+ return execution_context( t.fctx);
+ }
+
+ explicit operator bool() const noexcept {
+ return nullptr != fctx_;
+ }
+
+ bool operator!() const noexcept {
+ return nullptr == fctx_;
+ }
+
+ bool operator==( execution_context const& other) const noexcept {
+ return fctx_ == other.fctx_;
+ }
+
+ bool operator!=( execution_context const& other) const noexcept {
+ return fctx_ != other.fctx_;
+ }
+
+ bool operator<( execution_context const& other) const noexcept {
+ return fctx_ < other.fctx_;
+ }
+
+ bool operator>( execution_context const& other) const noexcept {
+ return other.fctx_ < fctx_;
+ }
+
+ bool operator<=( execution_context const& other) const noexcept {
+ return ! ( * this > other);
+ }
+
+ bool operator>=( execution_context const& other) const noexcept {
+ return ! ( * this < other);
+ }
+
+ template< typename charT, class traitsT >
+ friend std::basic_ostream< charT, traitsT > &
+ operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other) {
+ if ( nullptr != other.fctx_) {
+ return os << other.fctx_;
+ } else {
+ return os << "{not-a-context}";
+ }
+ }
+
+ void swap( execution_context & other) noexcept {
+ std::swap( fctx_, other.fctx_);
+ }
+};
diff --git a/boost/context/execution_context_winfib.ipp b/boost/context/execution_context_winfib.ipp
deleted file mode 100644
index 1b106fa245..0000000000
--- a/boost/context/execution_context_winfib.ipp
+++ /dev/null
@@ -1,361 +0,0 @@
-
-// Copyright Oliver Kowalke 2014.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_CONTEXT_EXECUTION_CONTEXT_H
-#define BOOST_CONTEXT_EXECUTION_CONTEXT_H
-
-#include <boost/context/detail/config.hpp>
-
-#if ! defined(BOOST_CONTEXT_NO_EXECUTION_CONTEXT)
-
-#include <windows.h>
-
-#include <algorithm>
-#include <atomic>
-#include <cstddef>
-#include <cstdint>
-#include <cstdlib>
-#include <memory>
-#include <tuple>
-#include <utility>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/intrusive_ptr.hpp>
-
-#include <boost/context/detail/invoke.hpp>
-#include <boost/context/fixedsize_stack.hpp>
-#include <boost/context/stack_context.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace context {
-namespace detail {
-
-struct activation_record {
- typedef boost::intrusive_ptr< activation_record > ptr_t;
-
- enum flag_t {
- flag_main_ctx = 1 << 1,
- flag_preserve_fpu = 1 << 2,
- flag_segmented_stack = 1 << 3
- };
-
- thread_local static ptr_t current_rec;
-
- std::atomic< std::size_t > use_count;
- LPVOID fiber;
- stack_context sctx;
- void * data;
- int flags;
-
- // used for toplevel-context
- // (e.g. main context, thread-entry context)
- activation_record() noexcept :
- use_count( 0),
- fiber( nullptr),
- sctx(),
- flags( flag_main_ctx
-# if defined(BOOST_USE_SEGMENTED_STACKS)
- | flag_segmented_stack
-# endif
- ) {
- }
-
- activation_record( stack_context sctx_, bool use_segmented_stack) noexcept :
- use_count( 0),
- fiber( nullptr),
- sctx( sctx_),
- data( nullptr),
- flags( use_segmented_stack ? flag_segmented_stack : 0) {
- }
-
- virtual ~activation_record() noexcept = default;
-
- void * resume( void * vp, bool fpu) noexcept {
- // store current activation record in local variable
- activation_record * from = current_rec.get();
- // store `this` in static, thread local pointer
- // `this` will become the active (running) context
- // returned by execution_context::current()
- current_rec = this;
- // context switch from parent context to `this`-context
-#if ( _WIN32_WINNT > 0x0600)
- if ( ::IsThreadAFiber() ) {
- from->fiber = ::GetCurrentFiber();
- } else {
- from->fiber = ::ConvertThreadToFiber( nullptr);
- }
-#else
- from->fiber = ::ConvertThreadToFiber( nullptr);
- if ( nullptr == from->fiber) {
- DWORD err = ::GetLastError();
- BOOST_ASSERT( ERROR_ALREADY_FIBER == err);
- from->fiber = ::GetCurrentFiber();
- BOOST_ASSERT( nullptr != from->fiber);
- BOOST_ASSERT( reinterpret_cast< LPVOID >( 0x1E00) != from->fiber);
- }
-#endif
- // store passed argument (void pointer)
- data = vp;
- // context switch
- ::SwitchToFiber( fiber);
- // access the activation-record of the current fiber
- activation_record * ar = static_cast< activation_record * >( GetFiberData() );
- return nullptr != ar ? ar->data : nullptr;
- }
-
- virtual void deallocate() {
- delete this;
- }
-
- friend void intrusive_ptr_add_ref( activation_record * ar) {
- ++ar->use_count;
- }
-
- friend void intrusive_ptr_release( activation_record * ar) {
- BOOST_ASSERT( nullptr != ar);
-
- if ( 0 == --ar->use_count) {
- ar->deallocate();
- }
- }
-};
-
-struct activation_record_initializer {
- activation_record_initializer();
- ~activation_record_initializer();
-};
-
-template< typename Fn, typename Tpl, typename StackAlloc >
-class capture_record : public activation_record {
-private:
- StackAlloc salloc_;
- Fn fn_;
- Tpl tpl_;
- activation_record * caller_;
-
- static void destroy( capture_record * p) {
- StackAlloc salloc( p->salloc_);
- stack_context sctx( p->sctx);
- // deallocate activation record
- p->~capture_record();
- // destroy stack with stack allocator
- salloc.deallocate( sctx);
- }
-
-public:
- explicit capture_record(
- stack_context sctx, StackAlloc const& salloc,
- Fn && fn, Tpl && tpl,
- activation_record * caller,
- bool use_segmented_stack) noexcept :
- activation_record( sctx, use_segmented_stack),
- salloc_( salloc),
- fn_( std::forward< Fn >( fn) ),
- tpl_( std::forward< Tpl >( tpl) ),
- caller_( caller) {
- }
-
- void deallocate() override final {
- destroy( this);
- }
-
- void run() noexcept {
- try {
- void * vp = caller_->resume( caller_, true);
- do_invoke( fn_, std::tuple_cat( tpl_, std::tie( vp) ) );
- } catch (...) {
- std::terminate();
- }
- BOOST_ASSERT( 0 == (flags & flag_main_ctx) );
- }
-};
-
-}
-
-struct preallocated {
- void * sp;
- std::size_t size;
- stack_context sctx;
-
- preallocated( void * sp_, std::size_t size_, stack_context sctx_) noexcept :
- sp( sp_), size( size_), sctx( sctx_) {
- }
-};
-
-class BOOST_CONTEXT_DECL execution_context {
-private:
- // tampoline function
- // entered if the execution context
- // is resumed for the first time
- template< typename AR >
- static VOID WINAPI entry_func( LPVOID p) {
- BOOST_ASSERT( 0 != p);
-
- AR * ar( reinterpret_cast< AR * >( p) );
- // start execution of toplevel context-function
- ar->run();
- //ctx->fn_(ctx->param_);
- ::DeleteFiber( ar->fiber);
- }
-
- typedef boost::intrusive_ptr< detail::activation_record > ptr_t;
-
- ptr_t ptr_;
-
- template< typename StackAlloc, typename Fn ,typename Tpl >
- static detail::activation_record * create_context(
- StackAlloc salloc,
- Fn && fn, Tpl && tpl,
- bool use_segmented_stack) {
- typedef detail::capture_record< Fn, Tpl, StackAlloc > capture_t;
-
- // hackish
- std::size_t fsize = salloc.size_;
- // protected_fixedsize_stack needs at least 2*page-size
- salloc.size_ = ( std::max)( sizeof( capture_t), 2 * stack_traits::page_size() );
-
- stack_context sctx( salloc.allocate() );
- // reserve space for control structure
- void * sp = static_cast< char * >( sctx.sp) - sizeof( capture_t);
- // get current activation record
- ptr_t curr = execution_context::current().ptr_;
- // placement new for control structure on fast-context stack
- capture_t * cr = new ( sp) capture_t(
- sctx, salloc, std::forward< Fn >( fn), std::forward< Tpl >( tpl), curr.get(), use_segmented_stack);
- // create fiber
- // use default stacksize
- cr->fiber = ::CreateFiber( fsize, execution_context::entry_func< capture_t >, cr);
- BOOST_ASSERT( nullptr != cr->fiber);
- return cr;
- }
-
- template< typename StackAlloc, typename Fn , typename Tpl >
- static detail::activation_record * create_context(
- preallocated palloc, StackAlloc salloc,
- Fn && fn, Tpl && tpl,
- bool use_segmented_stack) {
- typedef detail::capture_record< Fn, Tpl, StackAlloc > capture_t;
-
- // hackish
- std::size_t fsize = salloc.size_;
- // protected_fixedsize_stack needs at least 2*page-size
- salloc.size_ = ( std::max)( sizeof( capture_t), 2 * stack_traits::page_size() );
-
- // reserve space for control structure
- void * sp = static_cast< char * >( palloc.sp) - sizeof( capture_t);
- // get current activation record
- ptr_t curr = execution_context::current().ptr_;
- // placement new for control structure on fast-context stack
- capture_t * cr = new ( sp) capture_t(
- palloc.sctx, salloc, std::forward< Fn >( fn), std::forward< Tpl >( tpl), curr.get(), use_segmented_stack);
- // create fiber
- // use default stacksize
- cr->fiber = ::CreateFiber( fsize, execution_context::entry_func< capture_t >, cr);
- BOOST_ASSERT( nullptr != cr->fiber);
- return cr;
- }
-
- execution_context() :
- // default constructed with current activation_record
- ptr_( detail::activation_record::current_rec) {
- }
-
-public:
- static execution_context current() noexcept;
-
- template< typename Fn, typename ... Args >
- explicit execution_context( Fn && fn, Args && ... args) :
- // deferred execution of fn and its arguments
- // arguments are stored in std::tuple<>
- // non-type template parameter pack via std::index_sequence_for<>
- // preserves the number of arguments
- // used to extract the function arguments from std::tuple<>
- ptr_( create_context( fixedsize_stack(),
- std::forward< Fn >( fn),
- std::make_tuple( std::forward< Args >( args) ...),
- false) ) {
- ptr_->resume( ptr_.get(), true);
- }
-
- template< typename StackAlloc, typename Fn, typename ... Args >
- explicit execution_context( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Args && ... args) :
- // deferred execution of fn and its arguments
- // arguments are stored in std::tuple<>
- // non-type template parameter pack via std::index_sequence_for<>
- // preserves the number of arguments
- // used to extract the function arguments from std::tuple<>
- ptr_( create_context( salloc,
- std::forward< Fn >( fn),
- std::make_tuple( std::forward< Args >( args) ...),
- false) ) {
- ptr_->resume( ptr_.get(), true);
- }
-
- template< typename StackAlloc, typename Fn, typename ... Args >
- explicit execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Args && ... args) :
- // deferred execution of fn and its arguments
- // arguments are stored in std::tuple<>
- // non-type template parameter pack via std::index_sequence_for<>
- // preserves the number of arguments
- // used to extract the function arguments from std::tuple<>
- ptr_( create_context( palloc, salloc,
- std::forward< Fn >( fn),
- std::make_tuple( std::forward< Args >( args) ...),
- false) ) {
- ptr_->resume( ptr_.get(), true);
- }
-
- execution_context( execution_context const& other) noexcept :
- ptr_( other.ptr_) {
- }
-
- execution_context( execution_context && other) noexcept :
- ptr_( other.ptr_) {
- other.ptr_.reset();
- }
-
- execution_context & operator=( execution_context const& other) noexcept {
- if ( this != & other) {
- ptr_ = other.ptr_;
- }
- return * this;
- }
-
- execution_context & operator=( execution_context && other) noexcept {
- if ( this != & other) {
- ptr_ = other.ptr_;
- other.ptr_.reset();
- }
- return * this;
- }
-
- explicit operator bool() const noexcept {
- return nullptr != ptr_.get();
- }
-
- bool operator!() const noexcept {
- return nullptr == ptr_.get();
- }
-
- void * operator()( void * vp = nullptr, bool preserve_fpu = false) noexcept {
- return ptr_->resume( vp, preserve_fpu);
- }
-};
-
-}}
-
-# ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-# endif
-
-#endif
-
-#endif // BOOST_CONTEXT_EXECUTION_CONTEXT_H
diff --git a/boost/context/fixedsize_stack.hpp b/boost/context/fixedsize_stack.hpp
index b27d785d08..681de40576 100644
--- a/boost/context/fixedsize_stack.hpp
+++ b/boost/context/fixedsize_stack.hpp
@@ -32,16 +32,12 @@ namespace context {
template< typename traitsT >
class basic_fixedsize_stack {
private:
-#if defined(BOOST_USE_WINFIBERS)
- friend class execution_context;
-#endif
-
std::size_t size_;
public:
typedef traitsT traits_type;
- basic_fixedsize_stack( std::size_t size = traits_type::default_size() ) :
+ basic_fixedsize_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW :
size_( size) {
BOOST_ASSERT( traits_type::minimum_size() <= size_);
BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size_) );
@@ -60,17 +56,14 @@ public:
return sctx;
}
- void deallocate( stack_context & sctx) {
+ void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
BOOST_ASSERT( sctx.sp);
-#if ! defined(BOOST_USE_WINFIBERS)
BOOST_ASSERT( traits_type::minimum_size() <= sctx.size);
BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size) );
-#endif
#if defined(BOOST_USE_VALGRIND)
VALGRIND_STACK_DEREGISTER( sctx.valgrind_stack_id);
#endif
-
void * vp = static_cast< char * >( sctx.sp) - sctx.size;
std::free( vp);
}
diff --git a/boost/context/flags.hpp b/boost/context/flags.hpp
new file mode 100644
index 0000000000..c7ff1179da
--- /dev/null
+++ b/boost/context/flags.hpp
@@ -0,0 +1,28 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONTEXT_FLAGS_H
+#define BOOST_CONTEXT_FLAGS_H
+
+# include <boost/config.hpp>
+
+# ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+# endif
+
+namespace boost {
+namespace context {
+
+struct exec_ontop_arg_t {};
+const exec_ontop_arg_t exec_ontop_arg{};
+
+}}
+
+# ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+# endif
+
+#endif // BOOST_CONTEXT_FLAGS_H
diff --git a/boost/context/pooled_fixedsize_stack.hpp b/boost/context/pooled_fixedsize_stack.hpp
new file mode 100644
index 0000000000..3c0953cd07
--- /dev/null
+++ b/boost/context/pooled_fixedsize_stack.hpp
@@ -0,0 +1,115 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONTEXT_POOLED_pooled_fixedsize_H
+#define BOOST_CONTEXT_POOLED_pooled_fixedsize_H
+
+#include <atomic>
+#include <cstddef>
+#include <cstdlib>
+#include <new>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/pool/pool.hpp>
+
+#include <boost/context/detail/config.hpp>
+#include <boost/context/stack_context.hpp>
+#include <boost/context/stack_traits.hpp>
+
+#if defined(BOOST_USE_VALGRIND)
+#include <valgrind/valgrind.h>
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+
+template< typename traitsT >
+class basic_pooled_fixedsize_stack {
+private:
+ class storage {
+ private:
+ std::atomic< std::size_t > use_count_;
+ std::size_t stack_size_;
+ boost::pool< boost::default_user_allocator_malloc_free > storage_;
+
+ public:
+ storage( std::size_t stack_size, std::size_t next_size, std::size_t max_size) :
+ use_count_( 0),
+ stack_size_( stack_size),
+ storage_( stack_size, next_size, max_size) {
+ BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= stack_size_) );
+ }
+
+ stack_context allocate() {
+ void * vp = storage_.malloc();
+ if ( ! vp) {
+ throw std::bad_alloc();
+ }
+ stack_context sctx;
+ sctx.size = stack_size_;
+ sctx.sp = static_cast< char * >( vp) + sctx.size;
+#if defined(BOOST_USE_VALGRIND)
+ sctx.valgrind_stack_id = VALGRIND_STACK_REGISTER( sctx.sp, vp);
+#endif
+ return sctx;
+ }
+
+ void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
+ BOOST_ASSERT( sctx.sp);
+ BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size) );
+
+#if defined(BOOST_USE_VALGRIND)
+ VALGRIND_STACK_DEREGISTER( sctx.valgrind_stack_id);
+#endif
+ void * vp = static_cast< char * >( sctx.sp) - sctx.size;
+ storage_.free( vp);
+ }
+
+ friend void intrusive_ptr_add_ref( storage * s) noexcept {
+ ++s->use_count_;
+ }
+
+ friend void intrusive_ptr_release( storage * s) noexcept {
+ if ( 0 == --s->use_count_) {
+ delete s;
+ }
+ }
+ };
+
+ intrusive_ptr< storage > storage_;
+
+public:
+ typedef traitsT traits_type;
+
+ basic_pooled_fixedsize_stack( std::size_t stack_size = traits_type::default_size(),
+ std::size_t next_size = 32,
+ std::size_t max_size = 0) BOOST_NOEXCEPT_OR_NOTHROW :
+ storage_( new storage( stack_size, next_size, max_size) ) {
+ }
+
+ stack_context allocate() {
+ return storage_->allocate();
+ }
+
+ void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
+ storage_->deallocate( sctx);
+ }
+};
+
+typedef basic_pooled_fixedsize_stack< stack_traits > pooled_fixedsize_stack;
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_POOLED_pooled_fixedsize_H
diff --git a/boost/context/posix/protected_fixedsize_stack.hpp b/boost/context/posix/protected_fixedsize_stack.hpp
index 25ce9a6828..7d1b789d01 100644
--- a/boost/context/posix/protected_fixedsize_stack.hpp
+++ b/boost/context/posix/protected_fixedsize_stack.hpp
@@ -44,7 +44,7 @@ private:
public:
typedef traitsT traits_type;
- basic_protected_fixedsize_stack( std::size_t size = traits_type::default_size() ) :
+ basic_protected_fixedsize_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW :
size_( size) {
BOOST_ASSERT( traits_type::minimum_size() <= size_);
BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size_) );
@@ -86,7 +86,7 @@ public:
return sctx;
}
- void deallocate( stack_context & sctx) {
+ void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
BOOST_ASSERT( sctx.sp);
BOOST_ASSERT( traits_type::minimum_size() <= sctx.size);
BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size) );
diff --git a/boost/context/posix/segmented_stack.hpp b/boost/context/posix/segmented_stack.hpp
index 93f4210fd4..25842b6d32 100644
--- a/boost/context/posix/segmented_stack.hpp
+++ b/boost/context/posix/segmented_stack.hpp
@@ -45,7 +45,7 @@ private:
public:
typedef traitsT traits_type;
- basic_segmented_stack( std::size_t size = traits_type::default_size() ) :
+ basic_segmented_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW :
size_( size) {
BOOST_ASSERT( traits_type::minimum_size() <= size_);
BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size_) );
@@ -65,7 +65,7 @@ public:
return sctx;
}
- void deallocate( stack_context & sctx) {
+ void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
__splitstack_releasecontext( sctx.segments_ctx);
}
};
diff --git a/boost/context/preallocated.hpp b/boost/context/preallocated.hpp
new file mode 100644
index 0000000000..862a6a5060
--- /dev/null
+++ b/boost/context/preallocated.hpp
@@ -0,0 +1,39 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONTEXT_PREALLOCATED_H
+#define BOOST_CONTEXT_PREALLOCATED_H
+
+#include <cstddef>
+
+#include <boost/config.hpp>
+
+#include <boost/context/detail/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+
+struct preallocated {
+ void * sp;
+ std::size_t size;
+ stack_context sctx;
+
+ preallocated( void * sp_, std::size_t size_, stack_context sctx_) noexcept :
+ sp( sp_), size( size_), sctx( sctx_) {
+ }
+};
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_PREALLOCATED_H
diff --git a/boost/context/stack_context.hpp b/boost/context/stack_context.hpp
index 24a54e5748..6e516a3adf 100644
--- a/boost/context/stack_context.hpp
+++ b/boost/context/stack_context.hpp
@@ -20,49 +20,46 @@
namespace boost {
namespace context {
-#if defined(BOOST_USE_SEGMENTED_STACKS)
+#if ! defined(BOOST_CONTEXT_NO_CXX11)
struct stack_context {
+# if defined(BOOST_USE_SEGMENTED_STACKS)
typedef void * segments_context[BOOST_CONTEXT_SEGMENTS];
+# endif
- std::size_t size;
- void * sp;
- segments_context segments_ctx;
-#if defined(BOOST_USE_VALGRIND)
- unsigned valgrind_stack_id;
-#endif
-
-#if defined(BOOST_NO_CXX11_CONSTEXPR)
- stack_context() :
-#else
- constexpr stack_context() :
-#endif
- size( 0),
- sp( 0),
- segments_ctx()
-#if defined(BOOST_USE_VALGRIND)
- , valgrind_stack_id( 0)
-#endif
- {}
+ std::size_t size{ 0 };
+ void * sp{ nullptr };
+# if defined(BOOST_USE_SEGMENTED_STACKS)
+ segments_context segments_ctx{};
+# endif
+# if defined(BOOST_USE_VALGRIND)
+ unsigned valgrind_stack_id{ 0 };
+# endif
};
#else
struct stack_context {
+# if defined(BOOST_USE_SEGMENTED_STACKS)
+ typedef void * segments_context[BOOST_CONTEXT_SEGMENTS];
+# endif
+
std::size_t size;
void * sp;
-#if defined(BOOST_USE_VALGRIND)
+# if defined(BOOST_USE_SEGMENTED_STACKS)
+ segments_context segments_ctx;
+# endif
+# if defined(BOOST_USE_VALGRIND)
unsigned valgrind_stack_id;
-#endif
+# endif
-#if defined(BOOST_NO_CXX11_CONSTEXPR)
stack_context() :
-#else
- constexpr stack_context() :
-#endif
size( 0),
sp( 0)
-#if defined(BOOST_USE_VALGRIND)
+# if defined(BOOST_USE_SEGMENTED_STACKS)
+ , segments_ctx()
+# endif
+# if defined(BOOST_USE_VALGRIND)
, valgrind_stack_id( 0)
-#endif
- {}
+# endif
+ {}
};
#endif
diff --git a/boost/context/stack_traits.hpp b/boost/context/stack_traits.hpp
index 9b8a70636d..d5320f509d 100644
--- a/boost/context/stack_traits.hpp
+++ b/boost/context/stack_traits.hpp
@@ -22,15 +22,15 @@ namespace context {
struct BOOST_CONTEXT_DECL stack_traits
{
- static bool is_unbounded() BOOST_NOEXCEPT;
+ static bool is_unbounded() BOOST_NOEXCEPT_OR_NOTHROW;
- static std::size_t page_size() BOOST_NOEXCEPT;
+ static std::size_t page_size() BOOST_NOEXCEPT_OR_NOTHROW;
- static std::size_t default_size() BOOST_NOEXCEPT;
+ static std::size_t default_size() BOOST_NOEXCEPT_OR_NOTHROW;
- static std::size_t minimum_size() BOOST_NOEXCEPT;
+ static std::size_t minimum_size() BOOST_NOEXCEPT_OR_NOTHROW;
- static std::size_t maximum_size() BOOST_NOEXCEPT;
+ static std::size_t maximum_size() BOOST_NOEXCEPT_OR_NOTHROW;
};
}}
diff --git a/boost/context/windows/protected_fixedsize_stack.hpp b/boost/context/windows/protected_fixedsize_stack.hpp
index 548bcda31f..cd59764c93 100644
--- a/boost/context/windows/protected_fixedsize_stack.hpp
+++ b/boost/context/windows/protected_fixedsize_stack.hpp
@@ -31,16 +31,12 @@ namespace context {
template< typename traitsT >
class basic_protected_fixedsize_stack {
private:
-#if defined(BOOST_USE_WINFIBERS)
- friend class execution_context;
-#endif
-
std::size_t size_;
public:
typedef traitsT traits_type;
- basic_protected_fixedsize_stack( std::size_t size = traits_type::default_size() ) :
+ basic_protected_fixedsize_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW :
size_( size) {
BOOST_ASSERT( traits_type::minimum_size() <= size_);
BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size_) );
@@ -76,12 +72,10 @@ public:
return sctx;
}
- void deallocate( stack_context & sctx) {
+ void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
BOOST_ASSERT( sctx.sp);
-#if ! defined(BOOST_USE_WINFIBERS)
BOOST_ASSERT( traits_type::minimum_size() <= sctx.size);
BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size) );
-#endif
void * vp = static_cast< char * >( sctx.sp) - sctx.size;
::VirtualFree( vp, 0, MEM_RELEASE);
diff --git a/boost/core/demangle.hpp b/boost/core/demangle.hpp
index 44aeb8ded7..f13c26a7f4 100644
--- a/boost/core/demangle.hpp
+++ b/boost/core/demangle.hpp
@@ -17,7 +17,10 @@
# pragma once
#endif
-#if defined( __clang__ ) && defined( __has_include )
+// __has_include is currently supported by GCC and Clang. However GCC 4.9 may have issues and
+// returns 1 for 'defined( __has_include )', while '__has_include' is actually not supported:
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63662
+#if defined( __has_include ) && (!defined( BOOST_GCC ) || (__GNUC__ + 0) >= 5)
# if __has_include(<cxxabi.h>)
# define BOOST_CORE_HAS_CXXABI_H
# endif
diff --git a/boost/core/scoped_enum.hpp b/boost/core/scoped_enum.hpp
index 78c548bf81..56dd0ede43 100644
--- a/boost/core/scoped_enum.hpp
+++ b/boost/core/scoped_enum.hpp
@@ -43,7 +43,8 @@ namespace boost
* @throws No-throws.
*/
template <typename UnderlyingType, typename EnumType>
- UnderlyingType underlying_cast(EnumType v)
+ inline
+ BOOST_CONSTEXPR UnderlyingType underlying_cast(EnumType v) BOOST_NOEXCEPT
{
return v.get_underlying_value_();
}
@@ -61,7 +62,7 @@ namespace boost
*/
template <typename EnumType>
inline
- typename EnumType::enum_type native_value(EnumType e)
+ BOOST_CONSTEXPR typename EnumType::enum_type native_value(EnumType e) BOOST_NOEXCEPT
{
return e.get_native_value_();
}
@@ -75,14 +76,15 @@ namespace boost
};
template <typename UnderlyingType, typename EnumType>
- UnderlyingType underlying_cast(EnumType v)
+ inline
+ BOOST_CONSTEXPR UnderlyingType underlying_cast(EnumType v) BOOST_NOEXCEPT
{
return static_cast<UnderlyingType>(v);
}
template <typename EnumType>
inline
- EnumType native_value(EnumType e)
+ BOOST_CONSTEXPR EnumType native_value(EnumType e) BOOST_NOEXCEPT
{
return e;
}
@@ -96,7 +98,7 @@ namespace boost
#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
#define BOOST_SCOPED_ENUM_UT_DECLARE_CONVERSION_OPERATOR \
- explicit operator underlying_type() const BOOST_NOEXCEPT { return get_underlying_value_(); }
+ explicit BOOST_CONSTEXPR operator underlying_type() const BOOST_NOEXCEPT { return get_underlying_value_(); }
#else
@@ -115,8 +117,8 @@ namespace boost
typedef void is_boost_scoped_enum_tag; \
typedef UnderlyingType underlying_type; \
EnumType() BOOST_NOEXCEPT {} \
- explicit EnumType(underlying_type v) BOOST_NOEXCEPT : v_(v) {} \
- underlying_type get_underlying_value_() const BOOST_NOEXCEPT { return v_; } \
+ explicit BOOST_CONSTEXPR EnumType(underlying_type v) BOOST_NOEXCEPT : v_(v) {} \
+ BOOST_CONSTEXPR underlying_type get_underlying_value_() const BOOST_NOEXCEPT { return v_; } \
BOOST_SCOPED_ENUM_UT_DECLARE_CONVERSION_OPERATOR \
private: \
underlying_type v_; \
@@ -125,30 +127,30 @@ namespace boost
enum enum_type
#define BOOST_SCOPED_ENUM_DECLARE_END2() \
- enum_type get_native_value_() const BOOST_NOEXCEPT { return enum_type(v_); } \
- friend bool operator ==(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)==enum_type(rhs.v_); } \
- friend bool operator ==(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)==rhs; } \
- friend bool operator ==(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs==enum_type(rhs.v_); } \
- friend bool operator !=(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)!=enum_type(rhs.v_); } \
- friend bool operator !=(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)!=rhs; } \
- friend bool operator !=(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs!=enum_type(rhs.v_); } \
- friend bool operator <(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)<enum_type(rhs.v_); } \
- friend bool operator <(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)<rhs; } \
- friend bool operator <(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs<enum_type(rhs.v_); } \
- friend bool operator <=(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)<=enum_type(rhs.v_); } \
- friend bool operator <=(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)<=rhs; } \
- friend bool operator <=(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs<=enum_type(rhs.v_); } \
- friend bool operator >(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)>enum_type(rhs.v_); } \
- friend bool operator >(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)>rhs; } \
- friend bool operator >(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs>enum_type(rhs.v_); } \
- friend bool operator >=(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)>=enum_type(rhs.v_); } \
- friend bool operator >=(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)>=rhs; } \
- friend bool operator >=(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs>=enum_type(rhs.v_); } \
+ BOOST_CONSTEXPR enum_type get_native_value_() const BOOST_NOEXCEPT { return enum_type(v_); } \
+ friend BOOST_CONSTEXPR bool operator ==(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)==enum_type(rhs.v_); } \
+ friend BOOST_CONSTEXPR bool operator ==(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)==rhs; } \
+ friend BOOST_CONSTEXPR bool operator ==(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs==enum_type(rhs.v_); } \
+ friend BOOST_CONSTEXPR bool operator !=(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)!=enum_type(rhs.v_); } \
+ friend BOOST_CONSTEXPR bool operator !=(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)!=rhs; } \
+ friend BOOST_CONSTEXPR bool operator !=(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs!=enum_type(rhs.v_); } \
+ friend BOOST_CONSTEXPR bool operator <(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)<enum_type(rhs.v_); } \
+ friend BOOST_CONSTEXPR bool operator <(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)<rhs; } \
+ friend BOOST_CONSTEXPR bool operator <(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs<enum_type(rhs.v_); } \
+ friend BOOST_CONSTEXPR bool operator <=(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)<=enum_type(rhs.v_); } \
+ friend BOOST_CONSTEXPR bool operator <=(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)<=rhs; } \
+ friend BOOST_CONSTEXPR bool operator <=(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs<=enum_type(rhs.v_); } \
+ friend BOOST_CONSTEXPR bool operator >(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)>enum_type(rhs.v_); } \
+ friend BOOST_CONSTEXPR bool operator >(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)>rhs; } \
+ friend BOOST_CONSTEXPR bool operator >(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs>enum_type(rhs.v_); } \
+ friend BOOST_CONSTEXPR bool operator >=(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)>=enum_type(rhs.v_); } \
+ friend BOOST_CONSTEXPR bool operator >=(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)>=rhs; } \
+ friend BOOST_CONSTEXPR bool operator >=(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs>=enum_type(rhs.v_); } \
};
#define BOOST_SCOPED_ENUM_DECLARE_END(EnumType) \
; \
- EnumType(enum_type v) BOOST_NOEXCEPT : v_(v) {} \
+ BOOST_CONSTEXPR EnumType(enum_type v) BOOST_NOEXCEPT : v_(v) {} \
BOOST_SCOPED_ENUM_DECLARE_END2()
/**
diff --git a/boost/coroutine/attributes.hpp b/boost/coroutine/attributes.hpp
index 065a4c66e3..ca712ee68d 100644
--- a/boost/coroutine/attributes.hpp
+++ b/boost/coroutine/attributes.hpp
@@ -25,63 +25,27 @@ struct attributes
{
std::size_t size;
flag_unwind_t do_unwind;
- flag_fpu_t preserve_fpu;
attributes() BOOST_NOEXCEPT :
size( stack_allocator::traits_type::default_size() ),
- do_unwind( stack_unwind),
- preserve_fpu( fpu_preserved)
+ do_unwind( stack_unwind)
{}
explicit attributes( std::size_t size_) BOOST_NOEXCEPT :
size( size_),
- do_unwind( stack_unwind),
- preserve_fpu( fpu_preserved)
+ do_unwind( stack_unwind)
{}
explicit attributes( flag_unwind_t do_unwind_) BOOST_NOEXCEPT :
size( stack_allocator::traits_type::default_size() ),
- do_unwind( do_unwind_),
- preserve_fpu( fpu_preserved)
- {}
-
- explicit attributes( flag_fpu_t preserve_fpu_) BOOST_NOEXCEPT :
- size( stack_allocator::traits_type::default_size() ),
- do_unwind( stack_unwind),
- preserve_fpu( preserve_fpu_)
+ do_unwind( do_unwind_)
{}
explicit attributes(
std::size_t size_,
flag_unwind_t do_unwind_) BOOST_NOEXCEPT :
size( size_),
- do_unwind( do_unwind_),
- preserve_fpu( fpu_preserved)
- {}
-
- explicit attributes(
- std::size_t size_,
- flag_fpu_t preserve_fpu_) BOOST_NOEXCEPT :
- size( size_),
- do_unwind( stack_unwind),
- preserve_fpu( preserve_fpu_)
- {}
-
- explicit attributes(
- flag_unwind_t do_unwind_,
- flag_fpu_t preserve_fpu_) BOOST_NOEXCEPT :
- size( stack_allocator::traits_type::default_size() ),
- do_unwind( do_unwind_),
- preserve_fpu( preserve_fpu_)
- {}
-
- explicit attributes(
- std::size_t size_,
- flag_unwind_t do_unwind_,
- flag_fpu_t preserve_fpu_) BOOST_NOEXCEPT :
- size( size_),
- do_unwind( do_unwind_),
- preserve_fpu( preserve_fpu_)
+ do_unwind( do_unwind_)
{}
};
diff --git a/boost/coroutine/detail/config.hpp b/boost/coroutine/detail/config.hpp
index 9a3f4bf334..488a401862 100644
--- a/boost/coroutine/detail/config.hpp
+++ b/boost/coroutine/detail/config.hpp
@@ -35,14 +35,6 @@
# include <boost/config/auto_link.hpp>
#endif
-#if defined(BOOST_USE_SEGMENTED_STACKS)
-# if ! ( (defined(__GNUC__) && __GNUC__ > 3 && __GNUC_MINOR__ > 6) || \
- (defined(__clang__) && __clang_major__ > 2 && __clang_minor__ > 3) )
-# error "compiler does not support segmented stacks"
-# endif
-# define BOOST_COROUTINES_SEGMENTS 10
-#endif
-
#define BOOST_COROUTINES_UNIDIRECT
#define BOOST_COROUTINES_SYMMETRIC
diff --git a/boost/coroutine/detail/coroutine_context.hpp b/boost/coroutine/detail/coroutine_context.hpp
index 94aa69bd6e..2d2b60ace2 100644
--- a/boost/coroutine/detail/coroutine_context.hpp
+++ b/boost/coroutine/detail/coroutine_context.hpp
@@ -11,7 +11,7 @@
#include <boost/assert.hpp>
#include <boost/config.hpp>
-#include <boost/context/fcontext.hpp>
+#include <boost/context/detail/fcontext.hpp>
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/detail/preallocated.hpp>
@@ -29,11 +29,22 @@ namespace detail {
class BOOST_COROUTINES_DECL coroutine_context
{
private:
+ template< typename Coro >
+ friend void trampoline( context::detail::transfer_t);
+ template< typename Coro >
+ friend void trampoline_void( context::detail::transfer_t);
+ template< typename Coro >
+ friend void trampoline_pull( context::detail::transfer_t);
+ template< typename Coro >
+ friend void trampoline_push( context::detail::transfer_t);
+ template< typename Coro >
+ friend void trampoline_push_void( context::detail::transfer_t);
+
preallocated palloc_;
- context::fcontext_t ctx_;
+ context::detail::fcontext_t ctx_;
public:
- typedef void( * ctx_fn)( intptr_t);
+ typedef void( * ctx_fn)( context::detail::transfer_t);
// default ctor represents the current execution-context
coroutine_context();
@@ -47,7 +58,7 @@ public:
coroutine_context& operator=( coroutine_context const&);
- intptr_t jump( coroutine_context &, intptr_t = 0, bool = true);
+ void * jump( coroutine_context &, void * = 0);
stack_context & stack_ctx()
{ return palloc_.sctx; }
diff --git a/boost/coroutine/detail/data.hpp b/boost/coroutine/detail/data.hpp
new file mode 100644
index 0000000000..7c008fe831
--- /dev/null
+++ b/boost/coroutine/detail/data.hpp
@@ -0,0 +1,34 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES_DETAIL_DATA_H
+#define BOOST_COROUTINES_DETAIL_DATA_H
+
+#include <boost/config.hpp>
+
+#include <boost/coroutine/detail/coroutine_context.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+struct data_t
+{
+ coroutine_context * from;
+ void * data;
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_DETAIL_DATA_H
diff --git a/boost/coroutine/detail/flags.hpp b/boost/coroutine/detail/flags.hpp
index 8d19757ee8..2078b62362 100644
--- a/boost/coroutine/detail/flags.hpp
+++ b/boost/coroutine/detail/flags.hpp
@@ -23,8 +23,7 @@ enum flag_t
flag_running = 1 << 2,
flag_complete = 1 << 3,
flag_unwind_stack = 1 << 4,
- flag_force_unwind = 1 << 5,
- flag_preserve_fpu = 1 << 6
+ flag_force_unwind = 1 << 5
};
struct unwind_t
diff --git a/boost/coroutine/detail/pull_coroutine_impl.hpp b/boost/coroutine/detail/pull_coroutine_impl.hpp
index 10ca597544..e35b7894e2 100644
--- a/boost/coroutine/detail/pull_coroutine_impl.hpp
+++ b/boost/coroutine/detail/pull_coroutine_impl.hpp
@@ -46,7 +46,7 @@ public:
pull_coroutine_impl( coroutine_context * caller,
coroutine_context * callee,
- bool unwind, bool preserve_fpu) :
+ bool unwind) :
flags_( 0),
except_(),
caller_( caller),
@@ -54,12 +54,11 @@ public:
result_( 0)
{
if ( unwind) flags_ |= flag_force_unwind;
- if ( preserve_fpu) flags_ |= flag_preserve_fpu;
}
pull_coroutine_impl( coroutine_context * caller,
coroutine_context * callee,
- bool unwind, bool preserve_fpu,
+ bool unwind,
R * result) :
flags_( 0),
except_(),
@@ -68,7 +67,6 @@ public:
result_( result)
{
if ( unwind) flags_ |= flag_force_unwind;
- if ( preserve_fpu) flags_ |= flag_preserve_fpu;
}
virtual ~pull_coroutine_impl() {}
@@ -79,9 +77,6 @@ public:
bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
- bool preserve_fpu() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_preserve_fpu); }
-
bool is_started() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_started); }
@@ -99,8 +94,7 @@ public:
param_type to( unwind_t::force_unwind);
caller_->jump(
* callee_,
- reinterpret_cast< intptr_t >( & to),
- preserve_fpu() );
+ & to);
flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( is_complete() );
@@ -115,11 +109,10 @@ public:
flags_ |= flag_running;
param_type to( this);
param_type * from(
- reinterpret_cast< param_type * >(
+ static_cast< param_type * >(
caller_->jump(
* callee_,
- reinterpret_cast< intptr_t >( & to),
- preserve_fpu() ) ) );
+ & to) ) );
flags_ &= ~flag_running;
result_ = from->data;
if ( from->do_unwind) throw forced_unwind();
@@ -163,7 +156,7 @@ public:
pull_coroutine_impl( coroutine_context * caller,
coroutine_context * callee,
- bool unwind, bool preserve_fpu) :
+ bool unwind) :
flags_( 0),
except_(),
caller_( caller),
@@ -171,12 +164,11 @@ public:
result_( 0)
{
if ( unwind) flags_ |= flag_force_unwind;
- if ( preserve_fpu) flags_ |= flag_preserve_fpu;
}
pull_coroutine_impl( coroutine_context * caller,
coroutine_context * callee,
- bool unwind, bool preserve_fpu,
+ bool unwind,
R * result) :
flags_( 0),
except_(),
@@ -185,7 +177,6 @@ public:
result_( result)
{
if ( unwind) flags_ |= flag_force_unwind;
- if ( preserve_fpu) flags_ |= flag_preserve_fpu;
}
virtual ~pull_coroutine_impl() {}
@@ -196,9 +187,6 @@ public:
bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
- bool preserve_fpu() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_preserve_fpu); }
-
bool is_started() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_started); }
@@ -216,8 +204,7 @@ public:
param_type to( unwind_t::force_unwind);
caller_->jump(
* callee_,
- reinterpret_cast< intptr_t >( & to),
- preserve_fpu() );
+ & to);
flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( is_complete() );
@@ -232,11 +219,10 @@ public:
flags_ |= flag_running;
param_type to( this);
param_type * from(
- reinterpret_cast< param_type * >(
+ static_cast< param_type * >(
caller_->jump(
* callee_,
- reinterpret_cast< intptr_t >( & to),
- preserve_fpu() ) ) );
+ & to) ) );
flags_ &= ~flag_running;
result_ = from->data;
if ( from->do_unwind) throw forced_unwind();
@@ -279,14 +265,13 @@ public:
pull_coroutine_impl( coroutine_context * caller,
coroutine_context * callee,
- bool unwind, bool preserve_fpu) :
+ bool unwind) :
flags_( 0),
except_(),
caller_( caller),
callee_( callee)
{
if ( unwind) flags_ |= flag_force_unwind;
- if ( preserve_fpu) flags_ |= flag_preserve_fpu;
}
virtual ~pull_coroutine_impl() {}
@@ -297,9 +282,6 @@ public:
inline bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
- inline bool preserve_fpu() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_preserve_fpu); }
-
inline bool is_started() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_started); }
@@ -317,8 +299,7 @@ public:
param_type to( unwind_t::force_unwind);
caller_->jump(
* callee_,
- reinterpret_cast< intptr_t >( & to),
- preserve_fpu() );
+ & to);
flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( is_complete() );
@@ -333,11 +314,10 @@ public:
flags_ |= flag_running;
param_type to( this);
param_type * from(
- reinterpret_cast< param_type * >(
+ static_cast< param_type * >(
caller_->jump(
* callee_,
- reinterpret_cast< intptr_t >( & to),
- preserve_fpu() ) ) );
+ & to) ) );
flags_ &= ~flag_running;
if ( from->do_unwind) throw forced_unwind();
if ( except_) rethrow_exception( except_);
diff --git a/boost/coroutine/detail/pull_coroutine_object.hpp b/boost/coroutine/detail/pull_coroutine_object.hpp
index 57ae169d80..36918489de 100644
--- a/boost/coroutine/detail/pull_coroutine_object.hpp
+++ b/boost/coroutine/detail/pull_coroutine_object.hpp
@@ -78,8 +78,7 @@ public:
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
- stack_unwind == attrs.do_unwind,
- fpu_preserved == attrs.preserve_fpu),
+ stack_unwind == attrs.do_unwind),
fn_( fn),
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
@@ -92,8 +91,7 @@ public:
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
- stack_unwind == attrs.do_unwind,
- fpu_preserved == attrs.preserve_fpu),
+ stack_unwind == attrs.do_unwind),
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn_( fn),
#else
@@ -111,7 +109,7 @@ public:
base_t::flags_ |= flag_running;
// create push_coroutine
- typename PushCoro::synth_type b( & this->callee, & this->caller, false, base_t::preserve_fpu() );
+ typename PushCoro::synth_type b( & this->callee, & this->caller, false);
PushCoro push_coro( synthesized_t::syntesized, b);
try
{ fn_( push_coro); }
@@ -125,8 +123,7 @@ public:
typename base_t::param_type to;
this->callee.jump(
this->caller,
- reinterpret_cast< intptr_t >( & to),
- base_t::preserve_fpu() );
+ & to);
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
}
@@ -164,8 +161,7 @@ public:
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
- stack_unwind == attrs.do_unwind,
- fpu_preserved == attrs.preserve_fpu),
+ stack_unwind == attrs.do_unwind),
fn_( fn),
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
@@ -178,8 +174,7 @@ public:
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
- stack_unwind == attrs.do_unwind,
- fpu_preserved == attrs.preserve_fpu),
+ stack_unwind == attrs.do_unwind),
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn_( fn),
#else
@@ -197,7 +192,7 @@ public:
base_t::flags_ |= flag_running;
// create push_coroutine
- typename PushCoro::synth_type b( & this->callee, & this->caller, false, base_t::preserve_fpu() );
+ typename PushCoro::synth_type b( & this->callee, & this->caller, false);
PushCoro push_coro( synthesized_t::syntesized, b);
try
{ fn_( push_coro); }
@@ -211,8 +206,7 @@ public:
typename base_t::param_type to;
this->callee.jump(
this->caller,
- reinterpret_cast< intptr_t >( & to),
- base_t::preserve_fpu() );
+ & to);
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
}
@@ -250,8 +244,7 @@ public:
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
- stack_unwind == attrs.do_unwind,
- fpu_preserved == attrs.preserve_fpu),
+ stack_unwind == attrs.do_unwind),
fn_( fn),
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
@@ -264,8 +257,7 @@ public:
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
- stack_unwind == attrs.do_unwind,
- fpu_preserved == attrs.preserve_fpu),
+ stack_unwind == attrs.do_unwind),
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn_( fn),
#else
@@ -283,7 +275,7 @@ public:
base_t::flags_ |= flag_running;
// create push_coroutine
- typename PushCoro::synth_type b( & this->callee, & this->caller, false, base_t::preserve_fpu() );
+ typename PushCoro::synth_type b( & this->callee, & this->caller, false);
PushCoro push_coro( synthesized_t::syntesized, b);
try
{ fn_( push_coro); }
@@ -297,8 +289,7 @@ public:
typename base_t::param_type to;
this->callee.jump(
this->caller,
- reinterpret_cast< intptr_t >( & to),
- base_t::preserve_fpu() );
+ & to);
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
}
diff --git a/boost/coroutine/detail/pull_coroutine_synthesized.hpp b/boost/coroutine/detail/pull_coroutine_synthesized.hpp
index 952d50c113..313de3c2dd 100644
--- a/boost/coroutine/detail/pull_coroutine_synthesized.hpp
+++ b/boost/coroutine/detail/pull_coroutine_synthesized.hpp
@@ -30,9 +30,9 @@ private:
public:
pull_coroutine_synthesized( coroutine_context * caller,
coroutine_context * callee,
- bool unwind, bool preserve_fpu,
+ bool unwind,
R * result) :
- impl_t( caller, callee, unwind, preserve_fpu, result)
+ impl_t( caller, callee, unwind, result)
{}
void destroy() {}
@@ -47,9 +47,9 @@ private:
public:
pull_coroutine_synthesized( coroutine_context * caller,
coroutine_context * callee,
- bool unwind, bool preserve_fpu,
+ bool unwind,
R * result) :
- impl_t( caller, callee, unwind, preserve_fpu, result)
+ impl_t( caller, callee, unwind, result)
{}
void destroy() {}
@@ -64,8 +64,8 @@ private:
public:
pull_coroutine_synthesized( coroutine_context * caller,
coroutine_context * callee,
- bool unwind, bool preserve_fpu) :
- impl_t( caller, callee, unwind, preserve_fpu)
+ bool unwind) :
+ impl_t( caller, callee, unwind)
{}
inline void destroy() {}
diff --git a/boost/coroutine/detail/push_coroutine_impl.hpp b/boost/coroutine/detail/push_coroutine_impl.hpp
index 8ee2bd6f0e..b46bfa61a8 100644
--- a/boost/coroutine/detail/push_coroutine_impl.hpp
+++ b/boost/coroutine/detail/push_coroutine_impl.hpp
@@ -45,14 +45,13 @@ public:
push_coroutine_impl( coroutine_context * caller,
coroutine_context * callee,
- bool unwind, bool preserve_fpu) :
+ bool unwind) :
flags_( 0),
except_(),
caller_( caller),
callee_( callee)
{
if ( unwind) flags_ |= flag_force_unwind;
- if ( preserve_fpu) flags_ |= flag_preserve_fpu;
}
bool force_unwind() const BOOST_NOEXCEPT
@@ -61,9 +60,6 @@ public:
bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
- bool preserve_fpu() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_preserve_fpu); }
-
bool is_started() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_started); }
@@ -81,8 +77,7 @@ public:
param_type to( unwind_t::force_unwind);
caller_->jump(
* callee_,
- reinterpret_cast< intptr_t >( & to),
- preserve_fpu() );
+ & to);
flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( is_complete() );
@@ -97,11 +92,10 @@ public:
flags_ |= flag_running;
param_type to( const_cast< Arg * >( & arg), this);
param_type * from(
- reinterpret_cast< param_type * >(
+ static_cast< param_type * >(
caller_->jump(
* callee_,
- reinterpret_cast< intptr_t >( & to),
- preserve_fpu() ) ) );
+ & to) ) );
flags_ &= ~flag_running;
if ( from->do_unwind) throw forced_unwind();
if ( except_) rethrow_exception( except_);
@@ -115,11 +109,10 @@ public:
flags_ |= flag_running;
param_type to( const_cast< Arg * >( & arg), this);
param_type * from(
- reinterpret_cast< param_type * >(
+ static_cast< param_type * >(
caller_->jump(
* callee_,
- reinterpret_cast< intptr_t >( & to),
- preserve_fpu() ) ) );
+ & to) ) );
flags_ &= ~flag_running;
if ( from->do_unwind) throw forced_unwind();
if ( except_) rethrow_exception( except_);
@@ -142,14 +135,13 @@ public:
push_coroutine_impl( coroutine_context * caller,
coroutine_context * callee,
- bool unwind, bool preserve_fpu) :
+ bool unwind) :
flags_( 0),
except_(),
caller_( caller),
callee_( callee)
{
if ( unwind) flags_ |= flag_force_unwind;
- if ( preserve_fpu) flags_ |= flag_preserve_fpu;
}
bool force_unwind() const BOOST_NOEXCEPT
@@ -158,9 +150,6 @@ public:
bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
- bool preserve_fpu() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_preserve_fpu); }
-
bool is_started() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_started); }
@@ -178,8 +167,7 @@ public:
param_type to( unwind_t::force_unwind);
caller_->jump(
* callee_,
- reinterpret_cast< intptr_t >( & to),
- preserve_fpu() );
+ & to);
flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( is_complete() );
@@ -194,11 +182,10 @@ public:
flags_ |= flag_running;
param_type to( & arg, this);
param_type * from(
- reinterpret_cast< param_type * >(
+ static_cast< param_type * >(
caller_->jump(
* callee_,
- reinterpret_cast< intptr_t >( & to),
- preserve_fpu() ) ) );
+ & to) ) );
flags_ &= ~flag_running;
if ( from->do_unwind) throw forced_unwind();
if ( except_) rethrow_exception( except_);
@@ -221,14 +208,13 @@ public:
push_coroutine_impl( coroutine_context * caller,
coroutine_context * callee,
- bool unwind, bool preserve_fpu) :
+ bool unwind) :
flags_( 0),
except_(),
caller_( caller),
callee_( callee)
{
if ( unwind) flags_ |= flag_force_unwind;
- if ( preserve_fpu) flags_ |= flag_preserve_fpu;
}
inline bool force_unwind() const BOOST_NOEXCEPT
@@ -237,9 +223,6 @@ public:
inline bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
- inline bool preserve_fpu() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_preserve_fpu); }
-
inline bool is_started() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_started); }
@@ -257,8 +240,7 @@ public:
param_type to( unwind_t::force_unwind);
caller_->jump(
* callee_,
- reinterpret_cast< intptr_t >( & to),
- preserve_fpu() );
+ & to);
flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( is_complete() );
@@ -273,11 +255,10 @@ public:
flags_ |= flag_running;
param_type to( this);
param_type * from(
- reinterpret_cast< param_type * >(
+ static_cast< param_type * >(
caller_->jump(
* callee_,
- reinterpret_cast< intptr_t >( & to),
- preserve_fpu() ) ) );
+ & to) ) );
flags_ &= ~flag_running;
if ( from->do_unwind) throw forced_unwind();
if ( except_) rethrow_exception( except_);
diff --git a/boost/coroutine/detail/push_coroutine_object.hpp b/boost/coroutine/detail/push_coroutine_object.hpp
index 53d5c7710e..c3115ebe11 100644
--- a/boost/coroutine/detail/push_coroutine_object.hpp
+++ b/boost/coroutine/detail/push_coroutine_object.hpp
@@ -90,8 +90,7 @@ public:
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
- stack_unwind == attrs.do_unwind,
- fpu_preserved == attrs.preserve_fpu),
+ stack_unwind == attrs.do_unwind),
fn_( fn),
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
@@ -104,8 +103,7 @@ public:
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
- stack_unwind == attrs.do_unwind,
- fpu_preserved == attrs.preserve_fpu),
+ stack_unwind == attrs.do_unwind),
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn_( fn),
#else
@@ -123,7 +121,7 @@ public:
base_t::flags_ |= flag_running;
// create push_coroutine
- typename PullCoro::synth_type b( & this->callee, & this->caller, false, base_t::preserve_fpu(), result);
+ typename PullCoro::synth_type b( & this->callee, & this->caller, false, result);
PullCoro pull_coro( synthesized_t::syntesized, b);
try
{ fn_( pull_coro); }
@@ -137,8 +135,7 @@ public:
typename base_t::param_type to;
this->callee.jump(
this->caller,
- reinterpret_cast< intptr_t >( & to),
- base_t::preserve_fpu() );
+ & to);
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
}
@@ -176,8 +173,7 @@ public:
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
- stack_unwind == attrs.do_unwind,
- fpu_preserved == attrs.preserve_fpu),
+ stack_unwind == attrs.do_unwind),
fn_( fn),
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
@@ -190,8 +186,7 @@ public:
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
- stack_unwind == attrs.do_unwind,
- fpu_preserved == attrs.preserve_fpu),
+ stack_unwind == attrs.do_unwind),
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn_( fn),
#else
@@ -209,7 +204,7 @@ public:
base_t::flags_ |= flag_running;
// create push_coroutine
- typename PullCoro::synth_type b( & this->callee, & this->caller, false, base_t::preserve_fpu(), result);
+ typename PullCoro::synth_type b( & this->callee, & this->caller, false, result);
PullCoro push_coro( synthesized_t::syntesized, b);
try
{ fn_( push_coro); }
@@ -223,8 +218,7 @@ public:
typename base_t::param_type to;
this->callee.jump(
this->caller,
- reinterpret_cast< intptr_t >( & to),
- base_t::preserve_fpu() );
+ & to);
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
}
@@ -262,8 +256,7 @@ public:
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
- stack_unwind == attrs.do_unwind,
- fpu_preserved == attrs.preserve_fpu),
+ stack_unwind == attrs.do_unwind),
fn_( fn),
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
@@ -276,8 +269,7 @@ public:
ctx_t( palloc, this),
base_t( & this->caller,
& this->callee,
- stack_unwind == attrs.do_unwind,
- fpu_preserved == attrs.preserve_fpu),
+ stack_unwind == attrs.do_unwind),
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn_( fn),
#else
@@ -295,7 +287,7 @@ public:
base_t::flags_ |= flag_running;
// create push_coroutine
- typename PullCoro::synth_type b( & this->callee, & this->caller, false, base_t::preserve_fpu() );
+ typename PullCoro::synth_type b( & this->callee, & this->caller, false);
PullCoro push_coro( synthesized_t::syntesized, b);
try
{ fn_( push_coro); }
@@ -309,8 +301,7 @@ public:
typename base_t::param_type to;
this->callee.jump(
this->caller,
- reinterpret_cast< intptr_t >( & to),
- base_t::preserve_fpu() );
+ & to);
BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
}
diff --git a/boost/coroutine/detail/push_coroutine_synthesized.hpp b/boost/coroutine/detail/push_coroutine_synthesized.hpp
index 306a841fc0..c10a468b9b 100644
--- a/boost/coroutine/detail/push_coroutine_synthesized.hpp
+++ b/boost/coroutine/detail/push_coroutine_synthesized.hpp
@@ -30,8 +30,8 @@ private:
public:
push_coroutine_synthesized( coroutine_context * caller,
coroutine_context * callee,
- bool unwind, bool preserve_fpu) :
- impl_t( caller, callee, unwind, preserve_fpu)
+ bool unwind) :
+ impl_t( caller, callee, unwind)
{}
void destroy() {}
@@ -46,8 +46,8 @@ private:
public:
push_coroutine_synthesized( coroutine_context * caller,
coroutine_context * callee,
- bool unwind, bool preserve_fpu) :
- impl_t( caller, callee, unwind, preserve_fpu)
+ bool unwind) :
+ impl_t( caller, callee, unwind)
{}
void destroy() {}
@@ -62,8 +62,8 @@ private:
public:
push_coroutine_synthesized( coroutine_context * caller,
coroutine_context * callee,
- bool unwind, bool preserve_fpu) :
- impl_t( caller, callee, unwind, preserve_fpu)
+ bool unwind) :
+ impl_t( caller, callee, unwind)
{}
inline void destroy() {}
diff --git a/boost/coroutine/detail/symmetric_coroutine_impl.hpp b/boost/coroutine/detail/symmetric_coroutine_impl.hpp
index 96d948a49c..b4066d8f78 100644
--- a/boost/coroutine/detail/symmetric_coroutine_impl.hpp
+++ b/boost/coroutine/detail/symmetric_coroutine_impl.hpp
@@ -36,13 +36,12 @@ public:
typedef parameters< R > param_type;
symmetric_coroutine_impl( preallocated const& palloc,
- bool unwind, bool preserve_fpu) BOOST_NOEXCEPT :
+ bool unwind) BOOST_NOEXCEPT :
flags_( 0),
caller_(),
callee_( trampoline< symmetric_coroutine_impl< R > >, palloc)
{
if ( unwind) flags_ |= flag_force_unwind;
- if ( preserve_fpu) flags_ |= flag_preserve_fpu;
}
virtual ~symmetric_coroutine_impl() {}
@@ -53,9 +52,6 @@ public:
bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
- bool preserve_fpu() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_preserve_fpu); }
-
bool is_started() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_started); }
@@ -74,8 +70,7 @@ public:
param_type to( unwind_t::force_unwind);
caller_.jump(
callee_,
- reinterpret_cast< intptr_t >( & to),
- preserve_fpu() );
+ & to);
flags_ &= ~flag_running;
flags_ &= ~flag_unwind_stack;
@@ -97,11 +92,10 @@ public:
flags_ &= ~flag_running;
param_type to;
param_type * from(
- reinterpret_cast< param_type * >(
+ static_cast< param_type * >(
callee_.jump(
caller_,
- reinterpret_cast< intptr_t >( & to),
- preserve_fpu() ) ) );
+ & to) ) );
flags_ |= flag_running;
if ( from->do_unwind) throw forced_unwind();
BOOST_ASSERT( from->data);
@@ -149,8 +143,7 @@ protected:
flags_ |= flag_running;
caller_.jump(
callee_,
- reinterpret_cast< intptr_t >( to),
- preserve_fpu() );
+ to);
flags_ &= ~flag_running;
}
@@ -165,11 +158,10 @@ protected:
other->caller_ = caller_;
flags_ &= ~flag_running;
param_type * from(
- reinterpret_cast< param_type * >(
+ static_cast< param_type * >(
callee_.jump(
other->callee_,
- reinterpret_cast< intptr_t >( to),
- preserve_fpu() ) ) );
+ to) ) );
flags_ |= flag_running;
if ( from->do_unwind) throw forced_unwind();
BOOST_ASSERT( from->data);
@@ -184,13 +176,12 @@ public:
typedef parameters< R & > param_type;
symmetric_coroutine_impl( preallocated const& palloc,
- bool unwind, bool preserve_fpu) BOOST_NOEXCEPT :
+ bool unwind) BOOST_NOEXCEPT :
flags_( 0),
caller_(),
callee_( trampoline< symmetric_coroutine_impl< R > >, palloc)
{
if ( unwind) flags_ |= flag_force_unwind;
- if ( preserve_fpu) flags_ |= flag_preserve_fpu;
}
virtual ~symmetric_coroutine_impl() {}
@@ -201,9 +192,6 @@ public:
bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
- bool preserve_fpu() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_preserve_fpu); }
-
bool is_started() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_started); }
@@ -222,8 +210,7 @@ public:
param_type to( unwind_t::force_unwind);
caller_.jump(
callee_,
- reinterpret_cast< intptr_t >( & to),
- preserve_fpu() );
+ & to);
flags_ &= ~flag_running;
flags_ &= ~flag_unwind_stack;
@@ -245,11 +232,10 @@ public:
flags_ &= ~flag_running;
param_type to;
param_type * from(
- reinterpret_cast< param_type * >(
+ static_cast< param_type * >(
callee_.jump(
caller_,
- reinterpret_cast< intptr_t >( & to),
- preserve_fpu() ) ) );
+ & to) ) );
flags_ |= flag_running;
if ( from->do_unwind) throw forced_unwind();
BOOST_ASSERT( from->data);
@@ -297,8 +283,7 @@ protected:
flags_ |= flag_running;
caller_.jump(
callee_,
- reinterpret_cast< intptr_t >( to),
- preserve_fpu() );
+ to);
flags_ &= ~flag_running;
}
@@ -313,11 +298,10 @@ protected:
other->caller_ = caller_;
flags_ &= ~flag_running;
param_type * from(
- reinterpret_cast< param_type * >(
+ static_cast< param_type * >(
callee_.jump(
other->callee_,
- reinterpret_cast< intptr_t >( to),
- preserve_fpu() ) ) );
+ to) ) );
flags_ |= flag_running;
if ( from->do_unwind) throw forced_unwind();
BOOST_ASSERT( from->data);
@@ -332,13 +316,12 @@ public:
typedef parameters< void > param_type;
symmetric_coroutine_impl( preallocated const& palloc,
- bool unwind, bool preserve_fpu) BOOST_NOEXCEPT :
+ bool unwind) BOOST_NOEXCEPT :
flags_( 0),
caller_(),
callee_( trampoline_void< symmetric_coroutine_impl< void > >, palloc)
{
if ( unwind) flags_ |= flag_force_unwind;
- if ( preserve_fpu) flags_ |= flag_preserve_fpu;
}
virtual ~symmetric_coroutine_impl() {}
@@ -349,9 +332,6 @@ public:
inline bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
- inline bool preserve_fpu() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_preserve_fpu); }
-
inline bool is_started() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_started); }
@@ -370,8 +350,7 @@ public:
param_type to( unwind_t::force_unwind);
caller_.jump(
callee_,
- reinterpret_cast< intptr_t >( & to),
- preserve_fpu() );
+ & to);
flags_ &= ~flag_running;
flags_ &= ~flag_unwind_stack;
@@ -388,8 +367,7 @@ public:
flags_ |= flag_running;
caller_.jump(
callee_,
- reinterpret_cast< intptr_t >( & to),
- preserve_fpu() );
+ & to);
flags_ &= ~flag_running;
}
@@ -401,11 +379,10 @@ public:
flags_ &= ~flag_running;
param_type to;
param_type * from(
- reinterpret_cast< param_type * >(
+ static_cast< param_type * >(
callee_.jump(
caller_,
- reinterpret_cast< intptr_t >( & to),
- preserve_fpu() ) ) );
+ & to) ) );
flags_ |= flag_running;
if ( from->do_unwind) throw forced_unwind();
}
@@ -454,11 +431,10 @@ protected:
other->caller_ = caller_;
flags_ &= ~flag_running;
param_type * from(
- reinterpret_cast< param_type * >(
+ static_cast< param_type * >(
callee_.jump(
other->callee_,
- reinterpret_cast< intptr_t >( to),
- preserve_fpu() ) ) );
+ to) ) );
flags_ |= flag_running;
if ( from->do_unwind) throw forced_unwind();
}
diff --git a/boost/coroutine/detail/symmetric_coroutine_object.hpp b/boost/coroutine/detail/symmetric_coroutine_object.hpp
index 0e528f9611..a19cd92232 100644
--- a/boost/coroutine/detail/symmetric_coroutine_object.hpp
+++ b/boost/coroutine/detail/symmetric_coroutine_object.hpp
@@ -56,8 +56,7 @@ public:
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
impl_t( palloc,
- stack_unwind == attrs.do_unwind,
- fpu_preserved == attrs.preserve_fpu),
+ stack_unwind == attrs.do_unwind),
fn_( fn),
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
@@ -68,8 +67,7 @@ public:
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
impl_t( palloc,
- stack_unwind == attrs.do_unwind,
- fpu_preserved == attrs.preserve_fpu),
+ stack_unwind == attrs.do_unwind),
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn_( fn),
#else
@@ -100,8 +98,7 @@ public:
typename impl_t::param_type to;
impl_t::callee_.jump(
impl_t::caller_,
- reinterpret_cast< intptr_t >( & to),
- impl_t::preserve_fpu() );
+ & to);
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -135,8 +132,7 @@ public:
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
impl_t( palloc,
- stack_unwind == attrs.do_unwind,
- fpu_preserved == attrs.preserve_fpu),
+ stack_unwind == attrs.do_unwind),
fn_( fn),
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
@@ -147,8 +143,7 @@ public:
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
impl_t( palloc,
- stack_unwind == attrs.do_unwind,
- fpu_preserved == attrs.preserve_fpu),
+ stack_unwind == attrs.do_unwind),
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn_( fn),
#else
@@ -179,8 +174,7 @@ public:
typename impl_t::param_type to;
impl_t::callee_.jump(
impl_t::caller_,
- reinterpret_cast< intptr_t >( & to),
- impl_t::preserve_fpu() );
+ & to);
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
@@ -214,8 +208,7 @@ public:
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
impl_t( palloc,
- stack_unwind == attrs.do_unwind,
- fpu_preserved == attrs.preserve_fpu),
+ stack_unwind == attrs.do_unwind),
fn_( fn),
stack_ctx_( palloc.sctx),
stack_alloc_( stack_alloc)
@@ -226,8 +219,7 @@ public:
preallocated const& palloc,
StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
impl_t( palloc,
- stack_unwind == attrs.do_unwind,
- fpu_preserved == attrs.preserve_fpu),
+ stack_unwind == attrs.do_unwind),
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
fn_( fn),
#else
@@ -258,8 +250,7 @@ public:
typename impl_t::param_type to;
impl_t::callee_.jump(
impl_t::caller_,
- reinterpret_cast< intptr_t >( & to),
- impl_t::preserve_fpu() );
+ & to);
BOOST_ASSERT_MSG( false, "coroutine is complete");
}
diff --git a/boost/coroutine/detail/trampoline.hpp b/boost/coroutine/detail/trampoline.hpp
index 1cb3226d15..eb0c6c2378 100644
--- a/boost/coroutine/detail/trampoline.hpp
+++ b/boost/coroutine/detail/trampoline.hpp
@@ -9,9 +9,11 @@
#include <boost/assert.hpp>
#include <boost/config.hpp>
+#include <boost/context/detail/fcontext.hpp>
#include <boost/cstdint.hpp>
#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/detail/data.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
@@ -22,37 +24,37 @@ namespace coroutines {
namespace detail {
template< typename Coro >
-void trampoline( intptr_t vp)
+void trampoline( context::detail::transfer_t t)
{
typedef typename Coro::param_type param_type;
- BOOST_ASSERT( 0 != vp);
-
+ data_t * data = static_cast< data_t * >( t.data);
+ data->from->ctx_ = t.fctx;
param_type * param(
- reinterpret_cast< param_type * >( vp) );
+ static_cast< param_type * >( data->data) );
BOOST_ASSERT( 0 != param);
BOOST_ASSERT( 0 != param->data);
Coro * coro(
- reinterpret_cast< Coro * >( param->coro) );
+ static_cast< Coro * >( param->coro) );
BOOST_ASSERT( 0 != coro);
coro->run( param->data);
}
template< typename Coro >
-void trampoline_void( intptr_t vp)
+void trampoline_void( context::detail::transfer_t t)
{
typedef typename Coro::param_type param_type;
- BOOST_ASSERT( 0 != vp);
-
+ data_t * data = static_cast< data_t * >( t.data);
+ data->from->ctx_ = t.fctx;
param_type * param(
- reinterpret_cast< param_type * >( vp) );
+ static_cast< param_type * >( data->data) );
BOOST_ASSERT( 0 != param);
Coro * coro(
- reinterpret_cast< Coro * >( param->coro) );
+ static_cast< Coro * >( param->coro) );
BOOST_ASSERT( 0 != coro);
coro->run();
diff --git a/boost/coroutine/detail/trampoline_pull.hpp b/boost/coroutine/detail/trampoline_pull.hpp
index 179024529d..1daa76db3b 100644
--- a/boost/coroutine/detail/trampoline_pull.hpp
+++ b/boost/coroutine/detail/trampoline_pull.hpp
@@ -9,9 +9,11 @@
#include <boost/assert.hpp>
#include <boost/config.hpp>
+#include <boost/context/detail/fcontext.hpp>
#include <boost/cstdint.hpp>
#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/detail/data.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
@@ -22,18 +24,18 @@ namespace coroutines {
namespace detail {
template< typename Coro >
-void trampoline_pull( intptr_t vp)
+void trampoline_pull( context::detail::transfer_t t)
{
typedef typename Coro::param_type param_type;
- BOOST_ASSERT( 0 != vp);
-
+ data_t * data = static_cast< data_t * >( t.data);
+ data->from->ctx_ = t.fctx;
param_type * param(
- reinterpret_cast< param_type * >( vp) );
+ static_cast< param_type * >( data->data) );
BOOST_ASSERT( 0 != param);
Coro * coro(
- reinterpret_cast< Coro * >( param->coro) );
+ static_cast< Coro * >( param->coro) );
BOOST_ASSERT( 0 != coro);
coro->run();
diff --git a/boost/coroutine/detail/trampoline_push.hpp b/boost/coroutine/detail/trampoline_push.hpp
index 448904456e..80f90d0518 100644
--- a/boost/coroutine/detail/trampoline_push.hpp
+++ b/boost/coroutine/detail/trampoline_push.hpp
@@ -11,11 +11,13 @@
#include <boost/assert.hpp>
#include <boost/config.hpp>
+#include <boost/context/detail/fcontext.hpp>
#include <boost/cstdint.hpp>
#include <boost/exception_ptr.hpp>
#include <boost/move/move.hpp>
#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/detail/data.hpp>
#include <boost/coroutine/detail/flags.hpp>
#include <boost/coroutine/detail/parameters.hpp>
#include <boost/coroutine/detail/setup.hpp>
@@ -32,37 +34,37 @@ namespace coroutines {
namespace detail {
template< typename Coro >
-void trampoline_push( intptr_t vp)
+void trampoline_push( context::detail::transfer_t t)
{
typedef typename Coro::param_type param_type;
- BOOST_ASSERT( vp);
-
+ data_t * data = static_cast< data_t * >( t.data);
+ data->from->ctx_ = t.fctx;
param_type * param(
- reinterpret_cast< param_type * >( vp) );
+ static_cast< param_type * >( data->data) );
BOOST_ASSERT( 0 != param);
BOOST_ASSERT( 0 != param->data);
Coro * coro(
- reinterpret_cast< Coro * >( param->coro) );
+ static_cast< Coro * >( param->coro) );
BOOST_ASSERT( 0 != coro);
coro->run( param->data);
}
template< typename Coro >
-void trampoline_push_void( intptr_t vp)
+void trampoline_push_void( context::detail::transfer_t t)
{
typedef typename Coro::param_type param_type;
- BOOST_ASSERT( vp);
-
+ data_t * data = static_cast< data_t * >( t.data);
+ data->from->ctx_ = t.fctx;
param_type * param(
- reinterpret_cast< param_type * >( vp) );
+ static_cast< param_type * >( data->data) );
BOOST_ASSERT( 0 != param);
Coro * coro(
- reinterpret_cast< Coro * >( param->coro) );
+ static_cast< Coro * >( param->coro) );
BOOST_ASSERT( 0 != coro);
coro->run();
diff --git a/boost/coroutine/flags.hpp b/boost/coroutine/flags.hpp
index a8194c60ee..81940f30e5 100644
--- a/boost/coroutine/flags.hpp
+++ b/boost/coroutine/flags.hpp
@@ -16,12 +16,6 @@ enum flag_unwind_t
no_stack_unwind
};
-enum flag_fpu_t
-{
- fpu_preserved = 0,
- fpu_not_preserved
-};
-
}}
#endif // BOOST_COROUTINES_FLAGS_H
diff --git a/boost/coroutine/posix/segmented_stack_allocator.hpp b/boost/coroutine/posix/segmented_stack_allocator.hpp
index 335e5789b4..49cee28cd2 100644
--- a/boost/coroutine/posix/segmented_stack_allocator.hpp
+++ b/boost/coroutine/posix/segmented_stack_allocator.hpp
@@ -23,14 +23,14 @@
// forward declaration for splitstack-functions defined in libgcc
extern "C" {
void *__splitstack_makecontext( std::size_t,
- void * [BOOST_COROUTINES_SEGMENTS],
+ void * [BOOST_CONTEXT_SEGMENTS],
std::size_t *);
-void __splitstack_releasecontext( void * [BOOST_COROUTINES_SEGMENTS]);
+void __splitstack_releasecontext( void * [BOOST_CONTEXT_SEGMENTS]);
-void __splitstack_resetcontext( void * [BOOST_COROUTINES_SEGMENTS]);
+void __splitstack_resetcontext( void * [BOOST_CONTEXT_SEGMENTS]);
-void __splitstack_block_signals_context( void * [BOOST_COROUTINES_SEGMENTS],
+void __splitstack_block_signals_context( void * [BOOST_CONTEXT_SEGMENTS],
int * new_value, int * old_value);
}
diff --git a/boost/coroutine/stack_context.hpp b/boost/coroutine/stack_context.hpp
index 1ca11eb4a8..433056f7a1 100644
--- a/boost/coroutine/stack_context.hpp
+++ b/boost/coroutine/stack_context.hpp
@@ -23,7 +23,7 @@ namespace coroutines {
#if defined(BOOST_USE_SEGMENTED_STACKS)
struct stack_context
{
- typedef void * segments_context[BOOST_COROUTINES_SEGMENTS];
+ typedef void * segments_context[BOOST_CONTEXT_SEGMENTS];
std::size_t size;
void * sp;
diff --git a/boost/coroutine2/all.hpp b/boost/coroutine2/all.hpp
index f54b4569eb..dcd30aa029 100644
--- a/boost/coroutine2/all.hpp
+++ b/boost/coroutine2/all.hpp
@@ -9,6 +9,7 @@
#include <boost/coroutine2/coroutine.hpp>
#include <boost/coroutine2/fixedsize_stack.hpp>
+#include <boost/coroutine2/pooled_fixedsize_stack.hpp>
#include <boost/coroutine2/protected_fixedsize_stack.hpp>
#include <boost/coroutine2/segmented_stack.hpp>
diff --git a/boost/coroutine2/coroutine.hpp b/boost/coroutine2/coroutine.hpp
index 0269299518..39aa767cc3 100644
--- a/boost/coroutine2/coroutine.hpp
+++ b/boost/coroutine2/coroutine.hpp
@@ -23,8 +23,8 @@ namespace coroutines2 {
template< typename T >
struct coroutine {
- typedef detail::pull_coroutine< T > pull_type;
- typedef detail::push_coroutine< T > push_type;
+ using pull_type = detail::pull_coroutine< T >;
+ using push_type = detail::push_coroutine< T >;
};
template< typename T >
diff --git a/boost/coroutine2/detail/coroutine.hpp b/boost/coroutine2/detail/coroutine.hpp
index 55641e443c..7c1483d3be 100644
--- a/boost/coroutine2/detail/coroutine.hpp
+++ b/boost/coroutine2/detail/coroutine.hpp
@@ -8,6 +8,7 @@
#define BOOST_COROUTINES2_DETAIL_COROUTINE_HPP
#include <boost/config.hpp>
+#include <boost/context/detail/config.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
@@ -28,14 +29,26 @@ class push_coroutine;
#include <boost/coroutine2/detail/pull_coroutine.hpp>
#include <boost/coroutine2/detail/push_coroutine.hpp>
-#include <boost/coroutine2/detail/pull_control_block.hpp>
-#include <boost/coroutine2/detail/push_control_block.hpp>
-
-#include <boost/coroutine2/detail/pull_coroutine.ipp>
-#include <boost/coroutine2/detail/push_coroutine.ipp>
-
-#include <boost/coroutine2/detail/pull_control_block.ipp>
-#include <boost/coroutine2/detail/push_control_block.ipp>
+#if defined(BOOST_EXECUTION_CONTEXT)
+# if (BOOST_EXECUTION_CONTEXT==1)
+# include <boost/coroutine2/detail/pull_control_block_ecv1.hpp>
+# include <boost/coroutine2/detail/push_control_block_ecv1.hpp>
+# else
+# include <boost/coroutine2/detail/pull_control_block_ecv2.hpp>
+# include <boost/coroutine2/detail/push_control_block_ecv2.hpp>
+# endif
+
+# include <boost/coroutine2/detail/pull_coroutine.ipp>
+# include <boost/coroutine2/detail/push_coroutine.ipp>
+
+# if (BOOST_EXECUTION_CONTEXT==1)
+# include <boost/coroutine2/detail/pull_control_block_ecv1.ipp>
+# include <boost/coroutine2/detail/push_control_block_ecv1.ipp>
+# else
+# include <boost/coroutine2/detail/pull_control_block_ecv2.ipp>
+# include <boost/coroutine2/detail/push_control_block_ecv2.ipp>
+# endif
+#endif
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
diff --git a/boost/coroutine2/detail/create_control_block.ipp b/boost/coroutine2/detail/create_control_block.ipp
new file mode 100644
index 0000000000..9eaea2ebf3
--- /dev/null
+++ b/boost/coroutine2/detail/create_control_block.ipp
@@ -0,0 +1,60 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES2_DETAIL_CREATE_CONTROLBLOCK_IPP
+#define BOOST_COROUTINES2_DETAIL_CREATE_CONTROLBLOCK_IPP
+
+#include <cstddef>
+#include <memory>
+#include <utility>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/context/preallocated.hpp>
+#include <boost/context/stack_context.hpp>
+
+#include <boost/coroutine2/detail/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines2 {
+namespace detail {
+
+template< typename ControlBlock, typename StackAllocator, typename Fn >
+ControlBlock * create_control_block( StackAllocator salloc, Fn && fn) {
+ auto sctx = salloc.allocate();
+ // reserve space for control structure
+#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
+ void * sp = static_cast< char * >( sctx.sp) - sizeof( ControlBlock);
+ const std::size_t size = sctx.size - sizeof( ControlBlock);
+#else
+ constexpr std::size_t func_alignment = 64; // alignof( ControlBlock);
+ constexpr std::size_t func_size = sizeof( ControlBlock);
+ // reserve space on stack
+ void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
+ // align sp pointer
+ std::size_t space = func_size + func_alignment;
+ sp = std::align( func_alignment, func_size, sp, space);
+ BOOST_ASSERT( nullptr != sp);
+ // calculate remaining size
+ const std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
+#endif
+ // placment new for control structure on coroutine stack
+ return new ( sp) ControlBlock{ context::preallocated( sp, size, sctx),
+ salloc, std::forward< Fn >( fn) };
+}
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES2_DETAIL_CREATE_CONTROLBLOCK_IPP
diff --git a/boost/coroutine2/detail/decay_copy.hpp b/boost/coroutine2/detail/decay_copy.hpp
new file mode 100644
index 0000000000..3a5008dd81
--- /dev/null
+++ b/boost/coroutine2/detail/decay_copy.hpp
@@ -0,0 +1,36 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES2_DETAIL_DECAY_COPY_H
+#define BOOST_COROUTINES2_DETAIL_DECAY_COPY_H
+
+#include <type_traits>
+
+#include <boost/config.hpp>
+
+#include <boost/context/detail/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines2 {
+namespace detail {
+
+template< typename T >
+typename std::decay< T >::type
+decay_copy( T && t) {
+ return std::forward< T >( t);
+}
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES2_DETAIL_DECAY_COPY_H
diff --git a/boost/coroutine2/detail/disable_overload.hpp b/boost/coroutine2/detail/disable_overload.hpp
new file mode 100644
index 0000000000..633d46883c
--- /dev/null
+++ b/boost/coroutine2/detail/disable_overload.hpp
@@ -0,0 +1,34 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES2_DETAIL_DISABLE_OVERLOAD_H
+#define BOOST_COROUTINES2_DETAIL_DISABLE_OVERLOAD_H
+
+#include <type_traits>
+
+#include <boost/config.hpp>
+#include <boost/context/detail/disable_overload.hpp>
+
+#include <boost/coroutine2/detail/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines2 {
+namespace detail {
+
+template< typename X, typename Y >
+using disable_overload = boost::context::detail::disable_overload< X, Y >;
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES2_DETAIL_DISABLE_OVERLOAD_H
diff --git a/boost/coroutine2/detail/forced_unwind.hpp b/boost/coroutine2/detail/forced_unwind.hpp
index e04eb72d69..0f67f79a5f 100644
--- a/boost/coroutine2/detail/forced_unwind.hpp
+++ b/boost/coroutine2/detail/forced_unwind.hpp
@@ -24,6 +24,12 @@ namespace detail {
struct forced_unwind {};
+inline
+void * unwind_coroutine( void * data) {
+ throw forced_unwind{};
+ return data;
+}
+
}}}
#ifdef BOOST_HAS_ABI_HEADERS
diff --git a/boost/coroutine2/detail/pull_control_block.ipp b/boost/coroutine2/detail/pull_control_block.ipp
deleted file mode 100644
index 536e5e6a94..0000000000
--- a/boost/coroutine2/detail/pull_control_block.ipp
+++ /dev/null
@@ -1,299 +0,0 @@
-
-// Copyright Oliver Kowalke 2014.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
-#define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
-
-#include <exception>
-#include <memory>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-
-#include <boost/context/execution_context.hpp>
-
-#include <boost/coroutine2/detail/config.hpp>
-#include <boost/coroutine2/detail/forced_unwind.hpp>
-#include <boost/coroutine2/detail/state.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines2 {
-namespace detail {
-
-// pull_coroutine< T >
-
-template< typename T >
-template< typename StackAllocator, typename Fn >
-pull_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
- Fn && fn_, bool preserve_fpu_) :
- other( nullptr),
- ctx( std::allocator_arg, palloc, salloc,
- [=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
- // create synthesized push_coroutine< T >
- typename push_coroutine< T >::control_block synthesized_cb( this, ctx);
- push_coroutine< T > synthesized( & synthesized_cb);
- other = & synthesized_cb;
- try {
- // call coroutine-fn with synthesized push_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- // set termination flags
- state |= static_cast< int >( state_t::complete);
- // jump back to ctx
- other->ctx( nullptr, preserve_fpu);
- BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
- }),
- preserve_fpu( preserve_fpu_),
- state( static_cast< int >( state_t::unwind) ),
- except(),
- bvalid( false),
- storage() {
- // enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
- set( reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) ) );
-}
-
-template< typename T >
-pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb,
- boost::context::execution_context const& ctx_) :
- other( cb),
- ctx( ctx_),
- preserve_fpu( other->preserve_fpu),
- state( 0),
- except(),
- bvalid( false),
- storage() {
-}
-
-template< typename T >
-pull_coroutine< T >::control_block::~control_block() {
- if ( 0 == ( state & static_cast< int >( state_t::complete ) ) &&
- 0 != ( state & static_cast< int >( state_t::unwind) ) ) {
- // set early-exit flag
- state |= static_cast< int >( state_t::early_exit);
- ctx( nullptr, preserve_fpu);
- }
- // destroy data if it set
- if ( bvalid) {
- reinterpret_cast< T const* >( storage)->~T();
- }
-}
-
-template< typename T >
-void
-pull_coroutine< T >::control_block::resume() {
- other->ctx = boost::context::execution_context::current();
- set( reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) ) );
- if ( except) {
- std::rethrow_exception( except);
- }
- // test early-exit-flag
- if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) {
- throw forced_unwind();
- }
-}
-
-template< typename T >
-void
-pull_coroutine< T >::control_block::set( T * t) {
- // destroy data if it set
- if ( bvalid) {
- reinterpret_cast< T const* >( storage)->~T();
- }
- if ( nullptr != t) {
- new ( storage) T( std::move( * t) ); // FIXME: differrentiation between move/copy
- bvalid = true;
- } else {
- bvalid = false;
- }
-}
-
-template< typename T >
-T &
-pull_coroutine< T >::control_block::get() {
- return * reinterpret_cast< T * >( storage);
-}
-
-template< typename T >
-bool
-pull_coroutine< T >::control_block::valid() const noexcept {
- return nullptr != other && 0 == ( state & static_cast< int >( state_t::complete) ) && bvalid;
-}
-
-
-// pull_coroutine< T & >
-
-template< typename T >
-template< typename StackAllocator, typename Fn >
-pull_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
- Fn && fn_, bool preserve_fpu_) :
- other( nullptr),
- ctx( std::allocator_arg, palloc, salloc,
- [=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
- // create synthesized push_coroutine< T >
- typename push_coroutine< T & >::control_block synthesized_cb( this, ctx);
- push_coroutine< T & > synthesized( & synthesized_cb);
- other = & synthesized_cb;
- try {
- // call coroutine-fn with synthesized push_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- // set termination flags
- state |= static_cast< int >( state_t::complete);
- // jump back to ctx
- other->ctx( nullptr, preserve_fpu);
- BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
- }),
- preserve_fpu( preserve_fpu_),
- state( static_cast< int >( state_t::unwind) ),
- except(),
- t( nullptr) {
- // enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
- t = reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) );
-}
-
-template< typename T >
-pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb,
- boost::context::execution_context const& ctx_) :
- other( cb),
- ctx( ctx_),
- preserve_fpu( other->preserve_fpu),
- state( 0),
- except(),
- t( nullptr) {
-}
-
-template< typename T >
-pull_coroutine< T & >::control_block::~control_block() {
- if ( 0 == ( state & static_cast< int >( state_t::complete ) ) &&
- 0 != ( state & static_cast< int >( state_t::unwind) ) ) {
- // set early-exit flag
- state |= static_cast< int >( state_t::early_exit);
- ctx( nullptr, preserve_fpu);
- }
-}
-
-template< typename T >
-void
-pull_coroutine< T & >::control_block::resume() {
- other->ctx = boost::context::execution_context::current();
- t = reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) );
- if ( except) {
- std::rethrow_exception( except);
- }
- // test early-exit-flag
- if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) {
- throw forced_unwind();
- }
-}
-
-template< typename T >
-T &
-pull_coroutine< T & >::control_block::get() {
- return * reinterpret_cast< T * >( t);
-}
-
-template< typename T >
-bool
-pull_coroutine< T & >::control_block::valid() const noexcept {
- return nullptr != other && 0 == ( state & static_cast< int >( state_t::complete) ) && nullptr != t;
-}
-
-
-// pull_coroutine< void >
-
-template< typename StackAllocator, typename Fn >
-pull_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
- Fn && fn_, bool preserve_fpu_) :
- other( nullptr),
- ctx( std::allocator_arg, palloc, salloc,
- [=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
- // create synthesized push_coroutine< T >
- typename push_coroutine< void >::control_block synthesized_cb( this, ctx);
- push_coroutine< void > synthesized( & synthesized_cb);
- other = & synthesized_cb;
- try {
- // call coroutine-fn with synthesized push_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- // set termination flags
- state |= static_cast< int >( state_t::complete);
- // jump back to ctx
- other->ctx( nullptr, preserve_fpu);
- BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
- }),
- preserve_fpu( preserve_fpu_),
- state( static_cast< int >( state_t::unwind) ),
- except() {
- // enter coroutine-fn in order to have first value available after ctor returns
- ctx( nullptr, preserve_fpu);
-}
-
-inline
-pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb,
- boost::context::execution_context const& ctx_) :
- other( cb),
- ctx( ctx_),
- preserve_fpu( other->preserve_fpu),
- state( 0),
- except() {
-}
-
-inline
-pull_coroutine< void >::control_block::~control_block() {
- if ( 0 == ( state & static_cast< int >( state_t::complete ) ) &&
- 0 != ( state & static_cast< int >( state_t::unwind) ) ) {
- // set early-exit flag
- state |= static_cast< int >( state_t::early_exit);
- ctx( nullptr, preserve_fpu);
- }
-}
-
-inline
-void
-pull_coroutine< void >::control_block::resume() {
- other->ctx = boost::context::execution_context::current();
- ctx( nullptr, preserve_fpu);
- if ( except) {
- std::rethrow_exception( except);
- }
- // test early-exit-flag
- if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) {
- throw forced_unwind();
- }
-}
-
-inline
-bool
-pull_coroutine< void >::control_block::valid() const noexcept {
- return nullptr != other && 0 == ( state & static_cast< int >( state_t::complete) );
-}
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
diff --git a/boost/coroutine2/detail/pull_control_block.hpp b/boost/coroutine2/detail/pull_control_block_ecv1.hpp
index 7009454c88..16d65a3e62 100644
--- a/boost/coroutine2/detail/pull_control_block.hpp
+++ b/boost/coroutine2/detail/pull_control_block_ecv1.hpp
@@ -8,11 +8,14 @@
#define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_HPP
#include <exception>
+#include <functional>
#include <type_traits>
#include <boost/config.hpp>
#include <boost/context/execution_context.hpp>
+#include <boost/coroutine2/detail/state.hpp>
+
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
@@ -23,76 +26,85 @@ namespace detail {
template< typename T >
struct pull_coroutine< T >::control_block {
- typename push_coroutine< T >::control_block * other;
boost::context::execution_context ctx;
- bool preserve_fpu;
- int state;
+ typename push_coroutine< T >::control_block * other;
+ state_t state;
std::exception_ptr except;
bool bvalid;
- typename std::aligned_storage< sizeof( T), alignof( T) >::type storage[1];
+ typename std::aligned_storage< sizeof( T), alignof( T) >::type storage;
+
+ static void destroy( control_block * cb) noexcept;
template< typename StackAllocator, typename Fn >
- control_block( context::preallocated, StackAllocator, Fn &&, bool);
+ control_block( context::preallocated, StackAllocator, Fn &&);
- explicit control_block( typename push_coroutine< T >::control_block *, boost::context::execution_context const&);
+ control_block( typename push_coroutine< T >::control_block *, boost::context::execution_context const&) noexcept;
- ~control_block();
+ ~control_block() noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
+ void deallocate() noexcept;
+
void resume();
void set( T *);
- T & get();
+ T & get() noexcept;
bool valid() const noexcept;
};
template< typename T >
struct pull_coroutine< T & >::control_block {
- typename push_coroutine< T & >::control_block * other;
boost::context::execution_context ctx;
- bool preserve_fpu;
- int state;
+ typename push_coroutine< T & >::control_block * other;
+ state_t state;
std::exception_ptr except;
T * t;
+ static void destroy( control_block * cb) noexcept;
+
template< typename StackAllocator, typename Fn >
- control_block( context::preallocated, StackAllocator, Fn &&, bool);
+ control_block( context::preallocated, StackAllocator, Fn &&);
- explicit control_block( typename push_coroutine< T & >::control_block *, boost::context::execution_context const&);
+ control_block( typename push_coroutine< T & >::control_block *, boost::context::execution_context const&) noexcept;
- ~control_block();
+ ~control_block() noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
+ void deallocate() noexcept;
+
void resume();
- T & get();
+ T & get() noexcept;
bool valid() const noexcept;
};
struct pull_coroutine< void >::control_block {
- push_coroutine< void >::control_block * other;
boost::context::execution_context ctx;
- bool preserve_fpu;
- int state;
+ push_coroutine< void >::control_block * other;
+ state_t state;
std::exception_ptr except;
+ static void destroy( control_block * cb) noexcept;
+
template< typename StackAllocator, typename Fn >
- control_block( context::preallocated, StackAllocator, Fn &&, bool);
+ control_block( context::preallocated, StackAllocator, Fn &&);
- explicit control_block( push_coroutine< void >::control_block *, boost::context::execution_context const&);
+ control_block( push_coroutine< void >::control_block *, boost::context::execution_context const&) noexcept;
- ~control_block();
+ ~control_block() noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
+ void deallocate() noexcept;
+
void resume();
bool valid() const noexcept;
diff --git a/boost/coroutine2/detail/pull_control_block_ecv1.ipp b/boost/coroutine2/detail/pull_control_block_ecv1.ipp
new file mode 100644
index 0000000000..f271e795df
--- /dev/null
+++ b/boost/coroutine2/detail/pull_control_block_ecv1.ipp
@@ -0,0 +1,421 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
+#define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
+
+#include <exception>
+#include <functional>
+#include <memory>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/context/execution_context.hpp>
+
+#include <boost/coroutine2/detail/config.hpp>
+#include <boost/coroutine2/detail/decay_copy.hpp>
+#include <boost/coroutine2/detail/forced_unwind.hpp>
+#include <boost/coroutine2/detail/state.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines2 {
+namespace detail {
+
+// pull_coroutine< T >
+
+template< typename T >
+void
+pull_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
+ boost::context::execution_context ctx = cb->ctx;
+ // destroy control structure
+ cb->~control_block();
+}
+
+template< typename T >
+template< typename StackAllocator, typename Fn >
+pull_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
+ Fn && fn) :
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ ctx{ std::allocator_arg, palloc, salloc,
+ std::move(
+ std::bind(
+ [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx, void *) mutable noexcept {
+ // create synthesized push_coroutine< T >
+ typename push_coroutine< T >::control_block synthesized_cb{ this, ctx };
+ push_coroutine< T > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ try {
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized push_coroutine as argument
+ fn( synthesized);
+ } catch ( forced_unwind const&) {
+ // do nothing for unwinding exception
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ other->ctx();
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ },
+ std::forward< Fn >( fn),
+ boost::context::execution_context::current(),
+ std::placeholders::_1))},
+#else
+ ctx{ std::allocator_arg, palloc, salloc,
+ [this,fn_=decay_copy( std::forward< Fn >( fn) ),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
+ // create synthesized push_coroutine< T >
+ typename push_coroutine< T >::control_block synthesized_cb{ this, ctx };
+ push_coroutine< T > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ try {
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized push_coroutine as argument
+ fn( synthesized);
+ } catch ( forced_unwind const&) {
+ // do nothing for unwinding exception
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ other->ctx();
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }},
+#endif
+ other{ nullptr },
+ state{ state_t::unwind },
+ except{},
+ bvalid{ false },
+ storage{} {
+ // enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
+ set( static_cast< T * >( ctx() ) );
+}
+
+template< typename T >
+pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb,
+ boost::context::execution_context const& ctx_) noexcept :
+ ctx{ ctx_ },
+ other{ cb },
+ state{ state_t::none },
+ except{},
+ bvalid{ false },
+ storage{} {
+}
+
+template< typename T >
+pull_coroutine< T >::control_block::~control_block() {
+ if ( state_t::none == ( state & state_t::complete) &&
+ state_t::none != ( state & state_t::unwind) ) {
+ // unwind coroutine stack
+ ctx( context::exec_ontop_arg, unwind_coroutine);
+ }
+ // destroy data if it set
+ if ( bvalid) {
+ reinterpret_cast< T * >( std::addressof( storage) )->~T();
+ }
+}
+
+template< typename T >
+void
+pull_coroutine< T >::control_block::deallocate() noexcept {
+ if ( state_t::none != ( state & state_t::unwind) ) {
+ destroy( this);
+ }
+}
+
+template< typename T >
+void
+pull_coroutine< T >::control_block::resume() {
+ other->ctx = boost::context::execution_context::current();
+ set( static_cast< T * >( ctx() ) );
+ if ( except) {
+ std::rethrow_exception( except);
+ }
+}
+
+template< typename T >
+void
+pull_coroutine< T >::control_block::set( T * t) {
+ // destroy data if it set
+ if ( bvalid) {
+ reinterpret_cast< T * >( std::addressof( storage) )->~T();
+ }
+ if ( nullptr != t) {
+ ::new ( static_cast< void * >( std::addressof( storage) ) ) T( std::move( * t) );
+ bvalid = true;
+ } else {
+ bvalid = false;
+ }
+}
+
+template< typename T >
+T &
+pull_coroutine< T >::control_block::get() noexcept {
+ return * reinterpret_cast< T * >( std::addressof( storage) );
+}
+
+template< typename T >
+bool
+pull_coroutine< T >::control_block::valid() const noexcept {
+ return nullptr != other && state_t::none == ( state & state_t::complete) && bvalid;
+}
+
+
+// pull_coroutine< T & >
+
+template< typename T >
+void
+pull_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
+ boost::context::execution_context ctx = cb->ctx;
+ // destroy control structure
+ cb->~control_block();
+}
+
+template< typename T >
+template< typename StackAllocator, typename Fn >
+pull_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
+ Fn && fn) :
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ ctx{ std::allocator_arg, palloc, salloc,
+ std::move(
+ std::bind(
+ [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx, void *) mutable noexcept {
+ // create synthesized push_coroutine< T >
+ typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx };
+ push_coroutine< T & > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ try {
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized push_coroutine as argument
+ fn( synthesized);
+ } catch ( forced_unwind const&) {
+ // do nothing for unwinding exception
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ other->ctx();
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ },
+ std::forward< Fn >( fn),
+ boost::context::execution_context::current(),
+ std::placeholders::_1))},
+#else
+ ctx{ std::allocator_arg, palloc, salloc,
+ [this,fn_=decay_copy( std::forward< Fn >( fn) ),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
+ // create synthesized push_coroutine< T >
+ typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx };
+ push_coroutine< T & > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ try {
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized push_coroutine as argument
+ fn( synthesized);
+ } catch ( forced_unwind const&) {
+ // do nothing for unwinding exception
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ other->ctx();
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }},
+#endif
+ other{ nullptr },
+ state{ state_t::unwind },
+ except{},
+ t{ nullptr } {
+ // enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
+ t = static_cast< T * >( ctx() );
+}
+
+template< typename T >
+pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb,
+ boost::context::execution_context const& ctx_) noexcept :
+ ctx{ ctx_ },
+ other{ cb },
+ state{ state_t::none },
+ except{},
+ t( nullptr) {
+}
+
+template< typename T >
+pull_coroutine< T & >::control_block::~control_block() {
+ if ( state_t::none == ( state & state_t::complete) &&
+ state_t::none != ( state & state_t::unwind) ) {
+ // unwind coroutine stack
+ ctx( context::exec_ontop_arg, unwind_coroutine);
+ }
+}
+
+template< typename T >
+void
+pull_coroutine< T & >::control_block::deallocate() noexcept {
+ if ( state_t::none != ( state & state_t::unwind) ) {
+ destroy( this);
+ }
+}
+
+template< typename T >
+void
+pull_coroutine< T & >::control_block::resume() {
+ other->ctx = boost::context::execution_context::current();
+ t = static_cast< T * >( ctx() );
+ if ( except) {
+ std::rethrow_exception( except);
+ }
+}
+
+template< typename T >
+T &
+pull_coroutine< T & >::control_block::get() noexcept {
+ return * static_cast< T * >( t);
+}
+
+template< typename T >
+bool
+pull_coroutine< T & >::control_block::valid() const noexcept {
+ return nullptr != other && state_t::none == ( state & state_t::complete) && nullptr != t;
+}
+
+
+// pull_coroutine< void >
+
+inline
+void
+pull_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
+ boost::context::execution_context ctx = cb->ctx;
+ // destroy control structure
+ cb->~control_block();
+}
+
+template< typename StackAllocator, typename Fn >
+pull_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
+ Fn && fn) :
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ ctx{ std::allocator_arg, palloc, salloc,
+ std::move(
+ std::bind(
+ [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx, void *) mutable noexcept {
+ // create synthesized push_coroutine< T >
+ typename push_coroutine< void >::control_block synthesized_cb{ this, ctx };
+ push_coroutine< void > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ try {
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized push_coroutine as argument
+ fn( synthesized);
+ } catch ( forced_unwind const&) {
+ // do nothing for unwinding exception
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ other->ctx();
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ },
+ std::forward< Fn >( fn),
+ boost::context::execution_context::current(),
+ std::placeholders::_1))},
+#else
+ ctx{ std::allocator_arg, palloc, salloc,
+ [this,fn_=decay_copy( std::forward< Fn >( fn) ),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
+ // create synthesized push_coroutine< T >
+ typename push_coroutine< void >::control_block synthesized_cb{ this, ctx };
+ push_coroutine< void > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ try {
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized push_coroutine as argument
+ fn( synthesized);
+ } catch ( forced_unwind const&) {
+ // do nothing for unwinding exception
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ other->ctx();
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }},
+#endif
+ other{ nullptr },
+ state{ state_t::unwind },
+ except{} {
+ // enter coroutine-fn in order to have first value available after ctor returns
+ ctx();
+}
+
+inline
+pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb,
+ boost::context::execution_context const& ctx_) noexcept :
+ ctx{ ctx_ },
+ other{ cb },
+ state{ state_t::none },
+ except{} {
+}
+
+inline
+pull_coroutine< void >::control_block::~control_block() {
+ if ( state_t::none == ( state & state_t::complete) &&
+ state_t::none != ( state & state_t::unwind) ) {
+ // unwind coroutine stack
+ ctx( context::exec_ontop_arg, unwind_coroutine);
+ }
+}
+
+inline
+void
+pull_coroutine< void >::control_block::deallocate() noexcept {
+ if ( state_t::none != ( state & state_t::unwind) ) {
+ destroy( this);
+ }
+}
+
+inline
+void
+pull_coroutine< void >::control_block::resume() {
+ other->ctx = boost::context::execution_context::current();
+ ctx();
+ if ( except) {
+ std::rethrow_exception( except);
+ }
+}
+
+inline
+bool
+pull_coroutine< void >::control_block::valid() const noexcept {
+ return nullptr != other && state_t::none == ( state & state_t::complete);
+}
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
diff --git a/boost/coroutine2/detail/pull_control_block_ecv2.hpp b/boost/coroutine2/detail/pull_control_block_ecv2.hpp
new file mode 100644
index 0000000000..58d248833a
--- /dev/null
+++ b/boost/coroutine2/detail/pull_control_block_ecv2.hpp
@@ -0,0 +1,114 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_HPP
+#define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_HPP
+
+#include <exception>
+#include <type_traits>
+
+#include <boost/config.hpp>
+#include <boost/context/execution_context.hpp>
+
+#include <boost/coroutine2/detail/state.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines2 {
+namespace detail {
+
+template< typename T >
+struct pull_coroutine< T >::control_block {
+ boost::context::execution_context< T * > ctx;
+ typename push_coroutine< T >::control_block * other;
+ state_t state;
+ std::exception_ptr except;
+ bool bvalid;
+ typename std::aligned_storage< sizeof( T), alignof( T) >::type storage;
+
+ static void destroy( control_block * cb) noexcept;
+
+ template< typename StackAllocator, typename Fn >
+ control_block( context::preallocated, StackAllocator, Fn &&);
+
+ control_block( typename push_coroutine< T >::control_block *, boost::context::execution_context< T * > &) noexcept;
+
+ ~control_block();
+
+ control_block( control_block &) = delete;
+ control_block & operator=( control_block &) = delete;
+
+ void deallocate() noexcept;
+
+ void resume();
+
+ void set( T *);
+
+ T & get() noexcept;
+
+ bool valid() const noexcept;
+};
+
+template< typename T >
+struct pull_coroutine< T & >::control_block {
+ boost::context::execution_context< T * > ctx;
+ typename push_coroutine< T & >::control_block * other;
+ state_t state;
+ std::exception_ptr except;
+ T * t;
+
+ static void destroy( control_block * cb) noexcept;
+
+ template< typename StackAllocator, typename Fn >
+ control_block( context::preallocated, StackAllocator, Fn &&);
+
+ control_block( typename push_coroutine< T & >::control_block *, boost::context::execution_context< T * > &) noexcept;
+
+ control_block( control_block &) = delete;
+ control_block & operator=( control_block &) = delete;
+
+ void deallocate() noexcept;
+
+ void resume();
+
+ T & get() noexcept;
+
+ bool valid() const noexcept;
+};
+
+struct pull_coroutine< void >::control_block {
+ boost::context::execution_context< void > ctx;
+ push_coroutine< void >::control_block * other;
+ state_t state;
+ std::exception_ptr except;
+
+ static void destroy( control_block * cb) noexcept;
+
+ template< typename StackAllocator, typename Fn >
+ control_block( context::preallocated, StackAllocator, Fn &&);
+
+ control_block( push_coroutine< void >::control_block *, boost::context::execution_context< void > &) noexcept;
+
+ control_block( control_block &) = delete;
+ control_block & operator=( control_block &) = delete;
+
+ void deallocate() noexcept;
+
+ void resume();
+
+ bool valid() const noexcept;
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_HPP
diff --git a/boost/coroutine2/detail/pull_control_block_ecv2.ipp b/boost/coroutine2/detail/pull_control_block_ecv2.ipp
new file mode 100644
index 0000000000..785bc59ff1
--- /dev/null
+++ b/boost/coroutine2/detail/pull_control_block_ecv2.ipp
@@ -0,0 +1,411 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
+#define BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
+
+#include <algorithm>
+#include <exception>
+#include <memory>
+#include <tuple>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/context/execution_context.hpp>
+
+#include <boost/coroutine2/detail/config.hpp>
+#include <boost/coroutine2/detail/forced_unwind.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines2 {
+namespace detail {
+
+// pull_coroutine< T >
+
+template< typename T >
+void
+pull_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
+ boost::context::execution_context< T * > ctx = std::move( cb->ctx);
+ // destroy control structure
+ cb->~control_block();
+ // destroy coroutine's stack
+ ctx( nullptr);
+}
+
+template< typename T >
+template< typename StackAllocator, typename Fn >
+pull_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
+ Fn && fn) :
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ ctx{ std::allocator_arg, palloc, salloc,
+ std::move(
+ std::bind(
+ [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< T * > ctx, T *) mutable {
+ // create synthesized push_coroutine< T >
+ typename push_coroutine< T >::control_block synthesized_cb{ this, ctx };
+ push_coroutine< T > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ try {
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized push_coroutine as argument
+ fn( synthesized);
+ } catch ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ auto result = other->ctx( nullptr);
+ other->ctx = std::move( std::get< 0 >( result) );
+ return std::move( other->ctx);
+ },
+ std::forward< Fn >( fn),
+ std::placeholders::_1,
+ std::placeholders::_2))},
+#else
+ ctx{ std::allocator_arg, palloc, salloc,
+ [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< T * > ctx, T *) mutable {
+ // create synthesized push_coroutine< T >
+ typename push_coroutine< T >::control_block synthesized_cb{ this, ctx };
+ push_coroutine< T > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ try {
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized push_coroutine as argument
+ fn( synthesized);
+ } catch ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ auto result = other->ctx( nullptr);
+ other->ctx = std::move( std::get< 0 >( result) );
+ return std::move( other->ctx);
+ }},
+#endif
+ other{ nullptr },
+ state{ state_t::unwind },
+ except{},
+ bvalid{ false },
+ storage{} {
+ // enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
+ auto result = ctx( nullptr);
+ ctx = std::move( std::get< 0 >( result) );
+ set( std::get< 1 >( result) );
+}
+
+template< typename T >
+pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb,
+ boost::context::execution_context< T * > & ctx_) noexcept :
+ ctx{ std::move( ctx_) },
+ other{ cb },
+ state{ state_t::none },
+ except{},
+ bvalid{ false },
+ storage{} {
+}
+
+template< typename T >
+pull_coroutine< T >::control_block::~control_block() {
+ // destroy data if set
+ if ( bvalid) {
+ reinterpret_cast< T * >( std::addressof( storage) )->~T();
+ }
+}
+
+template< typename T >
+void
+pull_coroutine< T >::control_block::deallocate() noexcept {
+ if ( state_t::none != ( state & state_t::unwind) ) {
+ destroy( this);
+ }
+}
+
+template< typename T >
+void
+pull_coroutine< T >::control_block::resume() {
+ auto result = ctx( nullptr);
+ ctx = std::move( std::get< 0 >( result) );
+ set( std::get< 1 >( result) );
+ if ( except) {
+ std::rethrow_exception( except);
+ }
+}
+
+template< typename T >
+void
+pull_coroutine< T >::control_block::set( T * t) {
+ // destroy data if set
+ if ( bvalid) {
+ reinterpret_cast< T * >( std::addressof( storage) )->~T();
+ }
+ if ( nullptr != t) {
+ ::new ( static_cast< void * >( std::addressof( storage) ) ) T( std::move( * t) );
+ bvalid = true;
+ } else {
+ bvalid = false;
+ }
+}
+
+template< typename T >
+T &
+pull_coroutine< T >::control_block::get() noexcept {
+ return * reinterpret_cast< T * >( std::addressof( storage) );
+}
+
+template< typename T >
+bool
+pull_coroutine< T >::control_block::valid() const noexcept {
+ return nullptr != other && state_t::none == ( state & state_t::complete) && bvalid;
+}
+
+
+// pull_coroutine< T & >
+
+template< typename T >
+void
+pull_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
+ boost::context::execution_context< T * > ctx = std::move( cb->ctx);
+ // destroy control structure
+ cb->~control_block();
+ // destroy coroutine's stack
+ ctx( nullptr);
+}
+
+template< typename T >
+template< typename StackAllocator, typename Fn >
+pull_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
+ Fn && fn) :
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ ctx{ std::allocator_arg, palloc, salloc,
+ std::move(
+ std::bind(
+ [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< T *> ctx, T *) mutable {
+ // create synthesized push_coroutine< T & >
+ typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx };
+ push_coroutine< T & > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ try {
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized push_coroutine as argument
+ fn( synthesized);
+ } catch ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ auto result = other->ctx( nullptr);
+ other->ctx = std::move( std::get< 0 >( result) );
+ return std::move( other->ctx);
+ },
+ std::forward< Fn >( fn),
+ std::placeholders::_1,
+ std::placeholders::_2))},
+#else
+ ctx{ std::allocator_arg, palloc, salloc,
+ [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< T * > ctx, T *) mutable {
+ // create synthesized push_coroutine< T & >
+ typename push_coroutine< T & >::control_block synthesized_cb{ this, ctx };
+ push_coroutine< T & > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ try {
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized push_coroutine as argument
+ fn( synthesized);
+ } catch ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ auto result = other->ctx( nullptr);
+ other->ctx = std::move( std::get< 0 >( result) );
+ return std::move( other->ctx);
+ }},
+#endif
+ other{ nullptr },
+ state{ state_t::unwind },
+ except{},
+ t{ nullptr } {
+ // enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
+ auto result = ctx( nullptr);
+ ctx = std::move( std::get< 0 >( result) );
+ t = std::get< 1 >( result);
+}
+
+template< typename T >
+pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb,
+ boost::context::execution_context< T * > & ctx_) noexcept :
+ ctx{ std::move( ctx_) },
+ other{ cb },
+ state{ state_t::none },
+ except{},
+ t{ nullptr } {
+}
+
+template< typename T >
+void
+pull_coroutine< T & >::control_block::deallocate() noexcept {
+ if ( state_t::none != ( state & state_t::unwind) ) {
+ destroy( this);
+ }
+}
+
+template< typename T >
+void
+pull_coroutine< T & >::control_block::resume() {
+ auto result = ctx( nullptr);
+ ctx = std::move( std::get< 0 >( result) );
+ t = std::get< 1 >( result);
+ if ( except) {
+ std::rethrow_exception( except);
+ }
+}
+
+template< typename T >
+T &
+pull_coroutine< T & >::control_block::get() noexcept {
+ return * t;
+}
+
+template< typename T >
+bool
+pull_coroutine< T & >::control_block::valid() const noexcept {
+ return nullptr != other && state_t::none == ( state & state_t::complete) && nullptr != t;
+}
+
+
+// pull_coroutine< void >
+
+inline
+void
+pull_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
+ boost::context::execution_context< void > ctx = std::move( cb->ctx);
+ // destroy control structure
+ cb->~control_block();
+ // destroy coroutine's stack
+ ctx();
+}
+
+template< typename StackAllocator, typename Fn >
+pull_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
+ Fn && fn) :
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ ctx{ std::allocator_arg, palloc, salloc,
+ std::move(
+ std::bind(
+ [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< void > ctx) mutable {
+ // create synthesized push_coroutine< void >
+ typename push_coroutine< void >::control_block synthesized_cb{ this, ctx };
+ push_coroutine< void > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ try {
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized push_coroutine as argument
+ fn( synthesized);
+ } catch ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ other->ctx = other->ctx();
+ return std::move( other->ctx);
+ },
+ std::forward< Fn >( fn),
+ std::placeholders::_1))},
+#else
+ ctx{ std::allocator_arg, palloc, salloc,
+ [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< void > ctx) mutable {
+ // create synthesized push_coroutine< void >
+ typename push_coroutine< void >::control_block synthesized_cb{ this, ctx };
+ push_coroutine< void > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ try {
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized push_coroutine as argument
+ fn( synthesized);
+ } catch ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ other->ctx = other->ctx();
+ return std::move( other->ctx);
+ }},
+#endif
+ other{ nullptr },
+ state{ state_t::unwind },
+ except{} {
+ // enter coroutine-fn in order to have first value available after ctor (of `*this`) returns
+ ctx = ctx();
+}
+
+inline
+pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb,
+ boost::context::execution_context< void > & ctx_) noexcept :
+ ctx{ std::move( ctx_) },
+ other{ cb },
+ state{ state_t::none },
+ except{} {
+}
+
+inline
+void
+pull_coroutine< void >::control_block::deallocate() noexcept {
+ if ( state_t::none != ( state & state_t::unwind) ) {
+ destroy( this);
+ }
+}
+
+inline
+void
+pull_coroutine< void >::control_block::resume() {
+ ctx = ctx();
+ if ( except) {
+ std::rethrow_exception( except);
+ }
+}
+
+inline
+bool
+pull_coroutine< void >::control_block::valid() const noexcept {
+ return nullptr != other && state_t::none == ( state & state_t::complete);
+}
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES2_DETAIL_PULL_CONTROL_BLOCK_IPP
diff --git a/boost/coroutine2/detail/pull_coroutine.hpp b/boost/coroutine2/detail/pull_coroutine.hpp
index c78750442e..7123eac8b8 100644
--- a/boost/coroutine2/detail/pull_coroutine.hpp
+++ b/boost/coroutine2/detail/pull_coroutine.hpp
@@ -12,9 +12,9 @@
#include <boost/assert.hpp>
#include <boost/config.hpp>
-#include <boost/context/execution_context.hpp>
#include <boost/coroutine2/detail/config.hpp>
+#include <boost/coroutine2/detail/disable_overload.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
@@ -34,29 +34,30 @@ private:
control_block * cb_;
- explicit pull_coroutine( control_block *);
+ explicit pull_coroutine( control_block *) noexcept;
- bool has_result_() const;
+ bool has_result_() const noexcept;
public:
- template< typename Fn >
- explicit pull_coroutine( Fn &&, bool = false);
+ template< typename Fn,
+ typename = detail::disable_overload< pull_coroutine, Fn >
+ >
+ explicit pull_coroutine( Fn &&);
template< typename StackAllocator, typename Fn >
- explicit pull_coroutine( StackAllocator, Fn &&, bool = false);
+ pull_coroutine( StackAllocator, Fn &&);
- ~pull_coroutine();
+ ~pull_coroutine() noexcept;
pull_coroutine( pull_coroutine const&) = delete;
pull_coroutine & operator=( pull_coroutine const&) = delete;
- pull_coroutine( pull_coroutine &&);
+ pull_coroutine( pull_coroutine &&) noexcept;
- pull_coroutine & operator=( pull_coroutine && other) {
- if ( this != & other) {
- cb_ = other.cb_;
- other.cb_ = nullptr;
- }
+ pull_coroutine & operator=( pull_coroutine && other) noexcept {
+ if ( this == & other) return * this;
+ cb_ = other.cb_;
+ other.cb_ = nullptr;
return * this;
}
@@ -66,13 +67,13 @@ public:
bool operator!() const noexcept;
- T get();
+ T get() noexcept;
class iterator : public std::iterator< std::input_iterator_tag, typename std::remove_reference< T >::type > {
private:
- pull_coroutine< T > * c_;
+ pull_coroutine< T > * c_{ nullptr };
- void fetch_() {
+ void fetch_() noexcept {
BOOST_ASSERT( nullptr != c_);
if ( ! ( * c_) ) {
c_ = nullptr;
@@ -91,30 +92,28 @@ public:
typedef typename iterator::pointer pointer_t;
typedef typename iterator::reference reference_t;
- iterator() :
- c_( nullptr) {
- }
+ constexpr iterator() noexcept = default;
- explicit iterator( pull_coroutine< T > * c) :
- c_( c) {
+ explicit iterator( pull_coroutine< T > * c) noexcept :
+ c_{ c } {
fetch_();
}
- iterator( iterator const& other) :
- c_( other.c_) {
+ iterator( iterator const& other) noexcept :
+ c_{ other.c_ } {
}
- iterator & operator=( iterator const& other) {
+ iterator & operator=( iterator const& other) noexcept {
if ( this == & other) return * this;
c_ = other.c_;
return * this;
}
- bool operator==( iterator const& other) const {
+ bool operator==( iterator const& other) const noexcept {
return other.c_ == c_;
}
- bool operator!=( iterator const& other) const {
+ bool operator!=( iterator const& other) const noexcept {
return other.c_ != c_;
}
@@ -125,11 +124,11 @@ public:
iterator operator++( int) = delete;
- reference_t operator*() const {
+ reference_t operator*() const noexcept {
return c_->cb_->get();
}
- pointer_t operator->() const {
+ pointer_t operator->() const noexcept {
return std::addressof( c_->cb_->get() );
}
};
@@ -147,29 +146,30 @@ private:
control_block * cb_;
- explicit pull_coroutine( control_block *);
+ explicit pull_coroutine( control_block *) noexcept;
- bool has_result_() const;
+ bool has_result_() const noexcept;
public:
- template< typename Fn >
- explicit pull_coroutine( Fn &&, bool = false);
+ template< typename Fn,
+ typename = detail::disable_overload< pull_coroutine, Fn >
+ >
+ explicit pull_coroutine( Fn &&);
template< typename StackAllocator, typename Fn >
- explicit pull_coroutine( StackAllocator, Fn &&, bool = false);
+ pull_coroutine( StackAllocator, Fn &&);
- ~pull_coroutine();
+ ~pull_coroutine() noexcept;
pull_coroutine( pull_coroutine const&) = delete;
pull_coroutine & operator=( pull_coroutine const&) = delete;
- pull_coroutine( pull_coroutine &&);
+ pull_coroutine( pull_coroutine &&) noexcept;
- pull_coroutine & operator=( pull_coroutine && other) {
- if ( this != & other) {
- cb_ = other.cb_;
- other.cb_ = nullptr;
- }
+ pull_coroutine & operator=( pull_coroutine && other) noexcept {
+ if ( this == & other) return * this;
+ cb_ = other.cb_;
+ other.cb_ = nullptr;
return * this;
}
@@ -179,13 +179,13 @@ public:
bool operator!() const noexcept;
- T & get();
+ T & get() noexcept;
class iterator : public std::iterator< std::input_iterator_tag, typename std::remove_reference< T >::type > {
private:
- pull_coroutine< T & > * c_;
+ pull_coroutine< T & > * c_{ nullptr };
- void fetch_() {
+ void fetch_() noexcept {
BOOST_ASSERT( nullptr != c_);
if ( ! ( * c_) ) {
c_ = nullptr;
@@ -204,30 +204,28 @@ public:
typedef typename iterator::pointer pointer_t;
typedef typename iterator::reference reference_t;
- iterator() :
- c_( nullptr) {
- }
+ constexpr iterator() noexcept = default;
- explicit iterator( pull_coroutine< T & > * c) :
- c_( c) {
+ explicit iterator( pull_coroutine< T & > * c) noexcept :
+ c_{ c } {
fetch_();
}
- iterator( iterator const& other) :
- c_( other.c_) {
+ iterator( iterator const& other) noexcept :
+ c_{ other.c_ } {
}
- iterator & operator=( iterator const& other) {
+ iterator & operator=( iterator const& other) noexcept {
if ( this == & other) return * this;
c_ = other.c_;
return * this;
}
- bool operator==( iterator const& other) const {
+ bool operator==( iterator const& other) const noexcept {
return other.c_ == c_;
}
- bool operator!=( iterator const& other) const {
+ bool operator!=( iterator const& other) const noexcept {
return other.c_ != c_;
}
@@ -238,11 +236,11 @@ public:
iterator operator++( int) = delete;
- reference_t operator*() const {
+ reference_t operator*() const noexcept {
return c_->cb_->get();
}
- pointer_t operator->() const {
+ pointer_t operator->() const noexcept {
return std::addressof( c_->cb_->get() );
}
};
@@ -260,27 +258,28 @@ private:
control_block * cb_;
- explicit pull_coroutine( control_block *);
+ explicit pull_coroutine( control_block *) noexcept;
public:
- template< typename Fn >
- explicit pull_coroutine( Fn &&, bool = false);
+ template< typename Fn,
+ typename = detail::disable_overload< pull_coroutine, Fn >
+ >
+ explicit pull_coroutine( Fn &&);
template< typename StackAllocator, typename Fn >
- explicit pull_coroutine( StackAllocator, Fn &&, bool = false);
+ pull_coroutine( StackAllocator, Fn &&);
- ~pull_coroutine();
+ ~pull_coroutine() noexcept;
pull_coroutine( pull_coroutine const&) = delete;
pull_coroutine & operator=( pull_coroutine const&) = delete;
- pull_coroutine( pull_coroutine &&);
+ pull_coroutine( pull_coroutine &&) noexcept;
- pull_coroutine & operator=( pull_coroutine && other) {
- if ( this != & other) {
- cb_ = other.cb_;
- other.cb_ = nullptr;
- }
+ pull_coroutine & operator=( pull_coroutine && other) noexcept {
+ if ( this == & other) return * this;
+ cb_ = other.cb_;
+ other.cb_ = nullptr;
return * this;
}
diff --git a/boost/coroutine2/detail/pull_coroutine.ipp b/boost/coroutine2/detail/pull_coroutine.ipp
index 2e37ef2a98..58fe84575e 100644
--- a/boost/coroutine2/detail/pull_coroutine.ipp
+++ b/boost/coroutine2/detail/pull_coroutine.ipp
@@ -8,16 +8,14 @@
#define BOOST_COROUTINES2_DETAIL_PULL_COROUTINE_IPP
#include <algorithm>
-#include <memory>
#include <utility>
#include <boost/assert.hpp>
#include <boost/config.hpp>
-#include <boost/context/execution_context.hpp>
-#include <boost/context/stack_context.hpp>
-
#include <boost/coroutine2/detail/config.hpp>
+#include <boost/coroutine2/detail/create_control_block.ipp>
+#include <boost/coroutine2/detail/disable_overload.hpp>
#include <boost/coroutine2/fixedsize_stack.hpp>
#include <boost/coroutine2/segmented_stack.hpp>
@@ -32,58 +30,44 @@ namespace detail {
// pull_coroutine< T >
template< typename T >
-pull_coroutine< T >::pull_coroutine( control_block * cb) :
- cb_( cb) {
+pull_coroutine< T >::pull_coroutine( control_block * cb) noexcept :
+ cb_{ cb } {
}
template< typename T >
bool
-pull_coroutine< T >::has_result_() const {
+pull_coroutine< T >::has_result_() const noexcept {
return nullptr != cb_->other->t;
}
template< typename T >
-template< typename Fn >
-pull_coroutine< T >::pull_coroutine( Fn && fn, bool preserve_fpu) :
- pull_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) {
+template< typename Fn,
+ typename
+>
+pull_coroutine< T >::pull_coroutine( Fn && fn) :
+ pull_coroutine{ default_stack(), std::forward< Fn >( fn) } {
}
template< typename T >
template< typename StackAllocator, typename Fn >
-pull_coroutine< T >::pull_coroutine( StackAllocator salloc, Fn && fn, bool preserve_fpu) :
- cb_( nullptr) {
- context::stack_context sctx( salloc.allocate() );
- // reserve space for control structure
-#if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
- void * sp = static_cast< char * >( sctx.sp) - sizeof( control_block);
- std::size_t size = sctx.size - sizeof( control_block);
-#else
- constexpr std::size_t func_alignment = 64; // alignof( control_block);
- constexpr std::size_t func_size = sizeof( control_block);
- // reserve space on stack
- void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
- // align sp pointer
- std::size_t space = func_size + func_alignment;
- sp = std::align( func_alignment, func_size, sp, space);
- BOOST_ASSERT( nullptr != sp);
- // calculate remaining size
- std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
-#endif
- // placment new for control structure on coroutine stack
- cb_ = new ( sp) control_block( context::preallocated( sp, size, sctx),
- salloc, std::forward< Fn >( fn), preserve_fpu);
+pull_coroutine< T >::pull_coroutine( StackAllocator salloc, Fn && fn) :
+ cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
+ if ( ! cb_->valid() ) {
+ cb_->deallocate();
+ cb_ = nullptr;
+ }
}
template< typename T >
-pull_coroutine< T >::~pull_coroutine() {
+pull_coroutine< T >::~pull_coroutine() noexcept {
if ( nullptr != cb_) {
- cb_->~control_block();
+ cb_->deallocate();
}
}
template< typename T >
-pull_coroutine< T >::pull_coroutine( pull_coroutine && other) :
- cb_( other.cb_) {
+pull_coroutine< T >::pull_coroutine( pull_coroutine && other) noexcept :
+ cb_{ other.cb_ } {
other.cb_ = nullptr;
}
@@ -107,7 +91,7 @@ pull_coroutine< T >::operator!() const noexcept {
template< typename T >
T
-pull_coroutine< T >::get() {
+pull_coroutine< T >::get() noexcept {
return std::move( cb_->get() );
}
@@ -115,58 +99,44 @@ pull_coroutine< T >::get() {
// pull_coroutine< T & >
template< typename T >
-pull_coroutine< T & >::pull_coroutine( control_block * cb) :
- cb_( cb) {
+pull_coroutine< T & >::pull_coroutine( control_block * cb) noexcept :
+ cb_{ cb } {
}
template< typename T >
bool
-pull_coroutine< T & >::has_result_() const {
+pull_coroutine< T & >::has_result_() const noexcept {
return nullptr != cb_->other->t;
}
template< typename T >
-template< typename Fn >
-pull_coroutine< T & >::pull_coroutine( Fn && fn, bool preserve_fpu) :
- pull_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) {
+template< typename Fn,
+ typename
+>
+pull_coroutine< T & >::pull_coroutine( Fn && fn) :
+ pull_coroutine{ default_stack(), std::forward< Fn >( fn) } {
}
template< typename T >
template< typename StackAllocator, typename Fn >
-pull_coroutine< T & >::pull_coroutine( StackAllocator salloc, Fn && fn, bool preserve_fpu) :
- cb_( nullptr) {
- context::stack_context sctx( salloc.allocate() );
- // reserve space for control structure
-#if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
- void * sp = static_cast< char * >( sctx.sp) - sizeof( control_block);
- std::size_t size = sctx.size - sizeof( control_block);
-#else
- constexpr std::size_t func_alignment = 64; // alignof( control_block);
- constexpr std::size_t func_size = sizeof( control_block);
- // reserve space on stack
- void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
- // align sp pointer
- std::size_t space = func_size + func_alignment;
- sp = std::align( func_alignment, func_size, sp, space);
- BOOST_ASSERT( nullptr != sp);
- // calculate remaining size
- std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
-#endif
- // placment new for control structure on coroutine stack
- cb_ = new ( sp) control_block( context::preallocated( sp, size, sctx),
- salloc, std::forward< Fn >( fn), preserve_fpu);
+pull_coroutine< T & >::pull_coroutine( StackAllocator salloc, Fn && fn) :
+ cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
+ if ( ! cb_->valid() ) {
+ cb_->deallocate();
+ cb_ = nullptr;
+ }
}
template< typename T >
-pull_coroutine< T & >::~pull_coroutine() {
+pull_coroutine< T & >::~pull_coroutine() noexcept {
if ( nullptr != cb_) {
- cb_->~control_block();
+ cb_->deallocate();
}
}
template< typename T >
-pull_coroutine< T & >::pull_coroutine( pull_coroutine && other) :
- cb_( other.cb_) {
+pull_coroutine< T & >::pull_coroutine( pull_coroutine && other) noexcept :
+ cb_{ other.cb_ } {
other.cb_ = nullptr;
}
@@ -190,7 +160,7 @@ pull_coroutine< T & >::operator!() const noexcept {
template< typename T >
T &
-pull_coroutine< T & >::get() {
+pull_coroutine< T & >::get() noexcept {
return cb_->get();
}
@@ -198,50 +168,36 @@ pull_coroutine< T & >::get() {
// pull_coroutine< void >
inline
-pull_coroutine< void >::pull_coroutine( control_block * cb) :
- cb_( cb) {
+pull_coroutine< void >::pull_coroutine( control_block * cb) noexcept :
+ cb_{ cb } {
}
-template< typename Fn >
-pull_coroutine< void >::pull_coroutine( Fn && fn, bool preserve_fpu) :
- pull_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) {
+template< typename Fn,
+ typename
+>
+pull_coroutine< void >::pull_coroutine( Fn && fn) :
+ pull_coroutine{ default_stack(), std::forward< Fn >( fn) } {
}
template< typename StackAllocator, typename Fn >
-pull_coroutine< void >::pull_coroutine( StackAllocator salloc, Fn && fn, bool preserve_fpu) :
- cb_( nullptr) {
- context::stack_context sctx( salloc.allocate() );
- // reserve space for control structure
-#if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
- void * sp = static_cast< char * >( sctx.sp) - sizeof( control_block);
- std::size_t size = sctx.size - sizeof( control_block);
-#else
- constexpr std::size_t func_alignment = 64; // alignof( control_block);
- constexpr std::size_t func_size = sizeof( control_block);
- // reserve space on stack
- void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
- // align sp pointer
- std::size_t space = func_size + func_alignment;
- sp = std::align( func_alignment, func_size, sp, space);
- BOOST_ASSERT( nullptr != sp);
- // calculate remaining size
- std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
-#endif
- // placment new for control structure on coroutine stack
- cb_ = new ( sp) control_block( context::preallocated( sp, size, sctx),
- salloc, std::forward< Fn >( fn), preserve_fpu);
+pull_coroutine< void >::pull_coroutine( StackAllocator salloc, Fn && fn) :
+ cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
+ if ( ! cb_->valid() ) {
+ cb_->deallocate();
+ cb_ = nullptr;
+ }
}
inline
-pull_coroutine< void >::~pull_coroutine() {
+pull_coroutine< void >::~pull_coroutine() noexcept {
if ( nullptr != cb_) {
- cb_->~control_block();
+ cb_->deallocate();
}
}
inline
-pull_coroutine< void >::pull_coroutine( pull_coroutine && other) :
- cb_( other.cb_) {
+pull_coroutine< void >::pull_coroutine( pull_coroutine && other) noexcept :
+ cb_{ other.cb_ } {
other.cb_ = nullptr;
}
diff --git a/boost/coroutine2/detail/push_control_block.ipp b/boost/coroutine2/detail/push_control_block.ipp
deleted file mode 100644
index ce6776f600..0000000000
--- a/boost/coroutine2/detail/push_control_block.ipp
+++ /dev/null
@@ -1,289 +0,0 @@
-
-// Copyright Oliver Kowalke 2014.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
-#define BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
-
-#include <algorithm>
-#include <exception>
-#include <memory>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-
-#include <boost/context/execution_context.hpp>
-
-#include <boost/coroutine2/detail/config.hpp>
-#include <boost/coroutine2/detail/forced_unwind.hpp>
-#include <boost/coroutine2/detail/state.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines2 {
-namespace detail {
-
-// push_coroutine< T >
-
-template< typename T >
-template< typename StackAllocator, typename Fn >
-push_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
- Fn && fn_, bool preserve_fpu_) :
- other( nullptr),
- ctx( std::allocator_arg, palloc, salloc,
- [=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
- // create synthesized pull_coroutine< T >
- typename pull_coroutine< T >::control_block synthesized_cb( this, ctx);
- pull_coroutine< T > synthesized( & synthesized_cb);
- other = & synthesized_cb;
- // jump back to ctor
- T * t = reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) );
- // set transferred value
- synthesized_cb.set( t);
- try {
- // call coroutine-fn with synthesized pull_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- // set termination flags
- state |= static_cast< int >( state_t::complete);
- // jump back to ctx
- other->ctx( nullptr, preserve_fpu);
- BOOST_ASSERT_MSG( false, "push_coroutine is complete");
- }),
- preserve_fpu( preserve_fpu_),
- state( static_cast< int >( state_t::unwind) ),
- except() {
- // enter coroutine-fn in order to get other set
- ctx( nullptr, preserve_fpu);
-}
-
-template< typename T >
-push_coroutine< T >::control_block::control_block( typename pull_coroutine< T >::control_block * cb,
- boost::context::execution_context const& ctx_) :
- other( cb),
- ctx( ctx_),
- preserve_fpu( other->preserve_fpu),
- state( 0),
- except() {
-}
-
-template< typename T >
-push_coroutine< T >::control_block::~control_block() {
- if ( 0 == ( state & static_cast< int >( state_t::complete ) ) &&
- 0 != ( state & static_cast< int >( state_t::unwind) ) ) {
- // set early-exit flag
- state |= static_cast< int >( state_t::early_exit);
- ctx( nullptr, preserve_fpu);
- }
-}
-
-template< typename T >
-void
-push_coroutine< T >::control_block::resume( T const& t) {
- other->ctx = boost::context::execution_context::current();
- // pass an pointer to other context
- ctx( const_cast< T * >( & t), preserve_fpu);
- if ( except) {
- std::rethrow_exception( except);
- }
- // test early-exit-flag
- if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) {
- throw forced_unwind();
- }
-}
-
-template< typename T >
-void
-push_coroutine< T >::control_block::resume( T && t) {
- other->ctx = boost::context::execution_context::current();
- // pass an pointer to other context
- ctx( std::addressof( t), preserve_fpu);
- if ( except) {
- std::rethrow_exception( except);
- }
- // test early-exit-flag
- if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) {
- throw forced_unwind();
- }
-}
-
-template< typename T >
-bool
-push_coroutine< T >::control_block::valid() const noexcept {
- return 0 == ( state & static_cast< int >( state_t::complete) );
-}
-
-
-// push_coroutine< T & >
-
-template< typename T >
-template< typename StackAllocator, typename Fn >
-push_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
- Fn && fn_, bool preserve_fpu_) :
- other( nullptr),
- ctx( std::allocator_arg, palloc, salloc,
- [=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
- // create synthesized pull_coroutine< T >
- typename pull_coroutine< T & >::control_block synthesized_cb( this, ctx);
- pull_coroutine< T & > synthesized( & synthesized_cb);
- other = & synthesized_cb;
- // jump back to ctor
- T * t = reinterpret_cast< T * >( ctx( nullptr, preserve_fpu) );
- // set transferred value
- synthesized_cb.t = t;
- try {
- // call coroutine-fn with synthesized pull_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- // set termination flags
- state |= static_cast< int >( state_t::complete);
- // jump back to ctx
- other->ctx( nullptr, preserve_fpu);
- BOOST_ASSERT_MSG( false, "push_coroutine is complete");
- }),
- preserve_fpu( preserve_fpu_),
- state( static_cast< int >( state_t::unwind) ),
- except() {
- // enter coroutine-fn in order to get other set
- ctx( nullptr, preserve_fpu);
-}
-
-template< typename T >
-push_coroutine< T & >::control_block::control_block( typename pull_coroutine< T & >::control_block * cb,
- boost::context::execution_context const& ctx_) :
- other( cb),
- ctx( ctx_),
- preserve_fpu( other->preserve_fpu),
- state( 0),
- except() {
-}
-
-template< typename T >
-push_coroutine< T & >::control_block::~control_block() {
- if ( 0 == ( state & static_cast< int >( state_t::complete ) ) &&
- 0 != ( state & static_cast< int >( state_t::unwind) ) ) {
- // set early-exit flag
- state |= static_cast< int >( state_t::early_exit);
- ctx( nullptr, preserve_fpu);
- }
-}
-
-template< typename T >
-void
-push_coroutine< T & >::control_block::resume( T & t) {
- other->ctx = boost::context::execution_context::current();
- // pass an pointer to other context
- ctx( const_cast< typename std::remove_const< T >::type * >( std::addressof( t) ), preserve_fpu);
- if ( except) {
- std::rethrow_exception( except);
- }
- // test early-exit-flag
- if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) {
- throw forced_unwind();
- }
-}
-
-template< typename T >
-bool
-push_coroutine< T & >::control_block::valid() const noexcept {
- return 0 == ( state & static_cast< int >( state_t::complete) );
-}
-
-
-// push_coroutine< void >
-
-template< typename StackAllocator, typename Fn >
-push_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc, Fn && fn_, bool preserve_fpu_) :
- other( nullptr),
- ctx( std::allocator_arg, palloc, salloc,
- [=,fn=std::forward< Fn >( fn_),ctx=boost::context::execution_context::current()] (void *) mutable -> void {
- // create synthesized pull_coroutine< T >
- typename pull_coroutine< void >::control_block synthesized_cb( this, ctx);
- pull_coroutine< void > synthesized( & synthesized_cb);
- other = & synthesized_cb;
- // jump back to ctor
- ctx( nullptr, preserve_fpu);
- try {
- // call coroutine-fn with synthesized pull_coroutine as argument
- fn( synthesized);
- } catch ( forced_unwind const&) {
- // do nothing for unwinding exception
- } catch (...) {
- // store other exceptions in exception-pointer
- except = std::current_exception();
- }
- // set termination flags
- state |= static_cast< int >( state_t::complete);
- // jump back to ctx
- other->ctx( nullptr, preserve_fpu);
- BOOST_ASSERT_MSG( false, "push_coroutine is complete");
- }),
- preserve_fpu( preserve_fpu_),
- state( static_cast< int >( state_t::unwind) ),
- except() {
- // enter coroutine-fn in order to get other set
- ctx( nullptr, preserve_fpu);
-}
-
-inline
-push_coroutine< void >::control_block::control_block( pull_coroutine< void >::control_block * cb,
- boost::context::execution_context const& ctx_) :
- other( cb),
- ctx( ctx_),
- preserve_fpu( other->preserve_fpu),
- state( 0),
- except() {
-}
-
-inline
-push_coroutine< void >::control_block::~control_block() {
- if ( 0 == ( state & static_cast< int >( state_t::complete ) ) &&
- 0 != ( state & static_cast< int >( state_t::unwind) ) ) {
- // set early-exit flag
- state |= static_cast< int >( state_t::early_exit);
- ctx( nullptr, preserve_fpu);
- }
-}
-
-inline
-void
-push_coroutine< void >::control_block::resume() {
- other->ctx = boost::context::execution_context::current();
- ctx( nullptr, preserve_fpu);
- if ( except) {
- std::rethrow_exception( except);
- }
- // test early-exit-flag
- if ( 0 != ( ( other->state) & static_cast< int >( state_t::early_exit) ) ) {
- throw forced_unwind();
- }
-}
-
-inline
-bool
-push_coroutine< void >::control_block::valid() const noexcept {
- return 0 == ( state & static_cast< int >( state_t::complete) );
-}
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
diff --git a/boost/coroutine2/detail/push_control_block.hpp b/boost/coroutine2/detail/push_control_block_ecv1.hpp
index 03aa9125eb..29d49716a7 100644
--- a/boost/coroutine2/detail/push_control_block.hpp
+++ b/boost/coroutine2/detail/push_control_block_ecv1.hpp
@@ -7,11 +7,14 @@
#ifndef BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
#define BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
+#include <functional>
#include <exception>
#include <boost/config.hpp>
#include <boost/context/execution_context.hpp>
+#include <boost/coroutine2/detail/state.hpp>
+
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
@@ -22,22 +25,25 @@ namespace detail {
template< typename T >
struct push_coroutine< T >::control_block {
- typename pull_coroutine< T >::control_block * other;
boost::context::execution_context ctx;
- bool preserve_fpu;
- int state;
+ typename pull_coroutine< T >::control_block * other;
+ state_t state;
std::exception_ptr except;
+ static void destroy( control_block * cb) noexcept;
+
template< typename StackAllocator, typename Fn >
- control_block( context::preallocated, StackAllocator, Fn &&, bool);
+ control_block( context::preallocated, StackAllocator, Fn &&);
- explicit control_block( typename pull_coroutine< T >::control_block *, boost::context::execution_context const&);
+ control_block( typename pull_coroutine< T >::control_block *, boost::context::execution_context const&) noexcept;
- ~control_block();
+ ~control_block() noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
+ void deallocate() noexcept;
+
void resume( T const&);
void resume( T &&);
@@ -47,44 +53,50 @@ struct push_coroutine< T >::control_block {
template< typename T >
struct push_coroutine< T & >::control_block {
- typename pull_coroutine< T & >::control_block * other;
boost::context::execution_context ctx;
- bool preserve_fpu;
- int state;
+ typename pull_coroutine< T & >::control_block * other;
+ state_t state;
std::exception_ptr except;
+ static void destroy( control_block * cb) noexcept;
+
template< typename StackAllocator, typename Fn >
- control_block( context::preallocated, StackAllocator, Fn &&, bool);
+ control_block( context::preallocated, StackAllocator, Fn &&);
- explicit control_block( typename pull_coroutine< T & >::control_block *, boost::context::execution_context const&);
+ control_block( typename pull_coroutine< T & >::control_block *, boost::context::execution_context const&) noexcept;
- ~control_block();
+ ~control_block() noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
+ void deallocate() noexcept;
+
void resume( T &);
bool valid() const noexcept;
};
struct push_coroutine< void >::control_block {
- pull_coroutine< void >::control_block * other;
boost::context::execution_context ctx;
- bool preserve_fpu;
- int state;
+ pull_coroutine< void >::control_block * other;
+ state_t state;
std::exception_ptr except;
+ static void destroy( control_block * cb) noexcept;
+
template< typename StackAllocator, typename Fn >
- control_block( context::preallocated, StackAllocator, Fn &&, bool);
+ control_block( context::preallocated, StackAllocator, Fn &&);
- explicit control_block( pull_coroutine< void >::control_block *, boost::context::execution_context const&);
+ control_block( pull_coroutine< void >::control_block *, boost::context::execution_context const&) noexcept;
- ~control_block();
+ ~control_block() noexcept;
control_block( control_block &) = delete;
control_block & operator=( control_block &) = delete;
+ void deallocate() noexcept;
+
void resume();
bool valid() const noexcept;
diff --git a/boost/coroutine2/detail/push_control_block_ecv1.ipp b/boost/coroutine2/detail/push_control_block_ecv1.ipp
new file mode 100644
index 0000000000..f9119fd771
--- /dev/null
+++ b/boost/coroutine2/detail/push_control_block_ecv1.ipp
@@ -0,0 +1,418 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
+#define BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
+
+#include <algorithm>
+#include <exception>
+#include <functional>
+#include <memory>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/context/execution_context.hpp>
+
+#include <boost/coroutine2/detail/config.hpp>
+#include <boost/coroutine2/detail/decay_copy.hpp>
+#include <boost/coroutine2/detail/forced_unwind.hpp>
+#include <boost/coroutine2/detail/state.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines2 {
+namespace detail {
+
+// push_coroutine< T >
+
+template< typename T >
+void
+push_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
+ boost::context::execution_context ctx = cb->ctx;
+ // destroy control structure
+ cb->~control_block();
+}
+
+template< typename T >
+template< typename StackAllocator, typename Fn >
+push_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
+ Fn && fn) :
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ ctx{ std::allocator_arg, palloc, salloc,
+ std::move(
+ std::bind(
+ [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx, void * vp) mutable noexcept {
+ // create synthesized pull_coroutine< T >
+ typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
+ pull_coroutine< T > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ try {
+ // jump back to ctor
+ T * t = static_cast< T * >( ctx() );
+ // set transferred value
+ synthesized_cb.set( t);
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized pull_coroutine as argument
+ fn( synthesized);
+ } catch ( forced_unwind const&) {
+ // do nothing for unwinding exception
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ other->ctx();
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ },
+ std::forward< Fn >( fn),
+ boost::context::execution_context::current(),
+ std::placeholders::_1))},
+#else
+ ctx{ std::allocator_arg, palloc, salloc,
+ [this,fn_=decay_copy( std::forward< Fn >( fn) ),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
+ // create synthesized pull_coroutine< T >
+ typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
+ pull_coroutine< T > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ try {
+ // jump back to ctor
+ T * t = static_cast< T * >( ctx() );
+ // set transferred value
+ synthesized_cb.set( t);
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized pull_coroutine as argument
+ fn( synthesized);
+ } catch ( forced_unwind const&) {
+ // do nothing for unwinding exception
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ other->ctx();
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }},
+#endif
+ other{ nullptr },
+ state{ state_t::unwind },
+ except{} {
+ // enter coroutine-fn in order to get other set
+ ctx();
+}
+
+template< typename T >
+push_coroutine< T >::control_block::control_block( typename pull_coroutine< T >::control_block * cb,
+ boost::context::execution_context const& ctx_) noexcept :
+ ctx{ ctx_ },
+ other{ cb },
+ state{ state_t::none },
+ except{} {
+}
+
+template< typename T >
+push_coroutine< T >::control_block::~control_block() {
+ if ( state_t::none == ( state & state_t::complete) &&
+ state_t::none != ( state & state_t::unwind) ) {
+ // unwind coroutine stack
+ ctx( context::exec_ontop_arg, unwind_coroutine);
+ }
+}
+
+template< typename T >
+void
+push_coroutine< T >::control_block::deallocate() noexcept {
+ if ( state_t::none != ( state & state_t::unwind) ) {
+ destroy( this);
+ }
+}
+
+template< typename T >
+void
+push_coroutine< T >::control_block::resume( T const& t) {
+ other->ctx = boost::context::execution_context::current();
+ // pass an pointer to other context
+ ctx( const_cast< T * >( & t) );
+ if ( except) {
+ std::rethrow_exception( except);
+ }
+}
+
+template< typename T >
+void
+push_coroutine< T >::control_block::resume( T && t) {
+ other->ctx = boost::context::execution_context::current();
+ // pass an pointer to other context
+ ctx( std::addressof( t) );
+ if ( except) {
+ std::rethrow_exception( except);
+ }
+}
+
+template< typename T >
+bool
+push_coroutine< T >::control_block::valid() const noexcept {
+ return state_t::none == ( state & state_t::complete );
+}
+
+
+// push_coroutine< T & >
+
+template< typename T >
+void
+push_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
+ boost::context::execution_context ctx = cb->ctx;
+ // destroy control structure
+ cb->~control_block();
+}
+
+template< typename T >
+template< typename StackAllocator, typename Fn >
+push_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
+ Fn && fn) :
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ ctx{ std::allocator_arg, palloc, salloc,
+ std::move(
+ std::bind(
+ [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx, void * vp) mutable noexcept {
+ // create synthesized pull_coroutine< T >
+ typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
+ pull_coroutine< T & > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ try {
+ // jump back to ctor
+ T * t = static_cast< T * >( ctx() );
+ // set transferred value
+ synthesized_cb.t = t;
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized pull_coroutine as argument
+ fn( synthesized);
+ } catch ( forced_unwind const&) {
+ // do nothing for unwinding exception
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ other->ctx();
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ },
+ std::forward< Fn >( fn),
+ boost::context::execution_context::current(),
+ std::placeholders::_1))},
+#else
+ ctx{ std::allocator_arg, palloc, salloc,
+ [this,fn_=decay_copy( std::forward< Fn >( fn) ),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
+ // create synthesized pull_coroutine< T >
+ typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
+ pull_coroutine< T & > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ try {
+ // jump back to ctor
+ T * t = static_cast< T * >( ctx() );
+ // set transferred value
+ synthesized_cb.t = t;
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized pull_coroutine as argument
+ fn( synthesized);
+ } catch ( forced_unwind const&) {
+ // do nothing for unwinding exception
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ other->ctx();
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }},
+#endif
+ other{ nullptr },
+ state{ state_t::unwind },
+ except{} {
+ // enter coroutine-fn in order to get other set
+ ctx();
+}
+
+template< typename T >
+push_coroutine< T & >::control_block::control_block( typename pull_coroutine< T & >::control_block * cb,
+ boost::context::execution_context const& ctx_) noexcept :
+ ctx{ ctx_ },
+ other{ cb },
+ state{ state_t::none },
+ except{} {
+}
+
+template< typename T >
+push_coroutine< T & >::control_block::~control_block() {
+ if ( state_t::none == ( state & state_t::complete) &&
+ state_t::none != ( state & state_t::unwind) ) {
+ // unwind coroutine stack
+ ctx( context::exec_ontop_arg, unwind_coroutine);
+ }
+}
+
+template< typename T >
+void
+push_coroutine< T & >::control_block::deallocate() noexcept {
+ if ( state_t::none != ( state & state_t::unwind) ) {
+ destroy( this);
+ }
+}
+
+template< typename T >
+void
+push_coroutine< T & >::control_block::resume( T & t) {
+ other->ctx = boost::context::execution_context::current();
+ // pass an pointer to other context
+ ctx( const_cast< typename std::remove_const< T >::type * >( std::addressof( t) ) );
+ if ( except) {
+ std::rethrow_exception( except);
+ }
+}
+
+template< typename T >
+bool
+push_coroutine< T & >::control_block::valid() const noexcept {
+ return state_t::none == ( state & state_t::complete );
+}
+
+
+// push_coroutine< void >
+
+inline
+void
+push_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
+ boost::context::execution_context ctx = cb->ctx;
+ // destroy control structure
+ cb->~control_block();
+}
+
+template< typename StackAllocator, typename Fn >
+push_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc, Fn && fn) :
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ ctx{ std::allocator_arg, palloc, salloc,
+ std::move(
+ std::bind(
+ [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context & ctx,
+ void * vp) mutable noexcept {
+ // create synthesized pull_coroutine< T >
+ typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx };
+ pull_coroutine< void > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ try {
+ // jump back to ctor
+ ctx();
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized pull_coroutine as argument
+ fn( synthesized);
+ } catch ( forced_unwind const&) {
+ // do nothing for unwinding exception
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ other->ctx();
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ },
+ std::forward< Fn >( fn),
+ boost::context::execution_context::current(),
+ std::placeholders::_1))},
+#else
+ ctx{ std::allocator_arg, palloc, salloc,
+ [this,fn_=decay_copy( std::forward< Fn >( fn) ),ctx=boost::context::execution_context::current()] (void *) mutable noexcept {
+ // create synthesized pull_coroutine< T >
+ typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx };
+ pull_coroutine< void > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ try {
+ // jump back to ctor
+ ctx();
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized pull_coroutine as argument
+ fn( synthesized);
+ } catch ( forced_unwind const&) {
+ // do nothing for unwinding exception
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ other->ctx();
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }},
+#endif
+ other{ nullptr },
+ state{ state_t::unwind },
+ except{} {
+ // enter coroutine-fn in order to get other set
+ ctx();
+}
+
+inline
+push_coroutine< void >::control_block::control_block( pull_coroutine< void >::control_block * cb,
+ boost::context::execution_context const& ctx_) noexcept :
+ ctx{ ctx_ },
+ other{ cb },
+ state{ state_t::none },
+ except{} {
+}
+
+inline
+push_coroutine< void >::control_block::~control_block() {
+ if ( state_t::none == ( state & state_t::complete) &&
+ state_t::none != ( state & state_t::unwind) ) {
+ // unwind coroutine stack
+ ctx( context::exec_ontop_arg, unwind_coroutine);
+ }
+}
+
+inline
+void
+push_coroutine< void >::control_block::deallocate() noexcept {
+ if ( state_t::none != ( state & state_t::unwind) ) {
+ destroy( this);
+ }
+}
+
+inline
+void
+push_coroutine< void >::control_block::resume() {
+ other->ctx = boost::context::execution_context::current();
+ ctx();
+ if ( except) {
+ std::rethrow_exception( except);
+ }
+}
+
+inline
+bool
+push_coroutine< void >::control_block::valid() const noexcept {
+ return state_t::none == ( state & state_t::complete );
+}
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
diff --git a/boost/coroutine2/detail/push_control_block_ecv2.hpp b/boost/coroutine2/detail/push_control_block_ecv2.hpp
new file mode 100644
index 0000000000..feb5e4a61c
--- /dev/null
+++ b/boost/coroutine2/detail/push_control_block_ecv2.hpp
@@ -0,0 +1,104 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
+#define BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
+
+#include <exception>
+
+#include <boost/config.hpp>
+#include <boost/context/execution_context.hpp>
+
+#include <boost/coroutine2/detail/state.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines2 {
+namespace detail {
+
+template< typename T >
+struct push_coroutine< T >::control_block {
+ boost::context::execution_context< T * > ctx;
+ typename pull_coroutine< T >::control_block * other;
+ state_t state;
+ std::exception_ptr except;
+
+ static void destroy( control_block * cb) noexcept;
+
+ template< typename StackAllocator, typename Fn >
+ control_block( context::preallocated, StackAllocator, Fn &&);
+
+ control_block( typename pull_coroutine< T >::control_block *, boost::context::execution_context< T * > &) noexcept;
+
+ control_block( control_block &) = delete;
+ control_block & operator=( control_block &) = delete;
+
+ void deallocate() noexcept;
+
+ void resume( T const&);
+
+ void resume( T &&);
+
+ bool valid() const noexcept;
+};
+
+template< typename T >
+struct push_coroutine< T & >::control_block {
+ boost::context::execution_context< T * > ctx;
+ typename pull_coroutine< T & >::control_block * other;
+ state_t state;
+ std::exception_ptr except;
+
+ static void destroy( control_block * cb) noexcept;
+
+ template< typename StackAllocator, typename Fn >
+ control_block( context::preallocated, StackAllocator, Fn &&);
+
+ control_block( typename pull_coroutine< T & >::control_block *, boost::context::execution_context< T * > &) noexcept;
+
+ control_block( control_block &) = delete;
+ control_block & operator=( control_block &) = delete;
+
+ void deallocate() noexcept;
+
+ void resume( T &);
+
+ bool valid() const noexcept;
+};
+
+struct push_coroutine< void >::control_block {
+ boost::context::execution_context< void > ctx;
+ pull_coroutine< void >::control_block * other;
+ state_t state;
+ std::exception_ptr except;
+
+ static void destroy( control_block * cb) noexcept;
+
+ template< typename StackAllocator, typename Fn >
+ control_block( context::preallocated, StackAllocator, Fn &&);
+
+ control_block( pull_coroutine< void >::control_block *, boost::context::execution_context< void > &) noexcept;
+
+ control_block( control_block &) = delete;
+ control_block & operator=( control_block &) = delete;
+
+ void deallocate() noexcept;
+
+ void resume();
+
+ bool valid() const noexcept;
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_HPP
diff --git a/boost/coroutine2/detail/push_control_block_ecv2.ipp b/boost/coroutine2/detail/push_control_block_ecv2.ipp
new file mode 100644
index 0000000000..bfdee06a18
--- /dev/null
+++ b/boost/coroutine2/detail/push_control_block_ecv2.ipp
@@ -0,0 +1,377 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
+#define BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
+
+#include <algorithm>
+#include <exception>
+#include <memory>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/context/execution_context.hpp>
+
+#include <boost/coroutine2/detail/config.hpp>
+#include <boost/coroutine2/detail/forced_unwind.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines2 {
+namespace detail {
+
+// push_coroutine< T >
+
+template< typename T >
+void
+push_coroutine< T >::control_block::destroy( control_block * cb) noexcept {
+ boost::context::execution_context< T * > ctx = std::move( cb->ctx);
+ // destroy control structure
+ cb->~control_block();
+ // destroy coroutine's stack
+ ctx( nullptr);
+}
+
+template< typename T >
+template< typename StackAllocator, typename Fn >
+push_coroutine< T >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
+ Fn && fn) :
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ ctx{ std::allocator_arg, palloc, salloc,
+ std::move(
+ std::bind(
+ [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< T * > ctx, T * data) mutable {
+ // create synthesized pull_coroutine< T >
+ typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
+ pull_coroutine< T > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ // set transferred value
+ synthesized_cb.set( data);
+ try {
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized pull_coroutine as argument
+ fn( synthesized);
+ } catch ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ auto result = other->ctx( nullptr);
+ other->ctx = std::move( std::get< 0 >( result) );
+ return std::move( other->ctx);
+ },
+ std::forward< Fn >( fn),
+ std::placeholders::_1,
+ std::placeholders::_2))},
+#else
+ ctx{ std::allocator_arg, palloc, salloc,
+ [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< T * > ctx, T * data) mutable {
+ // create synthesized pull_coroutine< T >
+ typename pull_coroutine< T >::control_block synthesized_cb{ this, ctx };
+ pull_coroutine< T > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ // set transferred value
+ synthesized_cb.set( data);
+ try {
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized pull_coroutine as argument
+ fn( synthesized);
+ } catch ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ auto result = other->ctx( nullptr);
+ other->ctx = std::move( std::get< 0 >( result) );
+ return std::move( other->ctx);
+ }},
+#endif
+ other{ nullptr },
+ state{ state_t::unwind },
+ except{} {
+}
+
+template< typename T >
+push_coroutine< T >::control_block::control_block( typename pull_coroutine< T >::control_block * cb,
+ boost::context::execution_context< T * > & ctx_) noexcept :
+ ctx{ std::move( ctx_) },
+ other{ cb },
+ state{ state_t::none },
+ except{} {
+}
+
+template< typename T >
+void
+push_coroutine< T >::control_block::deallocate() noexcept {
+ if ( state_t::none != ( state & state_t::unwind) ) {
+ destroy( this);
+ }
+}
+
+template< typename T >
+void
+push_coroutine< T >::control_block::resume( T const& data) {
+ // pass an pointer to other context
+ auto result = ctx( const_cast< T * >( & data) );
+ ctx = std::move( std::get< 0 >( result) );
+ if ( except) {
+ std::rethrow_exception( except);
+ }
+}
+
+template< typename T >
+void
+push_coroutine< T >::control_block::resume( T && data) {
+ // pass an pointer to other context
+ auto result = ctx( std::addressof( data) );
+ ctx = std::move( std::get< 0 >( result) );
+ if ( except) {
+ std::rethrow_exception( except);
+ }
+}
+
+template< typename T >
+bool
+push_coroutine< T >::control_block::valid() const noexcept {
+ return state_t::none == ( state & state_t::complete );
+}
+
+
+// push_coroutine< T & >
+
+template< typename T >
+void
+push_coroutine< T & >::control_block::destroy( control_block * cb) noexcept {
+ boost::context::execution_context< T * > ctx = std::move( cb->ctx);
+ // destroy control structure
+ cb->~control_block();
+ // destroy coroutine's stack
+ ctx( nullptr);
+}
+
+template< typename T >
+template< typename StackAllocator, typename Fn >
+push_coroutine< T & >::control_block::control_block( context::preallocated palloc, StackAllocator salloc,
+ Fn && fn) :
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ ctx{ std::allocator_arg, palloc, salloc,
+ std::move(
+ std::bind(
+ [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< T * > ctx, T * data) mutable {
+ // create synthesized pull_coroutine< T & >
+ typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
+ pull_coroutine< T & > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ // set transferred value
+ synthesized_cb.t = data;
+ try {
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized pull_coroutine as argument
+ fn( synthesized);
+ } catch ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ auto result = other->ctx( nullptr);
+ other->ctx = std::move( std::get< 0 >( result) );
+ return std::move( other->ctx);
+ },
+ std::forward< Fn >( fn),
+ std::placeholders::_1,
+ std::placeholders::_2))},
+#else
+ ctx{ std::allocator_arg, palloc, salloc,
+ [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< T * > ctx, T * data) mutable {
+ // create synthesized pull_coroutine< T & >
+ typename pull_coroutine< T & >::control_block synthesized_cb{ this, ctx };
+ pull_coroutine< T & > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ // set transferred value
+ synthesized_cb.t = data;
+ try {
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized pull_coroutine as argument
+ fn( synthesized);
+ } catch ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ auto result = other->ctx( nullptr);
+ other->ctx = std::move( std::get< 0 >( result) );
+ return std::move( other->ctx);
+ }},
+#endif
+ other{ nullptr },
+ state{ state_t::unwind },
+ except{} {
+}
+
+template< typename T >
+push_coroutine< T & >::control_block::control_block( typename pull_coroutine< T & >::control_block * cb,
+ boost::context::execution_context< T * > & ctx_) noexcept :
+ ctx{ std::move( ctx_) },
+ other{ cb },
+ state{ state_t::none },
+ except{} {
+}
+
+template< typename T >
+void
+push_coroutine< T & >::control_block::deallocate() noexcept {
+ if ( state_t::none != ( state & state_t::unwind) ) {
+ destroy( this);
+ }
+}
+
+template< typename T >
+void
+push_coroutine< T & >::control_block::resume( T & t) {
+ // pass an pointer to other context
+ auto result = ctx( const_cast< typename std::remove_const< T >::type * >( std::addressof( t) ) );
+ ctx = std::move( std::get< 0 >( result) );
+ if ( except) {
+ std::rethrow_exception( except);
+ }
+}
+
+template< typename T >
+bool
+push_coroutine< T & >::control_block::valid() const noexcept {
+ return state_t::none == ( state & state_t::complete );
+}
+
+
+// push_coroutine< void >
+
+inline
+void
+push_coroutine< void >::control_block::destroy( control_block * cb) noexcept {
+ boost::context::execution_context< void > ctx = std::move( cb->ctx);
+ // destroy control structure
+ cb->~control_block();
+ // destroy coroutine's stack
+ ctx();
+}
+
+template< typename StackAllocator, typename Fn >
+push_coroutine< void >::control_block::control_block( context::preallocated palloc, StackAllocator salloc, Fn && fn) :
+#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
+ ctx{ std::allocator_arg, palloc, salloc,
+ std::move(
+ std::bind(
+ [this]( typename std::decay< Fn >::type & fn_, boost::context::execution_context< void > ctx) mutable {
+ // create synthesized pull_coroutine< void >
+ typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx };
+ pull_coroutine< void > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ try {
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized pull_coroutine as argument
+ fn( synthesized);
+ } catch ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ other->ctx = other->ctx();
+ return std::move( other->ctx);
+ },
+ std::forward< Fn >( fn),
+ std::placeholders::_1))},
+#else
+ ctx{ std::allocator_arg, palloc, salloc,
+ [this,fn_=std::forward< Fn >( fn)]( boost::context::execution_context< void > ctx) mutable {
+ // create synthesized pull_coroutine< void >
+ typename pull_coroutine< void >::control_block synthesized_cb{ this, ctx};
+ pull_coroutine< void > synthesized{ & synthesized_cb };
+ other = & synthesized_cb;
+ try {
+ auto fn = std::move( fn_);
+ // call coroutine-fn with synthesized pull_coroutine as argument
+ fn( synthesized);
+ } catch ( boost::context::detail::forced_unwind const&) {
+ throw;
+ } catch (...) {
+ // store other exceptions in exception-pointer
+ except = std::current_exception();
+ }
+ // set termination flags
+ state |= state_t::complete;
+ // jump back to ctx
+ other->ctx = other->ctx();
+ return std::move( other->ctx);
+ }},
+#endif
+ other{ nullptr },
+ state{ state_t::unwind },
+ except{} {
+}
+
+inline
+push_coroutine< void >::control_block::control_block( pull_coroutine< void >::control_block * cb,
+ boost::context::execution_context< void > & ctx_) noexcept :
+ ctx{ std::move( ctx_) },
+ other{ cb },
+ state{ state_t::none },
+ except{} {
+}
+
+inline
+void
+push_coroutine< void >::control_block::deallocate() noexcept {
+ if ( state_t::none != ( state & state_t::unwind) ) {
+ destroy( this);
+ }
+}
+
+inline
+void
+push_coroutine< void >::control_block::resume() {
+ ctx = ctx();
+ if ( except) {
+ std::rethrow_exception( except);
+ }
+}
+
+inline
+bool
+push_coroutine< void >::control_block::valid() const noexcept {
+ return state_t::none == ( state & state_t::complete );
+}
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES2_DETAIL_PUSH_CONTROL_BLOCK_IPP
diff --git a/boost/coroutine2/detail/push_coroutine.hpp b/boost/coroutine2/detail/push_coroutine.hpp
index 1a2d01f67e..5d9d092b65 100644
--- a/boost/coroutine2/detail/push_coroutine.hpp
+++ b/boost/coroutine2/detail/push_coroutine.hpp
@@ -12,9 +12,9 @@
#include <boost/assert.hpp>
#include <boost/config.hpp>
-#include <boost/context/execution_context.hpp>
#include <boost/coroutine2/detail/config.hpp>
+#include <boost/coroutine2/detail/disable_overload.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
@@ -34,27 +34,28 @@ private:
control_block * cb_;
- explicit push_coroutine( control_block *);
+ explicit push_coroutine( control_block *) noexcept;
public:
- template< typename Fn >
- explicit push_coroutine( Fn &&, bool = false);
+ template< typename Fn,
+ typename = detail::disable_overload< push_coroutine, Fn >
+ >
+ explicit push_coroutine( Fn &&);
template< typename StackAllocator, typename Fn >
- explicit push_coroutine( StackAllocator, Fn &&, bool = false);
+ push_coroutine( StackAllocator, Fn &&);
- ~push_coroutine();
+ ~push_coroutine() noexcept;
push_coroutine( push_coroutine const&) = delete;
push_coroutine & operator=( push_coroutine const&) = delete;
- push_coroutine( push_coroutine &&);
+ push_coroutine( push_coroutine &&) noexcept;
- push_coroutine & operator=( push_coroutine && other) {
- if ( this != & other) {
- cb_ = other.cb_;
- other.cb_ = nullptr;
- }
+ push_coroutine & operator=( push_coroutine && other) noexcept {
+ if ( this == & other) return * this;
+ cb_ = other.cb_;
+ other.cb_ = nullptr;
return * this;
}
@@ -68,36 +69,36 @@ public:
class iterator : public std::iterator< std::output_iterator_tag, void, void, void, void > {
private:
- push_coroutine< T > * c_;
+ push_coroutine< T > * c_{ nullptr };
public:
- iterator() :
- c_( nullptr) {
- }
+ constexpr iterator() noexcept = default;
- explicit iterator( push_coroutine< T > * c) :
- c_( c) {
+ explicit iterator( push_coroutine< T > * c) noexcept :
+ c_{ c } {
}
iterator & operator=( T t) {
BOOST_ASSERT( c_);
- if ( ! ( * c_)( t) ) c_ = 0;
+ if ( ! ( * c_)( t) ) {
+ c_ = nullptr;
+ }
return * this;
}
- bool operator==( iterator const& other) const {
+ bool operator==( iterator const& other) const noexcept {
return other.c_ == c_;
}
- bool operator!=( iterator const& other) const {
+ bool operator!=( iterator const& other) const noexcept {
return other.c_ != c_;
}
- iterator & operator*() {
+ iterator & operator*() noexcept {
return * this;
}
- iterator & operator++() {
+ iterator & operator++() noexcept {
return * this;
}
};
@@ -113,27 +114,28 @@ private:
control_block * cb_;
- explicit push_coroutine( control_block *);
+ explicit push_coroutine( control_block *) noexcept;
public:
- template< typename Fn >
- explicit push_coroutine( Fn &&, bool = false);
+ template< typename Fn,
+ typename = detail::disable_overload< push_coroutine, Fn >
+ >
+ explicit push_coroutine( Fn &&);
template< typename StackAllocator, typename Fn >
- explicit push_coroutine( StackAllocator, Fn &&, bool = false);
+ push_coroutine( StackAllocator, Fn &&);
- ~push_coroutine();
+ ~push_coroutine() noexcept;
push_coroutine( push_coroutine const&) = delete;
push_coroutine & operator=( push_coroutine const&) = delete;
- push_coroutine( push_coroutine &&);
+ push_coroutine( push_coroutine &&) noexcept;
- push_coroutine & operator=( push_coroutine && other) {
- if ( this != & other) {
- cb_ = other.cb_;
- other.cb_ = nullptr;
- }
+ push_coroutine & operator=( push_coroutine && other) noexcept {
+ if ( this == & other) return * this;
+ cb_ = other.cb_;
+ other.cb_ = nullptr;
return * this;
}
@@ -145,36 +147,36 @@ public:
class iterator : public std::iterator< std::output_iterator_tag, void, void, void, void > {
private:
- push_coroutine< T & > * c_;
+ push_coroutine< T & > * c_{ nullptr };
public:
- iterator() :
- c_( nullptr) {
- }
+ constexpr iterator() noexcept = default;
- explicit iterator( push_coroutine< T & > * c) :
- c_( c) {
+ explicit iterator( push_coroutine< T & > * c) noexcept :
+ c_{ c } {
}
iterator & operator=( T & t) {
BOOST_ASSERT( c_);
- if ( ! ( * c_)( t) ) c_ = 0;
+ if ( ! ( * c_)( t) ) {
+ c_ = nullptr;
+ }
return * this;
}
- bool operator==( iterator const& other) const {
+ bool operator==( iterator const& other) const noexcept {
return other.c_ == c_;
}
- bool operator!=( iterator const& other) const {
+ bool operator!=( iterator const& other) const noexcept {
return other.c_ != c_;
}
- iterator & operator*() {
+ iterator & operator*() noexcept {
return * this;
}
- iterator & operator++() {
+ iterator & operator++() noexcept {
return * this;
}
};
@@ -190,27 +192,28 @@ private:
control_block * cb_;
- explicit push_coroutine( control_block *);
+ explicit push_coroutine( control_block *) noexcept;
public:
- template< typename Fn >
- explicit push_coroutine( Fn &&, bool = false);
+ template< typename Fn,
+ typename = detail::disable_overload< push_coroutine, Fn >
+ >
+ explicit push_coroutine( Fn &&);
template< typename StackAllocator, typename Fn >
- explicit push_coroutine( StackAllocator, Fn &&, bool = false);
+ push_coroutine( StackAllocator, Fn &&);
- ~push_coroutine();
+ ~push_coroutine() noexcept;
push_coroutine( push_coroutine const&) = delete;
push_coroutine & operator=( push_coroutine const&) = delete;
- push_coroutine( push_coroutine &&);
+ push_coroutine( push_coroutine &&) noexcept;
- push_coroutine & operator=( push_coroutine && other) {
- if ( this != & other) {
- cb_ = other.cb_;
- other.cb_ = nullptr;
- }
+ push_coroutine & operator=( push_coroutine && other) noexcept {
+ if ( this == & other) return * this;
+ cb_ = other.cb_;
+ other.cb_ = nullptr;
return * this;
}
diff --git a/boost/coroutine2/detail/push_coroutine.ipp b/boost/coroutine2/detail/push_coroutine.ipp
index 5f4817802a..304e07729e 100644
--- a/boost/coroutine2/detail/push_coroutine.ipp
+++ b/boost/coroutine2/detail/push_coroutine.ipp
@@ -7,16 +7,14 @@
#ifndef BOOST_COROUTINES2_DETAIL_PUSH_COROUTINE_IPP
#define BOOST_COROUTINES2_DETAIL_PUSH_COROUTINE_IPP
-#include <memory>
#include <utility>
#include <boost/assert.hpp>
#include <boost/config.hpp>
-#include <boost/context/execution_context.hpp>
-#include <boost/context/stack_context.hpp>
-
#include <boost/coroutine2/detail/config.hpp>
+#include <boost/coroutine2/detail/create_control_block.ipp>
+#include <boost/coroutine2/detail/disable_overload.hpp>
#include <boost/coroutine2/fixedsize_stack.hpp>
#include <boost/coroutine2/segmented_stack.hpp>
@@ -31,52 +29,34 @@ namespace detail {
// push_coroutine< T >
template< typename T >
-push_coroutine< T >::push_coroutine( control_block * cb) :
- cb_( cb) {
+push_coroutine< T >::push_coroutine( control_block * cb) noexcept :
+ cb_{ cb } {
}
template< typename T >
-template< typename Fn >
-push_coroutine< T >::push_coroutine( Fn && fn, bool preserve_fpu) :
- push_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) {
+template< typename Fn,
+ typename
+>
+push_coroutine< T >::push_coroutine( Fn && fn) :
+ push_coroutine{ default_stack(), std::forward< Fn >( fn) } {
}
template< typename T >
template< typename StackAllocator, typename Fn >
-push_coroutine< T >::push_coroutine( StackAllocator salloc, Fn && fn, bool preserve_fpu) :
- cb_( nullptr) {
- context::stack_context sctx( salloc.allocate() );
- // reserve space for control structure
-#if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
- void * sp = static_cast< char * >( sctx.sp) - sizeof( control_block);
- std::size_t size = sctx.size - sizeof( control_block);
-#else
- constexpr std::size_t func_alignment = 64; // alignof( control_block);
- constexpr std::size_t func_size = sizeof( control_block);
- // reserve space on stack
- void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
- // align sp pointer
- std::size_t space = func_size + func_alignment;
- sp = std::align( func_alignment, func_size, sp, space);
- BOOST_ASSERT( nullptr != sp);
- // calculate remaining size
- std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
-#endif
- // placment new for control structure on coroutine stack
- cb_= new ( sp) control_block( context::preallocated( sp, size, sctx),
- salloc, std::forward< Fn >( fn), preserve_fpu);
+push_coroutine< T >::push_coroutine( StackAllocator salloc, Fn && fn) :
+ cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
}
template< typename T >
-push_coroutine< T >::~push_coroutine() {
+push_coroutine< T >::~push_coroutine() noexcept {
if ( nullptr != cb_) {
- cb_->~control_block();
+ cb_->deallocate();
}
}
template< typename T >
-push_coroutine< T >::push_coroutine( push_coroutine && other) :
- cb_( other.cb_) {
+push_coroutine< T >::push_coroutine( push_coroutine && other) noexcept :
+ cb_{ other.cb_ } {
other.cb_ = nullptr;
}
@@ -109,52 +89,34 @@ push_coroutine< T >::operator!() const noexcept {
// push_coroutine< T & >
template< typename T >
-push_coroutine< T & >::push_coroutine( control_block * cb) :
- cb_( cb) {
+push_coroutine< T & >::push_coroutine( control_block * cb) noexcept :
+ cb_{ cb } {
}
template< typename T >
-template< typename Fn >
-push_coroutine< T & >::push_coroutine( Fn && fn, bool preserve_fpu) :
- push_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) {
+template< typename Fn,
+ typename
+>
+push_coroutine< T & >::push_coroutine( Fn && fn) :
+ push_coroutine{ default_stack(), std::forward< Fn >( fn) } {
}
template< typename T >
template< typename StackAllocator, typename Fn >
-push_coroutine< T & >::push_coroutine( StackAllocator salloc, Fn && fn, bool preserve_fpu) :
- cb_( nullptr) {
- context::stack_context sctx( salloc.allocate() );
- // reserve space for control structure
-#if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
- void * sp = static_cast< char * >( sctx.sp) - sizeof( control_block);
- std::size_t size = sctx.size - sizeof( control_block);
-#else
- constexpr std::size_t func_alignment = 64; // alignof( control_block);
- constexpr std::size_t func_size = sizeof( control_block);
- // reserve space on stack
- void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
- // align sp pointer
- std::size_t space = func_size + func_alignment;
- sp = std::align( func_alignment, func_size, sp, space);
- BOOST_ASSERT( nullptr != sp);
- // calculate remaining size
- std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
-#endif
- // placment new for control structure on coroutine stack
- cb_ = new ( sp) control_block( context::preallocated( sp, size, sctx),
- salloc, std::forward< Fn >( fn), preserve_fpu);
+push_coroutine< T & >::push_coroutine( StackAllocator salloc, Fn && fn) :
+ cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
}
template< typename T >
-push_coroutine< T & >::~push_coroutine() {
+push_coroutine< T & >::~push_coroutine() noexcept {
if ( nullptr != cb_) {
- cb_->~control_block();
+ cb_->deallocate();
}
}
template< typename T >
-push_coroutine< T & >::push_coroutine( push_coroutine && other) :
- cb_( other.cb_) {
+push_coroutine< T & >::push_coroutine( push_coroutine && other) noexcept :
+ cb_{ other.cb_ } {
other.cb_ = nullptr;
}
@@ -180,50 +142,32 @@ push_coroutine< T & >::operator!() const noexcept {
// push_coroutine< void >
inline
-push_coroutine< void >::push_coroutine( control_block * cb) :
- cb_( cb) {
+push_coroutine< void >::push_coroutine( control_block * cb) noexcept :
+ cb_{ cb } {
}
-template< typename Fn >
-push_coroutine< void >::push_coroutine( Fn && fn, bool preserve_fpu) :
- push_coroutine( default_stack(), std::forward< Fn >( fn), preserve_fpu) {
+template< typename Fn,
+ typename
+>
+push_coroutine< void >::push_coroutine( Fn && fn) :
+ push_coroutine{ default_stack(), std::forward< Fn >( fn) } {
}
template< typename StackAllocator, typename Fn >
-push_coroutine< void >::push_coroutine( StackAllocator salloc, Fn && fn, bool preserve_fpu) :
- cb_( nullptr) {
- context::stack_context sctx( salloc.allocate() );
- // reserve space for control structure
-#if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
- void * sp = static_cast< char * >( sctx.sp) - sizeof( control_block);
- std::size_t size = sctx.size - sizeof( control_block);
-#else
- constexpr std::size_t func_alignment = 64; // alignof( control_block);
- constexpr std::size_t func_size = sizeof( control_block);
- // reserve space on stack
- void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
- // align sp pointer
- std::size_t space = func_size + func_alignment;
- sp = std::align( func_alignment, func_size, sp, space);
- BOOST_ASSERT( nullptr != sp);
- // calculate remaining size
- std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
-#endif
- // placment new for control structure on coroutine stack
- cb_ = new ( sp) control_block( context::preallocated( sp, size, sctx),
- salloc, std::forward< Fn >( fn), preserve_fpu);
+push_coroutine< void >::push_coroutine( StackAllocator salloc, Fn && fn) :
+ cb_{ create_control_block< control_block >( salloc, std::forward< Fn >( fn) ) } {
}
inline
-push_coroutine< void >::~push_coroutine() {
+push_coroutine< void >::~push_coroutine() noexcept {
if ( nullptr != cb_) {
- cb_->~control_block();
+ cb_->deallocate();
}
}
inline
-push_coroutine< void >::push_coroutine( push_coroutine && other) :
- cb_( other.cb_) {
+push_coroutine< void >::push_coroutine( push_coroutine && other) noexcept :
+ cb_{ other.cb_ } {
other.cb_ = nullptr;
}
diff --git a/boost/coroutine2/detail/state.hpp b/boost/coroutine2/detail/state.hpp
index 714548ff63..e338a5aed4 100644
--- a/boost/coroutine2/detail/state.hpp
+++ b/boost/coroutine2/detail/state.hpp
@@ -23,11 +23,60 @@ namespace coroutines2 {
namespace detail {
enum class state_t : unsigned int {
+ none = 0,
complete = 1 << 1,
- unwind = 1 << 2,
- early_exit = 1 << 3
+ unwind = 1 << 2
};
+
+inline
+constexpr state_t
+operator&( state_t l, state_t r) {
+ return static_cast< state_t >(
+ static_cast< unsigned int >( l) & static_cast< unsigned int >( r) );
+}
+
+inline
+constexpr state_t
+operator|( state_t l, state_t r) {
+ return static_cast< state_t >(
+ static_cast< unsigned int >( l) | static_cast< unsigned int >( r) );
+}
+
+inline
+constexpr state_t
+operator^( state_t l, state_t r) {
+ return static_cast< state_t >(
+ static_cast< unsigned int >( l) ^ static_cast< unsigned int >( r) );
+}
+
+inline
+constexpr state_t
+operator~( state_t l) {
+ return static_cast< state_t >( ~static_cast< unsigned int >( l) );
+}
+
+inline
+state_t &
+operator&=( state_t & l, state_t r) {
+ l = l & r;
+ return l;
+}
+
+inline
+state_t &
+operator|=( state_t & l, state_t r) {
+ l = l | r;
+ return l;
+}
+
+inline
+state_t &
+operator^=( state_t & l, state_t r) {
+ l = l ^ r;
+ return l;
+}
+
}}}
#ifdef BOOST_HAS_ABI_HEADERS
diff --git a/boost/coroutine2/fixedsize_stack.hpp b/boost/coroutine2/fixedsize_stack.hpp
index 8aa66fee61..54fc3dfddc 100644
--- a/boost/coroutine2/fixedsize_stack.hpp
+++ b/boost/coroutine2/fixedsize_stack.hpp
@@ -22,9 +22,9 @@
namespace boost {
namespace coroutines2 {
-typedef boost::context::fixedsize_stack fixedsize_stack;
+using fixedsize_stack = boost::context::fixedsize_stack;
#if !defined(BOOST_USE_SEGMENTED_STACKS)
-typedef boost::context::default_stack default_stack;
+using default_stack = boost::context::default_stack;
#endif
}}
diff --git a/boost/coroutine2/pooled_fixedsize_stack.hpp b/boost/coroutine2/pooled_fixedsize_stack.hpp
new file mode 100644
index 0000000000..24b59bb0d1
--- /dev/null
+++ b/boost/coroutine2/pooled_fixedsize_stack.hpp
@@ -0,0 +1,33 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINES2_POOLED_FIXEDSIZE_H
+#define BOOST_COROUTINES2_POOLED_FIXEDSIZE_H
+
+#include <exception>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/context/pooled_fixedsize_stack.hpp>
+
+#include <boost/coroutine2/detail/coroutine.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines2 {
+
+using pooled_fixedsize_stack = boost::context::pooled_fixedsize_stack;
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES2_POOLED_FIXEDSIZE_H
diff --git a/boost/coroutine2/protected_fixedsize_stack.hpp b/boost/coroutine2/protected_fixedsize_stack.hpp
index d2ee279775..938b6776db 100644
--- a/boost/coroutine2/protected_fixedsize_stack.hpp
+++ b/boost/coroutine2/protected_fixedsize_stack.hpp
@@ -22,7 +22,7 @@
namespace boost {
namespace coroutines2 {
-typedef boost::context::protected_fixedsize_stack protected_fixedsize_stack;
+using protected_fixedsize_stack = boost::context::protected_fixedsize_stack;
}}
diff --git a/boost/coroutine2/segmented_stack.hpp b/boost/coroutine2/segmented_stack.hpp
index 8443bc3561..24f93c86c2 100644
--- a/boost/coroutine2/segmented_stack.hpp
+++ b/boost/coroutine2/segmented_stack.hpp
@@ -24,8 +24,8 @@ namespace coroutines2 {
#if defined(BOOST_USE_SEGMENTED_STACKS)
# if ! defined(BOOST_WINDOWS)
-typedef boost::context::segmented_stack segmented_stack;
-typedef boost::context::default_stack default_stack;
+using segmented_stack = boost::context::segmented_stack;
+using default_stack = boost::context::default_stack;
# endif
#endif
diff --git a/boost/detail/utf8_codecvt_facet.hpp b/boost/detail/utf8_codecvt_facet.hpp
index 2d7ed8b2c4..b3c7346da7 100644
--- a/boost/detail/utf8_codecvt_facet.hpp
+++ b/boost/detail/utf8_codecvt_facet.hpp
@@ -105,16 +105,20 @@ BOOST_UTF8_BEGIN_NAMESPACE
// See utf8_codecvt_facet.ipp for the implementation. //
//----------------------------------------------------------------------------//
+#ifndef BOOST_UTF8_DECL
+#define BOOST_UTF8_DECL
+#endif
-struct BOOST_UTF8_DECL utf8_codecvt_facet :
+struct BOOST_SYMBOL_VISIBLE utf8_codecvt_facet :
public std::codecvt<wchar_t, char, std::mbstate_t>
{
public:
- explicit utf8_codecvt_facet(std::size_t no_locale_manage=0)
+ BOOST_UTF8_DECL explicit utf8_codecvt_facet(std::size_t no_locale_manage=0)
: std::codecvt<wchar_t, char, std::mbstate_t>(no_locale_manage)
{}
+ virtual ~utf8_codecvt_facet(){}
protected:
- virtual std::codecvt_base::result do_in(
+ BOOST_UTF8_DECL virtual std::codecvt_base::result do_in(
std::mbstate_t& state,
const char * from,
const char * from_end,
@@ -124,7 +128,7 @@ protected:
wchar_t*& to_next
) const;
- virtual std::codecvt_base::result do_out(
+ BOOST_UTF8_DECL virtual std::codecvt_base::result do_out(
std::mbstate_t & state,
const wchar_t * from,
const wchar_t * from_end,
@@ -148,11 +152,11 @@ protected:
return get_octet_count(lead_octet) - 1;
}
- static unsigned int get_octet_count(unsigned char lead_octet);
+ BOOST_UTF8_DECL static unsigned int get_octet_count(unsigned char lead_octet);
// How many "continuing octets" will be needed for this word
// == total octets - 1.
- int get_cont_octet_out_count(wchar_t word) const ;
+ BOOST_UTF8_DECL int get_cont_octet_out_count(wchar_t word) const ;
virtual bool do_always_noconv() const BOOST_NOEXCEPT_OR_NOTHROW {
return false;
@@ -176,7 +180,7 @@ protected:
// How many char objects can I process to get <= max_limit
// wchar_t objects?
- virtual int do_length(
+ BOOST_UTF8_DECL virtual int do_length(
const std::mbstate_t &,
const char * from,
const char * from_end,
diff --git a/boost/detail/utf8_codecvt_facet.ipp b/boost/detail/utf8_codecvt_facet.ipp
index d39170fdab..a6a5e2d375 100644
--- a/boost/detail/utf8_codecvt_facet.ipp
+++ b/boost/detail/utf8_codecvt_facet.ipp
@@ -31,7 +31,7 @@ BOOST_UTF8_BEGIN_NAMESPACE
// implementation for wchar_t
// Translate incoming UTF-8 into UCS-4
-std::codecvt_base::result utf8_codecvt_facet::do_in(
+BOOST_UTF8_DECL std::codecvt_base::result utf8_codecvt_facet::do_in(
std::mbstate_t& /*state*/,
const char * from,
const char * from_end,
@@ -108,7 +108,7 @@ std::codecvt_base::result utf8_codecvt_facet::do_in(
else return std::codecvt_base::partial;
}
-std::codecvt_base::result utf8_codecvt_facet::do_out(
+BOOST_UTF8_DECL std::codecvt_base::result utf8_codecvt_facet::do_out(
std::mbstate_t& /*state*/,
const wchar_t * from,
const wchar_t * from_end,
@@ -170,7 +170,7 @@ std::codecvt_base::result utf8_codecvt_facet::do_out(
// How many char objects can I process to get <= max_limit
// wchar_t objects?
-int utf8_codecvt_facet::do_length(
+BOOST_UTF8_DECL int utf8_codecvt_facet::do_length(
const std::mbstate_t &,
const char * from,
const char * from_end,
@@ -201,7 +201,7 @@ int utf8_codecvt_facet::do_length(
return static_cast<int>(from_next-from_end);
}
-unsigned int utf8_codecvt_facet::get_octet_count(
+BOOST_UTF8_DECL unsigned int utf8_codecvt_facet::get_octet_count(
unsigned char lead_octet
){
// if the 0-bit (MSB) is 0, then 1 character
@@ -273,7 +273,7 @@ int get_cont_octet_out_count_impl<4>(wchar_t word){
// How many "continuing octets" will be needed for this word
// == total octets - 1.
-int utf8_codecvt_facet::get_cont_octet_out_count(
+BOOST_UTF8_DECL int utf8_codecvt_facet::get_cont_octet_out_count(
wchar_t word
) const {
return detail::get_cont_octet_out_count_impl<sizeof(wchar_t)>(word);
diff --git a/boost/detail/winapi/GetCurrentProcess.hpp b/boost/detail/winapi/GetCurrentProcess.hpp
index 431b52fa4c..14d5186888 100644
--- a/boost/detail/winapi/GetCurrentProcess.hpp
+++ b/boost/detail/winapi/GetCurrentProcess.hpp
@@ -10,25 +10,16 @@
#ifndef BOOST_DETAIL_WINAPI_GETCURRENTPROCESS_HPP
#define BOOST_DETAIL_WINAPI_GETCURRENTPROCESS_HPP
-#include <boost/detail/winapi/basic_types.hpp>
+#include <boost/detail/winapi/get_current_process.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
-// Windows CE define GetCurrentProcess as an inline function in kfuncs.h
-#if !defined( BOOST_USE_WINDOWS_H ) && !defined( UNDER_CE )
-extern "C" {
-BOOST_SYMBOL_IMPORT boost::detail::winapi::HANDLE_ WINAPI GetCurrentProcess(BOOST_DETAIL_WINAPI_VOID);
-}
+#if defined(__GNUC__)
+#pragma message "This header is deprecated, use boost/detail/winapi/get_current_process.hpp instead."
+#elif defined(_MSC_VER)
+#pragma message("This header is deprecated, use boost/detail/winapi/get_current_process.hpp instead.")
#endif
-namespace boost {
-namespace detail {
-namespace winapi {
-using ::GetCurrentProcess;
-}
-}
-}
-
#endif // BOOST_DETAIL_WINAPI_GETCURRENTPROCESS_HPP
diff --git a/boost/detail/winapi/GetCurrentThread.hpp b/boost/detail/winapi/GetCurrentThread.hpp
index cbcdc97bda..047add8c9c 100644
--- a/boost/detail/winapi/GetCurrentThread.hpp
+++ b/boost/detail/winapi/GetCurrentThread.hpp
@@ -10,25 +10,16 @@
#ifndef BOOST_DETAIL_WINAPI_GETCURRENTTHREAD_HPP
#define BOOST_DETAIL_WINAPI_GETCURRENTTHREAD_HPP
-#include <boost/detail/winapi/basic_types.hpp>
+#include <boost/detail/winapi/get_current_thread.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
-// Windows CE define GetCurrentThread as an inline function in kfuncs.h
-#if !defined( BOOST_USE_WINDOWS_H ) && !defined( UNDER_CE )
-extern "C" {
-BOOST_SYMBOL_IMPORT boost::detail::winapi::HANDLE_ WINAPI GetCurrentThread(BOOST_DETAIL_WINAPI_VOID);
-}
+#if defined(__GNUC__)
+#pragma message "This header is deprecated, use boost/detail/winapi/get_current_thread.hpp instead."
+#elif defined(_MSC_VER)
+#pragma message("This header is deprecated, use boost/detail/winapi/get_current_thread.hpp instead.")
#endif
-namespace boost {
-namespace detail {
-namespace winapi {
-using ::GetCurrentThread;
-}
-}
-}
-
#endif // BOOST_DETAIL_WINAPI_GETCURRENTTHREAD_HPP
diff --git a/boost/detail/winapi/GetLastError.hpp b/boost/detail/winapi/GetLastError.hpp
index 8874ba853a..7fda753806 100644
--- a/boost/detail/winapi/GetLastError.hpp
+++ b/boost/detail/winapi/GetLastError.hpp
@@ -10,24 +10,16 @@
#ifndef BOOST_DETAIL_WINAPI_GETLASTERROR_HPP
#define BOOST_DETAIL_WINAPI_GETLASTERROR_HPP
-#include <boost/detail/winapi/basic_types.hpp>
+#include <boost/detail/winapi/get_last_error.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
-#if !defined( BOOST_USE_WINDOWS_H )
-extern "C" {
-BOOST_SYMBOL_IMPORT boost::detail::winapi::DWORD_ WINAPI GetLastError(BOOST_DETAIL_WINAPI_VOID);
-}
+#if defined(__GNUC__)
+#pragma message "This header is deprecated, use boost/detail/winapi/get_last_error.hpp instead."
+#elif defined(_MSC_VER)
+#pragma message("This header is deprecated, use boost/detail/winapi/get_last_error.hpp instead.")
#endif
-namespace boost {
-namespace detail {
-namespace winapi {
-using ::GetLastError;
-}
-}
-}
-
#endif // BOOST_DETAIL_WINAPI_GETLASTERROR_HPP
diff --git a/boost/detail/winapi/GetProcessTimes.hpp b/boost/detail/winapi/GetProcessTimes.hpp
index 41b3f0e493..7b2b969261 100644
--- a/boost/detail/winapi/GetProcessTimes.hpp
+++ b/boost/detail/winapi/GetProcessTimes.hpp
@@ -9,52 +9,16 @@
#ifndef BOOST_DETAIL_WINAPI_GETPROCESSTIMES_HPP
#define BOOST_DETAIL_WINAPI_GETPROCESSTIMES_HPP
-#include <boost/detail/winapi/config.hpp>
+#include <boost/detail/winapi/get_process_times.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
-// Windows CE does not define GetProcessTimes
-#if !defined( UNDER_CE )
-
-#include <boost/detail/winapi/basic_types.hpp>
-#include <boost/detail/winapi/time.hpp>
-
-#if !defined( BOOST_USE_WINDOWS_H )
-extern "C" {
-BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI
-GetProcessTimes(
- boost::detail::winapi::HANDLE_ hProcess,
- ::_FILETIME* lpCreationTime,
- ::_FILETIME* lpExitTime,
- ::_FILETIME* lpKernelTime,
- ::_FILETIME* lpUserTime);
-}
+#if defined(__GNUC__)
+#pragma message "This header is deprecated, use boost/detail/winapi/get_process_times.hpp instead."
+#elif defined(_MSC_VER)
+#pragma message("This header is deprecated, use boost/detail/winapi/get_process_times.hpp instead.")
#endif
-namespace boost {
-namespace detail {
-namespace winapi {
-
-BOOST_FORCEINLINE BOOL_ GetProcessTimes(
- HANDLE_ hProcess,
- LPFILETIME_ lpCreationTime,
- LPFILETIME_ lpExitTime,
- LPFILETIME_ lpKernelTime,
- LPFILETIME_ lpUserTime)
-{
- return ::GetProcessTimes(
- hProcess,
- reinterpret_cast< ::_FILETIME* >(lpCreationTime),
- reinterpret_cast< ::_FILETIME* >(lpExitTime),
- reinterpret_cast< ::_FILETIME* >(lpKernelTime),
- reinterpret_cast< ::_FILETIME* >(lpUserTime));
-}
-
-}
-}
-}
-
-#endif // !defined( UNDER_CE )
#endif // BOOST_DETAIL_WINAPI_GETPROCESSTIMES_HPP
diff --git a/boost/detail/winapi/GetThreadTimes.hpp b/boost/detail/winapi/GetThreadTimes.hpp
index 2e1eb8f45c..d69c410e61 100644
--- a/boost/detail/winapi/GetThreadTimes.hpp
+++ b/boost/detail/winapi/GetThreadTimes.hpp
@@ -10,46 +10,16 @@
#ifndef BOOST_DETAIL_WINAPI_GETTHREADTIMES_HPP
#define BOOST_DETAIL_WINAPI_GETTHREADTIMES_HPP
-#include <boost/detail/winapi/basic_types.hpp>
-#include <boost/detail/winapi/time.hpp>
+#include <boost/detail/winapi/get_thread_times.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
-#if !defined( BOOST_USE_WINDOWS_H )
-extern "C" {
-BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI
-GetThreadTimes(
- boost::detail::winapi::HANDLE_ hThread,
- ::_FILETIME* lpCreationTime,
- ::_FILETIME* lpExitTime,
- ::_FILETIME* lpKernelTime,
- ::_FILETIME* lpUserTime);
-}
+#if defined(__GNUC__)
+#pragma message "This header is deprecated, use boost/detail/winapi/get_thread_times.hpp instead."
+#elif defined(_MSC_VER)
+#pragma message("This header is deprecated, use boost/detail/winapi/get_thread_times.hpp instead.")
#endif
-namespace boost {
-namespace detail {
-namespace winapi {
-
-BOOST_FORCEINLINE BOOL_ GetThreadTimes(
- HANDLE_ hThread,
- LPFILETIME_ lpCreationTime,
- LPFILETIME_ lpExitTime,
- LPFILETIME_ lpKernelTime,
- LPFILETIME_ lpUserTime)
-{
- return ::GetThreadTimes(
- hThread,
- reinterpret_cast< ::_FILETIME* >(lpCreationTime),
- reinterpret_cast< ::_FILETIME* >(lpExitTime),
- reinterpret_cast< ::_FILETIME* >(lpKernelTime),
- reinterpret_cast< ::_FILETIME* >(lpUserTime));
-}
-
-}
-}
-}
-
#endif // BOOST_DETAIL_WINAPI_GETTHREADTIMES_HPP
diff --git a/boost/detail/winapi/access_rights.hpp b/boost/detail/winapi/access_rights.hpp
new file mode 100644
index 0000000000..951edb1db4
--- /dev/null
+++ b/boost/detail/winapi/access_rights.hpp
@@ -0,0 +1,84 @@
+// access_rights.hpp --------------------------------------------------------------//
+
+// Copyright 2016 Andrey Semashev
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+
+#ifndef BOOST_DETAIL_WINAPI_ACCESS_RIGHTS_HPP
+#define BOOST_DETAIL_WINAPI_ACCESS_RIGHTS_HPP
+
+#include <boost/detail/winapi/basic_types.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+namespace detail {
+namespace winapi {
+
+#if defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ DELETE_ = DELETE;
+const DWORD_ READ_CONTROL_ = READ_CONTROL;
+const DWORD_ WRITE_DAC_ = WRITE_DAC;
+const DWORD_ WRITE_OWNER_ = WRITE_OWNER;
+const DWORD_ SYNCHRONIZE_ = SYNCHRONIZE;
+
+const DWORD_ STANDARD_RIGHTS_ALL_ = STANDARD_RIGHTS_ALL;
+const DWORD_ STANDARD_RIGHTS_EXECUTE_ = STANDARD_RIGHTS_EXECUTE;
+const DWORD_ STANDARD_RIGHTS_READ_ = STANDARD_RIGHTS_READ;
+const DWORD_ STANDARD_RIGHTS_REQUIRED_ = STANDARD_RIGHTS_REQUIRED;
+const DWORD_ STANDARD_RIGHTS_WRITE_ = STANDARD_RIGHTS_WRITE;
+
+const DWORD_ SPECIFIC_RIGHTS_ALL_ = SPECIFIC_RIGHTS_ALL;
+
+const DWORD_ ACCESS_SYSTEM_SECURITY_ = ACCESS_SYSTEM_SECURITY;
+
+const DWORD_ MAXIMUM_ALLOWED_ = MAXIMUM_ALLOWED;
+
+const DWORD_ GENERIC_ALL_ = GENERIC_ALL;
+const DWORD_ GENERIC_EXECUTE_ = GENERIC_EXECUTE;
+const DWORD_ GENERIC_WRITE_ = GENERIC_WRITE;
+const DWORD_ GENERIC_READ_ = GENERIC_READ;
+
+typedef ::ACCESS_MASK ACCESS_MASK_;
+typedef ::PACCESS_MASK PACCESS_MASK_;
+
+#else // defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ DELETE_ = 0x00010000;
+const DWORD_ READ_CONTROL_ = 0x00020000;
+const DWORD_ WRITE_DAC_ = 0x00040000;
+const DWORD_ WRITE_OWNER_ = 0x00080000;
+const DWORD_ SYNCHRONIZE_ = 0x00100000;
+
+const DWORD_ STANDARD_RIGHTS_ALL_ = 0x001F0000;
+const DWORD_ STANDARD_RIGHTS_EXECUTE_ = READ_CONTROL_;
+const DWORD_ STANDARD_RIGHTS_READ_ = READ_CONTROL_;
+const DWORD_ STANDARD_RIGHTS_REQUIRED_ = 0x000F0000;
+const DWORD_ STANDARD_RIGHTS_WRITE_ = READ_CONTROL_;
+
+const DWORD_ SPECIFIC_RIGHTS_ALL_ = 0x0000FFFF;
+
+const DWORD_ ACCESS_SYSTEM_SECURITY_ = 0x01000000;
+
+const DWORD_ MAXIMUM_ALLOWED_ = 0x02000000;
+
+const DWORD_ GENERIC_ALL_ = 0x10000000;
+const DWORD_ GENERIC_EXECUTE_ = 0x20000000;
+const DWORD_ GENERIC_WRITE_ = 0x40000000;
+const DWORD_ GENERIC_READ_ = 0x80000000;
+
+typedef DWORD_ ACCESS_MASK_;
+typedef ACCESS_MASK_* PACCESS_MASK_;
+
+#endif // defined( BOOST_USE_WINDOWS_H )
+
+}
+}
+}
+
+#endif // BOOST_DETAIL_WINAPI_ACCESS_RIGHTS_HPP
diff --git a/boost/detail/winapi/basic_types.hpp b/boost/detail/winapi/basic_types.hpp
index 717e934e42..30df135642 100644
--- a/boost/detail/winapi/basic_types.hpp
+++ b/boost/detail/winapi/basic_types.hpp
@@ -98,6 +98,10 @@ typedef ::PDWORD PDWORD_;
typedef ::LPDWORD LPDWORD_;
typedef ::HANDLE HANDLE_;
typedef ::PHANDLE PHANDLE_;
+typedef ::SHORT SHORT_;
+typedef ::PSHORT PSHORT_;
+typedef ::USHORT USHORT_;
+typedef ::PUSHORT PUSHORT_;
typedef ::INT INT_;
typedef ::PINT PINT_;
typedef ::LPINT LPINT_;
@@ -150,6 +154,10 @@ typedef DWORD_* LPDWORD_;
typedef void* HANDLE_;
typedef void** PHANDLE_;
+typedef short SHORT_;
+typedef SHORT_* PSHORT_;
+typedef unsigned short USHORT_;
+typedef USHORT_* PUSHORT_;
typedef int INT_;
typedef INT_* PINT_;
typedef INT_* LPINT_;
diff --git a/boost/detail/winapi/character_code_conversion.hpp b/boost/detail/winapi/character_code_conversion.hpp
new file mode 100644
index 0000000000..d7c4cbeda0
--- /dev/null
+++ b/boost/detail/winapi/character_code_conversion.hpp
@@ -0,0 +1,108 @@
+// character_code_conversion.hpp --------------------------------------------------------------//
+
+// Copyright 2016 Andrey Semashev
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+
+#ifndef BOOST_DETAIL_WINAPI_CHARACTER_CODE_CONVERSION_HPP
+#define BOOST_DETAIL_WINAPI_CHARACTER_CODE_CONVERSION_HPP
+
+#include <boost/detail/winapi/basic_types.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if !defined( BOOST_USE_WINDOWS_H )
+extern "C" {
+
+BOOST_SYMBOL_IMPORT int WINAPI
+MultiByteToWideChar(
+ boost::detail::winapi::UINT_ CodePage,
+ boost::detail::winapi::DWORD_ dwFlags,
+ boost::detail::winapi::LPCSTR_ lpMultiByteStr,
+ int cbMultiByte,
+ boost::detail::winapi::LPWSTR_ lpWideCharStr,
+ int cchWideChar);
+
+BOOST_SYMBOL_IMPORT int WINAPI
+WideCharToMultiByte(
+ boost::detail::winapi::UINT_ CodePage,
+ boost::detail::winapi::DWORD_ dwFlags,
+ boost::detail::winapi::LPCWSTR_ lpWideCharStr,
+ int cchWideChar,
+ boost::detail::winapi::LPSTR_ lpMultiByteStr,
+ int cbMultiByte,
+ boost::detail::winapi::LPCSTR_ lpDefaultChar,
+ boost::detail::winapi::LPBOOL_ lpUsedDefaultChar);
+
+} // extern "C"
+#endif // #if !defined( BOOST_USE_WINDOWS_H )
+
+namespace boost {
+namespace detail {
+namespace winapi {
+
+#if defined( BOOST_USE_WINDOWS_H )
+
+const UINT_ CP_ACP_ = CP_ACP;
+const UINT_ CP_OEMCP_ = CP_OEMCP;
+const UINT_ CP_MACCP_ = CP_MACCP;
+const UINT_ CP_THREAD_ACP_ = CP_THREAD_ACP;
+const UINT_ CP_SYMBOL_ = CP_SYMBOL;
+const UINT_ CP_UTF7_ = CP_UTF7;
+const UINT_ CP_UTF8_ = CP_UTF8;
+
+const DWORD_ MB_PRECOMPOSED_ = MB_PRECOMPOSED;
+const DWORD_ MB_COMPOSITE_ = MB_COMPOSITE;
+const DWORD_ MB_USEGLYPHCHARS_ = MB_USEGLYPHCHARS;
+const DWORD_ MB_ERR_INVALID_CHARS_ = MB_ERR_INVALID_CHARS;
+
+const DWORD_ WC_COMPOSITECHECK_ = WC_COMPOSITECHECK;
+const DWORD_ WC_DISCARDNS_ = WC_DISCARDNS;
+const DWORD_ WC_SEPCHARS_ = WC_SEPCHARS;
+const DWORD_ WC_DEFAULTCHAR_ = WC_DEFAULTCHAR;
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN2K
+const DWORD_ WC_NO_BEST_FIT_CHARS_ = WC_NO_BEST_FIT_CHARS;
+#endif
+
+#else // defined( BOOST_USE_WINDOWS_H )
+
+const UINT_ CP_ACP_ = 0u;
+const UINT_ CP_OEMCP_ = 1u;
+const UINT_ CP_MACCP_ = 2u;
+const UINT_ CP_THREAD_ACP_ = 3u;
+const UINT_ CP_SYMBOL_ = 42u;
+const UINT_ CP_UTF7_ = 65000u;
+const UINT_ CP_UTF8_ = 65001u;
+
+const DWORD_ MB_PRECOMPOSED_ = 0x00000001;
+const DWORD_ MB_COMPOSITE_ = 0x00000002;
+const DWORD_ MB_USEGLYPHCHARS_ = 0x00000004;
+const DWORD_ MB_ERR_INVALID_CHARS_ = 0x00000008;
+
+const DWORD_ WC_COMPOSITECHECK_ = 0x00000200;
+const DWORD_ WC_DISCARDNS_ = 0x00000010;
+const DWORD_ WC_SEPCHARS_ = 0x00000020;
+const DWORD_ WC_DEFAULTCHAR_ = 0x00000040;
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN2K
+const DWORD_ WC_NO_BEST_FIT_CHARS_ = 0x00000400;
+#endif
+
+#endif // defined( BOOST_USE_WINDOWS_H )
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+// This constant is not present in MinGW
+const DWORD_ WC_ERR_INVALID_CHARS_ = 0x00000080;
+#endif
+
+using ::MultiByteToWideChar;
+using ::WideCharToMultiByte;
+
+} // namespace winapi
+} // namespace detail
+} // namespace boost
+
+#endif // BOOST_DETAIL_WINAPI_CHARACTER_CODE_CONVERSION_HPP
diff --git a/boost/detail/winapi/condition_variable.hpp b/boost/detail/winapi/condition_variable.hpp
index b47a537158..7182d756a0 100644
--- a/boost/detail/winapi/condition_variable.hpp
+++ b/boost/detail/winapi/condition_variable.hpp
@@ -57,6 +57,13 @@ namespace winapi {
typedef struct BOOST_DETAIL_WINAPI_MAY_ALIAS _RTL_CONDITION_VARIABLE {
PVOID_ Ptr;
} CONDITION_VARIABLE_, *PCONDITION_VARIABLE_;
+
+#if defined( BOOST_USE_WINDOWS_H )
+#define BOOST_DETAIL_WINAPI_CONDITION_VARIABLE_INIT CONDITION_VARIABLE_INIT
+#else
+#define BOOST_DETAIL_WINAPI_CONDITION_VARIABLE {0}
+#endif
+
struct _RTL_CRITICAL_SECTION;
struct _RTL_SRWLOCK;
diff --git a/boost/detail/winapi/config.hpp b/boost/detail/winapi/config.hpp
index c67d670dd2..1f08c2a88e 100644
--- a/boost/detail/winapi/config.hpp
+++ b/boost/detail/winapi/config.hpp
@@ -9,15 +9,10 @@
#ifndef BOOST_DETAIL_WINAPI_CONFIG_HPP_INCLUDED_
#define BOOST_DETAIL_WINAPI_CONFIG_HPP_INCLUDED_
-#include <boost/config.hpp>
#if defined __MINGW32__
#include <_mingw.h>
#endif
-#ifdef BOOST_HAS_PRAGMA_ONCE
-#pragma once
-#endif
-
// BOOST_WINAPI_IS_MINGW indicates that the target Windows SDK is provided by MinGW (http://mingw.org/).
// BOOST_WINAPI_IS_MINGW_W64 indicates that the target Windows SDK is provided by MinGW-w64 (http://mingw-w64.org).
#if defined __MINGW32__
@@ -51,7 +46,7 @@
#define BOOST_USE_WINAPI_VERSION WINVER
#else
// By default use Windows Vista API on compilers that support it and XP on the others
-#if (defined(_MSC_VER) && _MSC_VER <= 1400) || defined(BOOST_WINAPI_IS_MINGW)
+#if (defined(_MSC_VER) && _MSC_VER < 1500) || defined(BOOST_WINAPI_IS_MINGW)
#define BOOST_USE_WINAPI_VERSION BOOST_WINAPI_VERSION_WINXP
#else
#define BOOST_USE_WINAPI_VERSION BOOST_WINAPI_VERSION_WIN6
@@ -69,4 +64,10 @@
#endif
#endif
+#include <boost/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
#endif // BOOST_DETAIL_WINAPI_CONFIG_HPP_INCLUDED_
diff --git a/boost/detail/winapi/crypt.hpp b/boost/detail/winapi/crypt.hpp
index 4d2ebedb01..0650845179 100644
--- a/boost/detail/winapi/crypt.hpp
+++ b/boost/detail/winapi/crypt.hpp
@@ -12,8 +12,8 @@
#include <boost/detail/winapi/basic_types.hpp>
#include <boost/detail/winapi/detail/cast_ptr.hpp>
-#if defined( BOOST_USE_WINDOWS_H ) && defined( BOOST_WINAPI_IS_MINGW )
-// MinGW does not include this header as part of windows.h
+#if defined( BOOST_USE_WINDOWS_H )
+// This header is not always included as part of windows.h
#include <wincrypt.h>
#endif
diff --git a/boost/detail/winapi/dbghelp.hpp b/boost/detail/winapi/dbghelp.hpp
new file mode 100644
index 0000000000..74add558b8
--- /dev/null
+++ b/boost/detail/winapi/dbghelp.hpp
@@ -0,0 +1,171 @@
+// dbghelp.hpp --------------------------------------------------------------//
+
+// Copyright 2015 Klemens Morgenstern
+// Copyright 2016 Jorge Lodos
+// Copyright 2016 Andrey Semashev
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+
+#ifndef BOOST_DETAIL_WINAPI_DBGHELP_HPP
+#define BOOST_DETAIL_WINAPI_DBGHELP_HPP
+
+#include <boost/detail/winapi/basic_types.hpp>
+
+#if defined( BOOST_USE_WINDOWS_H )
+#if !defined( BOOST_WINAPI_IS_MINGW )
+#include <dbghelp.h>
+#else
+// In MinGW there is no dbghelp.h but an older imagehlp.h header defines some of the symbols from it.
+// Note that the user has to link with libimagehlp.a instead of libdbghelp.a for it to work.
+#include <imagehlp.h>
+#endif
+#endif
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+// Some symbols declared below are not present in all versions of Windows SDK, MinGW and MinGW-w64.
+// dbghelp.h/imagehlp.h define the API_VERSION_NUMBER macro which we use to detect its version.
+// When the macro is not available we can only guess based on the compiler version or SDK type.
+#if defined(API_VERSION_NUMBER)
+#if API_VERSION_NUMBER >= 11
+// UnDecorateSymbolNameW available since Windows SDK 6.0A and MinGW-w64 (as of 2016-02-14)
+#define BOOST_DETAIL_WINAPI_HAS_UNDECORATESYMBOLNAMEW
+#endif
+#elif defined(_MSC_VER) && _MSC_VER >= 1500
+// Until MSVC 9.0 Windows SDK was bundled in Visual Studio and didn't have UnDecorateSymbolNameW.
+// Supposedly, Windows SDK 6.0A was the first standalone one and it is used with MSVC 9.0.
+#define BOOST_DETAIL_WINAPI_HAS_UNDECORATESYMBOLNAMEW
+#elif !defined(BOOST_WINAPI_IS_MINGW)
+// MinGW does not provide UnDecorateSymbolNameW (as of 2016-02-14)
+#define BOOST_DETAIL_WINAPI_HAS_UNDECORATESYMBOLNAMEW
+#endif
+
+#if !defined( BOOST_USE_WINDOWS_H )
+extern "C" {
+
+struct API_VERSION;
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::DWORD_ WINAPI
+UnDecorateSymbolName(
+ boost::detail::winapi::LPCSTR_ DecoratedName,
+ boost::detail::winapi::LPSTR_ UnDecoratedName,
+ boost::detail::winapi::DWORD_ UndecoratedLength,
+ boost::detail::winapi::DWORD_ Flags);
+
+#if defined( BOOST_DETAIL_WINAPI_HAS_UNDECORATESYMBOLNAMEW )
+BOOST_SYMBOL_IMPORT boost::detail::winapi::DWORD_ WINAPI
+UnDecorateSymbolNameW(
+ boost::detail::winapi::LPCWSTR_ DecoratedName,
+ boost::detail::winapi::LPWSTR_ UnDecoratedName,
+ boost::detail::winapi::DWORD_ UndecoratedLength,
+ boost::detail::winapi::DWORD_ Flags);
+#endif
+
+BOOST_SYMBOL_IMPORT API_VERSION* WINAPI
+ImagehlpApiVersion(BOOST_DETAIL_WINAPI_VOID);
+
+} // extern "C"
+#endif
+
+namespace boost {
+namespace detail {
+namespace winapi {
+
+#if defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ UNDNAME_COMPLETE_ = UNDNAME_COMPLETE;
+const DWORD_ UNDNAME_NO_LEADING_UNDERSCORES_ = UNDNAME_NO_LEADING_UNDERSCORES;
+const DWORD_ UNDNAME_NO_MS_KEYWORDS_ = UNDNAME_NO_MS_KEYWORDS;
+const DWORD_ UNDNAME_NO_FUNCTION_RETURNS_ = UNDNAME_NO_FUNCTION_RETURNS;
+const DWORD_ UNDNAME_NO_ALLOCATION_MODEL_ = UNDNAME_NO_ALLOCATION_MODEL;
+const DWORD_ UNDNAME_NO_ALLOCATION_LANGUAGE_ = UNDNAME_NO_ALLOCATION_LANGUAGE;
+const DWORD_ UNDNAME_NO_MS_THISTYPE_ = UNDNAME_NO_MS_THISTYPE;
+const DWORD_ UNDNAME_NO_CV_THISTYPE_ = UNDNAME_NO_CV_THISTYPE;
+const DWORD_ UNDNAME_NO_THISTYPE_ = UNDNAME_NO_THISTYPE;
+const DWORD_ UNDNAME_NO_ACCESS_SPECIFIERS_ = UNDNAME_NO_ACCESS_SPECIFIERS;
+const DWORD_ UNDNAME_NO_THROW_SIGNATURES_ = UNDNAME_NO_THROW_SIGNATURES;
+const DWORD_ UNDNAME_NO_MEMBER_TYPE_ = UNDNAME_NO_MEMBER_TYPE;
+const DWORD_ UNDNAME_NO_RETURN_UDT_MODEL_ = UNDNAME_NO_RETURN_UDT_MODEL;
+const DWORD_ UNDNAME_32_BIT_DECODE_ = UNDNAME_32_BIT_DECODE;
+const DWORD_ UNDNAME_NAME_ONLY_ = UNDNAME_NAME_ONLY;
+const DWORD_ UNDNAME_NO_ARGUMENTS_ = UNDNAME_NO_ARGUMENTS;
+const DWORD_ UNDNAME_NO_SPECIAL_SYMS_ = UNDNAME_NO_SPECIAL_SYMS;
+
+#else // defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ UNDNAME_COMPLETE_ = 0x00000000;
+const DWORD_ UNDNAME_NO_LEADING_UNDERSCORES_ = 0x00000001;
+const DWORD_ UNDNAME_NO_MS_KEYWORDS_ = 0x00000002;
+const DWORD_ UNDNAME_NO_FUNCTION_RETURNS_ = 0x00000004;
+const DWORD_ UNDNAME_NO_ALLOCATION_MODEL_ = 0x00000008;
+const DWORD_ UNDNAME_NO_ALLOCATION_LANGUAGE_ = 0x00000010;
+const DWORD_ UNDNAME_NO_MS_THISTYPE_ = 0x00000020;
+const DWORD_ UNDNAME_NO_CV_THISTYPE_ = 0x00000040;
+const DWORD_ UNDNAME_NO_THISTYPE_ = 0x00000060;
+const DWORD_ UNDNAME_NO_ACCESS_SPECIFIERS_ = 0x00000080;
+const DWORD_ UNDNAME_NO_THROW_SIGNATURES_ = 0x00000100;
+const DWORD_ UNDNAME_NO_MEMBER_TYPE_ = 0x00000200;
+const DWORD_ UNDNAME_NO_RETURN_UDT_MODEL_ = 0x00000400;
+const DWORD_ UNDNAME_32_BIT_DECODE_ = 0x00000800;
+const DWORD_ UNDNAME_NAME_ONLY_ = 0x00001000;
+const DWORD_ UNDNAME_NO_ARGUMENTS_ = 0x00002000;
+const DWORD_ UNDNAME_NO_SPECIAL_SYMS_ = 0x00004000;
+
+#endif // defined( BOOST_USE_WINDOWS_H )
+
+using ::UnDecorateSymbolName;
+#if defined( BOOST_DETAIL_WINAPI_HAS_UNDECORATESYMBOLNAMEW )
+using ::UnDecorateSymbolNameW;
+#endif
+
+typedef struct BOOST_DETAIL_WINAPI_MAY_ALIAS API_VERSION {
+ USHORT_ MajorVersion;
+ USHORT_ MinorVersion;
+ USHORT_ Revision;
+ USHORT_ Reserved;
+} API_VERSION_, *LPAPI_VERSION_;
+
+BOOST_FORCEINLINE LPAPI_VERSION_ ImagehlpApiVersion()
+{
+ return reinterpret_cast<LPAPI_VERSION_>(::ImagehlpApiVersion());
+}
+
+BOOST_FORCEINLINE DWORD_ undecorate_symbol_name(
+ LPCSTR_ DecoratedName,
+ LPSTR_ UnDecoratedName,
+ DWORD_ UndecoratedLength,
+ DWORD_ Flags)
+{
+ return ::UnDecorateSymbolName(
+ DecoratedName,
+ UnDecoratedName,
+ UndecoratedLength,
+ Flags);
+}
+
+#if defined( BOOST_DETAIL_WINAPI_HAS_UNDECORATESYMBOLNAMEW )
+
+BOOST_FORCEINLINE DWORD_ undecorate_symbol_name(
+ LPCWSTR_ DecoratedName,
+ LPWSTR_ UnDecoratedName,
+ DWORD_ UndecoratedLength,
+ DWORD_ Flags)
+{
+ return ::UnDecorateSymbolNameW(
+ DecoratedName,
+ UnDecoratedName,
+ UndecoratedLength,
+ Flags);
+}
+
+#endif
+
+}
+}
+}
+
+#endif // BOOST_DETAIL_WINAPI_DBGHELP_HPP
diff --git a/boost/detail/winapi/directory_management.hpp b/boost/detail/winapi/directory_management.hpp
index 61e406b02e..1da53c38cc 100644
--- a/boost/detail/winapi/directory_management.hpp
+++ b/boost/detail/winapi/directory_management.hpp
@@ -11,6 +11,7 @@
#define BOOST_DETAIL_WINAPI_DIRECTORY_MANAGEMENT_HPP
#include <boost/detail/winapi/basic_types.hpp>
+#include <boost/detail/winapi/get_system_directory.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
diff --git a/boost/detail/winapi/dll.hpp b/boost/detail/winapi/dll.hpp
index 5172f33880..2872936581 100644
--- a/boost/detail/winapi/dll.hpp
+++ b/boost/detail/winapi/dll.hpp
@@ -77,8 +77,17 @@ GetModuleFileNameW(
BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI
FreeLibrary(boost::detail::winapi::HMODULE_ hModule);
+#if !defined( UNDER_CE )
BOOST_SYMBOL_IMPORT boost::detail::winapi::FARPROC_ WINAPI
GetProcAddress(boost::detail::winapi::HMODULE_ hModule, boost::detail::winapi::LPCSTR_ lpProcName);
+#else
+// On Windows CE there are two functions: GetProcAddressA (since Windows CE 3.0) and GetProcAddressW.
+// GetProcAddress is a macro that is _always_ defined to GetProcAddressW.
+BOOST_SYMBOL_IMPORT boost::detail::winapi::FARPROC_ WINAPI
+GetProcAddressA(boost::detail::winapi::HMODULE_ hModule, boost::detail::winapi::LPCSTR_ lpProcName);
+BOOST_SYMBOL_IMPORT boost::detail::winapi::FARPROC_ WINAPI
+GetProcAddressW(boost::detail::winapi::HMODULE_ hModule, boost::detail::winapi::LPCWSTR_ lpProcName);
+#endif
struct _MEMORY_BASIC_INFORMATION;
@@ -140,7 +149,23 @@ using ::LoadLibraryExW;
using ::GetModuleHandleW;
using ::GetModuleFileNameW;
using ::FreeLibrary;
+
+#if !defined( UNDER_CE )
+// For backward compatibility, don't use directly. Use get_proc_address instead.
using ::GetProcAddress;
+#else
+using ::GetProcAddressA;
+using ::GetProcAddressW;
+#endif
+
+BOOST_FORCEINLINE FARPROC_ get_proc_address(HMODULE_ hModule, LPCSTR_ lpProcName)
+{
+#if !defined( UNDER_CE )
+ return ::GetProcAddress(hModule, lpProcName);
+#else
+ return ::GetProcAddressA(hModule, lpProcName);
+#endif
+}
BOOST_FORCEINLINE SIZE_T_ VirtualQuery(LPCVOID_ lpAddress, MEMORY_BASIC_INFORMATION_* lpBuffer, ULONG_PTR_ dwLength)
{
diff --git a/boost/detail/winapi/error_handling.hpp b/boost/detail/winapi/error_handling.hpp
index cdd759ded5..4847bc944d 100644
--- a/boost/detail/winapi/error_handling.hpp
+++ b/boost/detail/winapi/error_handling.hpp
@@ -2,6 +2,7 @@
// Copyright 2010 Vicente J. Botet Escriba
// Copyright 2015 Andrey Semashev
+// Copyright 2016 Jorge Lodos
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
@@ -12,7 +13,7 @@
#include <stdarg.h>
#include <boost/detail/winapi/basic_types.hpp>
-#include <boost/detail/winapi/GetLastError.hpp>
+#include <boost/detail/winapi/get_last_error.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -41,6 +42,9 @@ FormatMessageW(
boost::detail::winapi::LPWSTR_ lpBuffer,
boost::detail::winapi::DWORD_ nSize,
va_list *Arguments);
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::UINT_ WINAPI
+SetErrorMode(boost::detail::winapi::UINT_ uMode);
}
#endif
@@ -68,6 +72,11 @@ BOOST_FORCEINLINE WORD_ MAKELANGID_(WORD_ p, WORD_ s)
return MAKELANGID(p,s);
}
+const DWORD_ SEM_FAILCRITICALERRORS_ = SEM_FAILCRITICALERRORS;
+const DWORD_ SEM_NOGPFAULTERRORBOX_ = SEM_NOGPFAULTERRORBOX;
+const DWORD_ SEM_NOALIGNMENTFAULTEXCEPT_ = SEM_NOALIGNMENTFAULTEXCEPT;
+const DWORD_ SEM_NOOPENFILEERRORBOX_ = SEM_NOOPENFILEERRORBOX;
+
#else
const DWORD_ FORMAT_MESSAGE_ALLOCATE_BUFFER_= 0x00000100;
@@ -85,15 +94,21 @@ const WORD_ SUBLANG_DEFAULT_= 0x01; // user default
BOOST_FORCEINLINE WORD_ MAKELANGID_(WORD_ p, WORD_ s)
{
- return ((((WORD_)(s)) << 10) | (WORD_)(p));
+ return (WORD_)((((WORD_)(s)) << 10) | (WORD_)(p));
}
+const DWORD_ SEM_FAILCRITICALERRORS_ = 0x0001;
+const DWORD_ SEM_NOGPFAULTERRORBOX_ = 0x0002;
+const DWORD_ SEM_NOALIGNMENTFAULTEXCEPT_ = 0x0004;
+const DWORD_ SEM_NOOPENFILEERRORBOX_ = 0x8000;
+
#endif
#if !defined( BOOST_NO_ANSI_APIS )
using ::FormatMessageA;
#endif
using ::FormatMessageW;
+using ::SetErrorMode;
#if !defined( BOOST_NO_ANSI_APIS )
BOOST_FORCEINLINE DWORD_ format_message(
diff --git a/boost/detail/winapi/event.hpp b/boost/detail/winapi/event.hpp
index ec2b096103..64ee892a04 100644
--- a/boost/detail/winapi/event.hpp
+++ b/boost/detail/winapi/event.hpp
@@ -92,14 +92,16 @@ using ::ResetEvent;
#if defined( BOOST_USE_WINDOWS_H )
const DWORD_ EVENT_ALL_ACCESS_ = EVENT_ALL_ACCESS;
+const DWORD_ EVENT_MODIFY_STATE_ = EVENT_MODIFY_STATE;
#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
const DWORD_ CREATE_EVENT_INITIAL_SET_ = CREATE_EVENT_INITIAL_SET;
const DWORD_ CREATE_EVENT_MANUAL_RESET_ = CREATE_EVENT_MANUAL_RESET;
#endif
#else // defined( BOOST_USE_WINDOWS_H )
-
-const DWORD_ EVENT_ALL_ACCESS_ = 0x1F0003;
+
+const DWORD_ EVENT_ALL_ACCESS_ = 0x001F0003;
+const DWORD_ EVENT_MODIFY_STATE_ = 0x00000002;
#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
const DWORD_ CREATE_EVENT_INITIAL_SET_ = 0x00000002;
const DWORD_ CREATE_EVENT_MANUAL_RESET_ = 0x00000001;
@@ -107,7 +109,12 @@ const DWORD_ CREATE_EVENT_MANUAL_RESET_ = 0x00000001;
#endif // defined( BOOST_USE_WINDOWS_H )
+// Undocumented and not present in Windows SDK. Enables NtQueryEvent.
+// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FEvent%2FNtQueryEvent.html
+const DWORD_ EVENT_QUERY_STATE_ = 0x00000001;
+
const DWORD_ event_all_access = EVENT_ALL_ACCESS_;
+const DWORD_ event_modify_state = EVENT_MODIFY_STATE_;
#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
const DWORD_ create_event_initial_set = CREATE_EVENT_INITIAL_SET_;
const DWORD_ create_event_manual_reset = CREATE_EVENT_MANUAL_RESET_;
@@ -118,7 +125,7 @@ BOOST_FORCEINLINE HANDLE_ CreateEventA(SECURITY_ATTRIBUTES_* lpEventAttributes,
{
#if BOOST_PLAT_WINDOWS_RUNTIME && BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
const DWORD_ flags = (bManualReset ? create_event_manual_reset : 0u) | (bInitialState ? create_event_initial_set : 0u);
- return ::CreateEventExA(reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpEventAttributes), lpName, flags, event_all_access);
+ return ::CreateEventExA(reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpEventAttributes), lpName, flags, event_all_access);
#else
return ::CreateEventA(reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpEventAttributes), bManualReset, bInitialState, lpName);
#endif
@@ -136,7 +143,7 @@ BOOST_FORCEINLINE HANDLE_ CreateEventW(SECURITY_ATTRIBUTES_* lpEventAttributes,
{
#if BOOST_PLAT_WINDOWS_RUNTIME && BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
const DWORD_ flags = (bManualReset ? create_event_manual_reset : 0u) | (bInitialState ? create_event_initial_set : 0u);
- return ::CreateEventExW(reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpEventAttributes), lpName, flags, event_all_access);
+ return ::CreateEventExW(reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpEventAttributes), lpName, flags, event_all_access);
#else
return ::CreateEventW(reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpEventAttributes), bManualReset, bInitialState, lpName);
#endif
diff --git a/boost/detail/winapi/file_management.hpp b/boost/detail/winapi/file_management.hpp
index c923d8499e..308535e2ae 100644
--- a/boost/detail/winapi/file_management.hpp
+++ b/boost/detail/winapi/file_management.hpp
@@ -2,6 +2,7 @@
// Copyright 2010 Vicente J. Botet Escriba
// Copyright 2015 Andrey Semashev
+// Copyright 2016 Jorge Lodos
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
@@ -11,7 +12,9 @@
#define BOOST_DETAIL_WINAPI_FILE_MANAGEMENT_HPP
#include <boost/detail/winapi/basic_types.hpp>
+#include <boost/detail/winapi/limits.hpp>
#include <boost/detail/winapi/time.hpp>
+#include <boost/detail/winapi/overlapped.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -19,7 +22,6 @@
#if !defined( BOOST_USE_WINDOWS_H )
extern "C" {
-struct _OVERLAPPED;
#if !defined( BOOST_NO_ANSI_APIS )
BOOST_SYMBOL_IMPORT boost::detail::winapi::HANDLE_ WINAPI
@@ -47,6 +49,12 @@ MoveFileExA(
boost::detail::winapi::LPCSTR_ lpExistingFileName,
boost::detail::winapi::LPCSTR_ lpNewFileName,
boost::detail::winapi::DWORD_ dwFlags);
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::DWORD_ WINAPI
+GetFileAttributesA(boost::detail::winapi::LPCSTR_ lpFileName);
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI
+AreFileApisANSI(BOOST_DETAIL_WINAPI_VOID);
#endif
BOOST_SYMBOL_IMPORT boost::detail::winapi::HANDLE_ WINAPI
@@ -75,6 +83,9 @@ MoveFileExW(
boost::detail::winapi::LPCWSTR_ lpNewFileName,
boost::detail::winapi::DWORD_ dwFlags);
+BOOST_SYMBOL_IMPORT boost::detail::winapi::DWORD_ WINAPI
+GetFileAttributesW(boost::detail::winapi::LPCWSTR_ lpFileName);
+
BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI
FindClose(boost::detail::winapi::HANDLE_ hFindFile);
@@ -131,6 +142,13 @@ WriteFile(
boost::detail::winapi::DWORD_ nNumberOfBytesToWrite,
boost::detail::winapi::LPDWORD_ lpNumberOfBytesWritten,
::_OVERLAPPED* lpOverlapped);
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::DWORD_ WINAPI
+SetFilePointer(
+ boost::detail::winapi::HANDLE_ hFile,
+ boost::detail::winapi::LONG_ lpDistanceToMove,
+ boost::detail::winapi::PLONG_ lpDistanceToMoveHigh,
+ boost::detail::winapi::DWORD_ dwMoveMethod);
}
#endif
@@ -138,13 +156,99 @@ namespace boost {
namespace detail {
namespace winapi {
+#if defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ INVALID_FILE_SIZE_ = INVALID_FILE_SIZE;
+const DWORD_ INVALID_SET_FILE_POINTER_ = INVALID_SET_FILE_POINTER;
+const DWORD_ INVALID_FILE_ATTRIBUTES_ = INVALID_FILE_ATTRIBUTES;
+
+const DWORD_ FILE_ATTRIBUTE_READONLY_ = FILE_ATTRIBUTE_READONLY;
+const DWORD_ FILE_ATTRIBUTE_HIDDEN_ = FILE_ATTRIBUTE_HIDDEN;
+const DWORD_ FILE_ATTRIBUTE_SYSTEM_ = FILE_ATTRIBUTE_SYSTEM;
+const DWORD_ FILE_ATTRIBUTE_DIRECTORY_ = FILE_ATTRIBUTE_DIRECTORY;
+const DWORD_ FILE_ATTRIBUTE_ARCHIVE_ = FILE_ATTRIBUTE_ARCHIVE;
+const DWORD_ FILE_ATTRIBUTE_DEVICE_ = FILE_ATTRIBUTE_DEVICE;
+const DWORD_ FILE_ATTRIBUTE_NORMAL_ = FILE_ATTRIBUTE_NORMAL;
+const DWORD_ FILE_ATTRIBUTE_TEMPORARY_ = FILE_ATTRIBUTE_TEMPORARY;
+const DWORD_ FILE_ATTRIBUTE_SPARSE_FILE_ = FILE_ATTRIBUTE_SPARSE_FILE;
+const DWORD_ FILE_ATTRIBUTE_REPARSE_POINT_ = FILE_ATTRIBUTE_REPARSE_POINT;
+const DWORD_ FILE_ATTRIBUTE_COMPRESSED_ = FILE_ATTRIBUTE_COMPRESSED;
+const DWORD_ FILE_ATTRIBUTE_OFFLINE_ = FILE_ATTRIBUTE_OFFLINE;
+const DWORD_ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED_ = FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
+const DWORD_ FILE_ATTRIBUTE_ENCRYPTED_ = FILE_ATTRIBUTE_ENCRYPTED;
+
+const DWORD_ CREATE_NEW_ = CREATE_NEW;
+const DWORD_ CREATE_ALWAYS_ = CREATE_ALWAYS;
+const DWORD_ OPEN_EXISTING_ = OPEN_EXISTING;
+const DWORD_ OPEN_ALWAYS_ = OPEN_ALWAYS;
+const DWORD_ TRUNCATE_EXISTING_ = TRUNCATE_EXISTING;
+
+const DWORD_ FILE_SHARE_READ_ = FILE_SHARE_READ;
+const DWORD_ FILE_SHARE_WRITE_ = FILE_SHARE_WRITE;
+const DWORD_ FILE_SHARE_DELETE_ = FILE_SHARE_DELETE;
+
+const DWORD_ FILE_BEGIN_ = FILE_BEGIN;
+const DWORD_ FILE_CURRENT_ = FILE_CURRENT;
+const DWORD_ FILE_END_ = FILE_END;
+
+#else // defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ INVALID_FILE_SIZE_ = ((DWORD_)0xFFFFFFFF);
+const DWORD_ INVALID_SET_FILE_POINTER_ = ((DWORD_)-1);
+const DWORD_ INVALID_FILE_ATTRIBUTES_ = ((DWORD_)-1);
+
+const DWORD_ FILE_ATTRIBUTE_READONLY_ = 0x00000001;
+const DWORD_ FILE_ATTRIBUTE_HIDDEN_ = 0x00000002;
+const DWORD_ FILE_ATTRIBUTE_SYSTEM_ = 0x00000004;
+const DWORD_ FILE_ATTRIBUTE_DIRECTORY_ = 0x00000010;
+const DWORD_ FILE_ATTRIBUTE_ARCHIVE_ = 0x00000020;
+const DWORD_ FILE_ATTRIBUTE_DEVICE_ = 0x00000040;
+const DWORD_ FILE_ATTRIBUTE_NORMAL_ = 0x00000080;
+const DWORD_ FILE_ATTRIBUTE_TEMPORARY_ = 0x00000100;
+const DWORD_ FILE_ATTRIBUTE_SPARSE_FILE_ = 0x00000200;
+const DWORD_ FILE_ATTRIBUTE_REPARSE_POINT_ = 0x00000400;
+const DWORD_ FILE_ATTRIBUTE_COMPRESSED_ = 0x00000800;
+const DWORD_ FILE_ATTRIBUTE_OFFLINE_ = 0x00001000;
+const DWORD_ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED_ = 0x00002000;
+const DWORD_ FILE_ATTRIBUTE_ENCRYPTED_ = 0x00004000;
+
+const DWORD_ CREATE_NEW_ = 1;
+const DWORD_ CREATE_ALWAYS_ = 2;
+const DWORD_ OPEN_EXISTING_ = 3;
+const DWORD_ OPEN_ALWAYS_ = 4;
+const DWORD_ TRUNCATE_EXISTING_ = 5;
+
+const DWORD_ FILE_SHARE_READ_ = 0x00000001;
+const DWORD_ FILE_SHARE_WRITE_ = 0x00000002;
+const DWORD_ FILE_SHARE_DELETE_ = 0x00000004;
+
+const DWORD_ FILE_BEGIN_ = 0;
+const DWORD_ FILE_CURRENT_ = 1;
+const DWORD_ FILE_END_ = 2;
+
+#endif // defined( BOOST_USE_WINDOWS_H )
+
+// This constant is not defined in Windows SDK up until 6.0A
+const DWORD_ FILE_ATTRIBUTE_VIRTUAL_ = 0x00010000;
+
+// These constants are not defined in Windows SDK up until 8.0 and MinGW/MinGW-w64 (as of 2016-02-14).
+// They are documented to be supported only since Windows 8/Windows Server 2012
+// but defined unconditionally.
+const DWORD_ FILE_ATTRIBUTE_INTEGRITY_STREAM_ = 0x00008000;
+const DWORD_ FILE_ATTRIBUTE_NO_SCRUB_DATA_ = 0x00020000;
+// Undocumented
+const DWORD_ FILE_ATTRIBUTE_EA_ = 0x00040000;
+
#if !defined( BOOST_NO_ANSI_APIS )
using ::DeleteFileA;
using ::MoveFileExA;
+using ::GetFileAttributesA;
+using ::AreFileApisANSI;
#endif
using ::DeleteFileW;
using ::MoveFileExW;
+using ::GetFileAttributesW;
using ::FindClose;
@@ -157,19 +261,8 @@ using ::SetFileValidData;
using ::SetEndOfFile;
using ::LockFile;
using ::UnlockFile;
+using ::SetFilePointer;
-typedef struct BOOST_DETAIL_WINAPI_MAY_ALIAS _OVERLAPPED {
- ULONG_PTR_ Internal;
- ULONG_PTR_ InternalHigh;
- union {
- struct {
- DWORD_ Offset;
- DWORD_ OffsetHigh;
- };
- PVOID_ Pointer;
- };
- HANDLE_ hEvent;
-} OVERLAPPED_, *LPOVERLAPPED_;
#if !defined( BOOST_NO_ANSI_APIS )
BOOST_FORCEINLINE HANDLE_ CreateFileA(
@@ -200,8 +293,8 @@ typedef struct BOOST_DETAIL_WINAPI_MAY_ALIAS _WIN32_FIND_DATAA {
DWORD_ nFileSizeLow;
DWORD_ dwReserved0;
DWORD_ dwReserved1;
- CHAR_ cFileName[ 260 ]; // MAX_PATH
- CHAR_ cAlternateFileName[ 14 ];
+ CHAR_ cFileName[MAX_PATH_];
+ CHAR_ cAlternateFileName[14];
#ifdef _MAC
DWORD_ dwFileType;
DWORD_ dwCreatorType;
@@ -248,8 +341,8 @@ typedef struct BOOST_DETAIL_WINAPI_MAY_ALIAS _WIN32_FIND_DATAW {
DWORD_ nFileSizeLow;
DWORD_ dwReserved0;
DWORD_ dwReserved1;
- WCHAR_ cFileName[ 260 ]; // MAX_PATH
- WCHAR_ cAlternateFileName[ 14 ];
+ WCHAR_ cFileName[MAX_PATH_];
+ WCHAR_ cAlternateFileName[14];
#ifdef _MAC
DWORD_ dwFileType;
DWORD_ dwCreatorType;
@@ -303,7 +396,6 @@ BOOST_FORCEINLINE BOOL_ WriteFile(
return ::WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, reinterpret_cast< ::_OVERLAPPED* >(lpOverlapped));
};
-
#if !defined( BOOST_NO_ANSI_APIS )
BOOST_FORCEINLINE HANDLE_ create_file(
LPCSTR_ lpFileName,
@@ -343,6 +435,11 @@ BOOST_FORCEINLINE BOOL_ move_file(LPCSTR_ lpExistingFileName, LPCSTR_ lpNewFileN
{
return ::MoveFileExA(lpExistingFileName, lpNewFileName, dwFlags);
}
+
+BOOST_FORCEINLINE DWORD_ get_file_attributes(LPCSTR_ lpFileName)
+{
+ return ::GetFileAttributesA(lpFileName);
+}
#endif
BOOST_FORCEINLINE HANDLE_ create_file(
@@ -384,6 +481,11 @@ BOOST_FORCEINLINE BOOL_ move_file(LPCWSTR_ lpExistingFileName, LPCWSTR_ lpNewFil
return ::MoveFileExW(lpExistingFileName, lpNewFileName, dwFlags);
}
+BOOST_FORCEINLINE DWORD_ get_file_attributes(LPCWSTR_ lpFileName)
+{
+ return ::GetFileAttributesW(lpFileName);
+}
+
}
}
}
diff --git a/boost/detail/winapi/file_mapping.hpp b/boost/detail/winapi/file_mapping.hpp
index f3cf794b41..38c23d554d 100644
--- a/boost/detail/winapi/file_mapping.hpp
+++ b/boost/detail/winapi/file_mapping.hpp
@@ -2,6 +2,7 @@
// Copyright 2010 Vicente J. Botet Escriba
// Copyright 2015 Andrey Semashev
+// Copyright 2016 Jorge Lodos
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
@@ -51,6 +52,14 @@ OpenFileMappingW(
boost::detail::winapi::LPCWSTR_ lpName);
BOOST_SYMBOL_IMPORT boost::detail::winapi::LPVOID_ WINAPI
+MapViewOfFile(
+ boost::detail::winapi::HANDLE_ hFileMappingObject,
+ boost::detail::winapi::DWORD_ dwDesiredAccess,
+ boost::detail::winapi::DWORD_ dwFileOffsetHigh,
+ boost::detail::winapi::DWORD_ dwFileOffsetLow,
+ boost::detail::winapi::SIZE_T_ dwNumberOfBytesToMap);
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::LPVOID_ WINAPI
MapViewOfFileEx(
boost::detail::winapi::HANDLE_ hFileMappingObject,
boost::detail::winapi::DWORD_ dwDesiredAccess,
@@ -73,10 +82,69 @@ namespace boost {
namespace detail {
namespace winapi {
+#if defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ SEC_FILE_ = SEC_FILE;
+const DWORD_ SEC_IMAGE_ = SEC_IMAGE;
+const DWORD_ SEC_RESERVE_ = SEC_RESERVE;
+const DWORD_ SEC_COMMIT_ = SEC_COMMIT;
+const DWORD_ SEC_NOCACHE_ = SEC_NOCACHE;
+
+// These permission flags are undocumented and some of them are equivalent to the FILE_MAP_* flags.
+// SECTION_QUERY enables NtQuerySection.
+// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FSection%2FNtQuerySection.html
+const DWORD_ SECTION_QUERY_ = SECTION_QUERY;
+const DWORD_ SECTION_MAP_WRITE_ = SECTION_MAP_WRITE;
+const DWORD_ SECTION_MAP_READ_ = SECTION_MAP_READ;
+const DWORD_ SECTION_MAP_EXECUTE_ = SECTION_MAP_EXECUTE;
+const DWORD_ SECTION_EXTEND_SIZE_ = SECTION_EXTEND_SIZE;
+const DWORD_ SECTION_ALL_ACCESS_ = SECTION_ALL_ACCESS;
+
+const DWORD_ FILE_MAP_COPY_ = FILE_MAP_COPY;
+const DWORD_ FILE_MAP_WRITE_ = FILE_MAP_WRITE;
+const DWORD_ FILE_MAP_READ_ = FILE_MAP_READ;
+const DWORD_ FILE_MAP_ALL_ACCESS_ = FILE_MAP_ALL_ACCESS;
+
+#else // defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ SEC_FILE_ = 0x800000;
+const DWORD_ SEC_IMAGE_ = 0x1000000;
+const DWORD_ SEC_RESERVE_ = 0x4000000;
+const DWORD_ SEC_COMMIT_ = 0x8000000;
+const DWORD_ SEC_NOCACHE_ = 0x10000000;
+
+// These permission flags are undocumented and some of them are equivalent to the FILE_MAP_* flags.
+// SECTION_QUERY enables NtQuerySection.
+// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FSection%2FNtQuerySection.html
+const DWORD_ SECTION_QUERY_ = 0x00000001;
+const DWORD_ SECTION_MAP_WRITE_ = 0x00000002;
+const DWORD_ SECTION_MAP_READ_ = 0x00000004;
+const DWORD_ SECTION_MAP_EXECUTE_ = 0x00000008;
+const DWORD_ SECTION_EXTEND_SIZE_ = 0x00000010;
+const DWORD_ SECTION_ALL_ACCESS_ = 0x000F001F; // STANDARD_RIGHTS_REQUIRED | SECTION_*
+
+const DWORD_ FILE_MAP_COPY_ = SECTION_QUERY_;
+const DWORD_ FILE_MAP_WRITE_ = SECTION_MAP_WRITE_;
+const DWORD_ FILE_MAP_READ_ = SECTION_MAP_READ_;
+const DWORD_ FILE_MAP_ALL_ACCESS_ = SECTION_ALL_ACCESS_;
+
+#endif // defined( BOOST_USE_WINDOWS_H )
+
+// These constants are not defined in Windows SDK up until the one shipped with MSVC 8 and MinGW (as of 2016-02-14)
+const DWORD_ SECTION_MAP_EXECUTE_EXPLICIT_ = 0x00000020; // not included in SECTION_ALL_ACCESS
+const DWORD_ FILE_MAP_EXECUTE_ = SECTION_MAP_EXECUTE_EXPLICIT_; // not included in FILE_MAP_ALL_ACCESS
+
+// These constants are not defined in Windows SDK up until 6.0A and MinGW (as of 2016-02-14)
+const DWORD_ SEC_PROTECTED_IMAGE_ = 0x2000000;
+const DWORD_ SEC_WRITECOMBINE_ = 0x40000000;
+const DWORD_ SEC_LARGE_PAGES_ = 0x80000000;
+const DWORD_ SEC_IMAGE_NO_EXECUTE_ = (SEC_IMAGE_ | SEC_NOCACHE_);
+
#if !defined( BOOST_NO_ANSI_APIS )
using ::OpenFileMappingA;
#endif
using ::OpenFileMappingW;
+using ::MapViewOfFile;
using ::MapViewOfFileEx;
using ::FlushViewOfFile;
using ::UnmapViewOfFile;
@@ -102,7 +170,7 @@ BOOST_FORCEINLINE HANDLE_ CreateFileMappingA(
BOOST_FORCEINLINE HANDLE_ CreateFileMappingW(
HANDLE_ hFile,
- ::_SECURITY_ATTRIBUTES* lpFileMappingAttributes,
+ SECURITY_ATTRIBUTES_* lpFileMappingAttributes,
DWORD_ flProtect,
DWORD_ dwMaximumSizeHigh,
DWORD_ dwMaximumSizeLow,
@@ -143,7 +211,7 @@ BOOST_FORCEINLINE HANDLE_ open_file_mapping(DWORD_ dwDesiredAccess, BOOL_ bInher
BOOST_FORCEINLINE HANDLE_ create_file_mapping(
HANDLE_ hFile,
- ::_SECURITY_ATTRIBUTES* lpFileMappingAttributes,
+ SECURITY_ATTRIBUTES_* lpFileMappingAttributes,
DWORD_ flProtect,
DWORD_ dwMaximumSizeHigh,
DWORD_ dwMaximumSizeLow,
diff --git a/boost/detail/winapi/get_current_process.hpp b/boost/detail/winapi/get_current_process.hpp
new file mode 100644
index 0000000000..e5f4f2aaab
--- /dev/null
+++ b/boost/detail/winapi/get_current_process.hpp
@@ -0,0 +1,34 @@
+// get_current_process.hpp --------------------------------------------------------------//
+
+// Copyright 2010 Vicente J. Botet Escriba
+// Copyright 2015 Andrey Semashev
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+
+#ifndef BOOST_DETAIL_WINAPI_GET_CURRENT_PROCESS_HPP
+#define BOOST_DETAIL_WINAPI_GET_CURRENT_PROCESS_HPP
+
+#include <boost/detail/winapi/basic_types.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+// Windows CE define GetCurrentProcess as an inline function in kfuncs.h
+#if !defined( BOOST_USE_WINDOWS_H ) && !defined( UNDER_CE )
+extern "C" {
+BOOST_SYMBOL_IMPORT boost::detail::winapi::HANDLE_ WINAPI GetCurrentProcess(BOOST_DETAIL_WINAPI_VOID);
+}
+#endif
+
+namespace boost {
+namespace detail {
+namespace winapi {
+using ::GetCurrentProcess;
+}
+}
+}
+
+#endif // BOOST_DETAIL_WINAPI_GET_CURRENT_PROCESS_HPP
diff --git a/boost/detail/winapi/get_current_process_id.hpp b/boost/detail/winapi/get_current_process_id.hpp
new file mode 100644
index 0000000000..aa21e6c884
--- /dev/null
+++ b/boost/detail/winapi/get_current_process_id.hpp
@@ -0,0 +1,33 @@
+// get_current_process_id.hpp --------------------------------------------------------------//
+
+// Copyright 2010 Vicente J. Botet Escriba
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+
+#ifndef BOOST_DETAIL_WINAPI_GET_CURRENT_PROCESS_ID_HPP
+#define BOOST_DETAIL_WINAPI_GET_CURRENT_PROCESS_ID_HPP
+
+#include <boost/detail/winapi/basic_types.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+// Windows CE define GetCurrentProcessId as an inline function in kfuncs.h
+#if !defined( BOOST_USE_WINDOWS_H ) && !defined( UNDER_CE )
+extern "C" {
+BOOST_SYMBOL_IMPORT boost::detail::winapi::DWORD_ WINAPI GetCurrentProcessId(BOOST_DETAIL_WINAPI_VOID);
+}
+#endif
+
+namespace boost {
+namespace detail {
+namespace winapi {
+using ::GetCurrentProcessId;
+}
+}
+}
+
+#endif // BOOST_DETAIL_WINAPI_GET_CURRENT_PROCESS_ID_HPP
diff --git a/boost/detail/winapi/get_current_thread.hpp b/boost/detail/winapi/get_current_thread.hpp
new file mode 100644
index 0000000000..b52c3a8c19
--- /dev/null
+++ b/boost/detail/winapi/get_current_thread.hpp
@@ -0,0 +1,34 @@
+// get_current_thread.hpp --------------------------------------------------------------//
+
+// Copyright 2010 Vicente J. Botet Escriba
+// Copyright 2015 Andrey Semashev
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+
+#ifndef BOOST_DETAIL_WINAPI_GET_CURRENT_THREAD_HPP
+#define BOOST_DETAIL_WINAPI_GET_CURRENT_THREAD_HPP
+
+#include <boost/detail/winapi/basic_types.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+// Windows CE define GetCurrentThread as an inline function in kfuncs.h
+#if !defined( BOOST_USE_WINDOWS_H ) && !defined( UNDER_CE )
+extern "C" {
+BOOST_SYMBOL_IMPORT boost::detail::winapi::HANDLE_ WINAPI GetCurrentThread(BOOST_DETAIL_WINAPI_VOID);
+}
+#endif
+
+namespace boost {
+namespace detail {
+namespace winapi {
+using ::GetCurrentThread;
+}
+}
+}
+
+#endif // BOOST_DETAIL_WINAPI_GET_CURRENT_THREAD_HPP
diff --git a/boost/detail/winapi/get_current_thread_id.hpp b/boost/detail/winapi/get_current_thread_id.hpp
new file mode 100644
index 0000000000..198af3bf71
--- /dev/null
+++ b/boost/detail/winapi/get_current_thread_id.hpp
@@ -0,0 +1,34 @@
+// get_current_thread_id.hpp --------------------------------------------------------------//
+
+// Copyright 2010 Vicente J. Botet Escriba
+// Copyright 2015 Andrey Semashev
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+
+#ifndef BOOST_DETAIL_WINAPI_GET_CURRENT_THREAD_ID_HPP
+#define BOOST_DETAIL_WINAPI_GET_CURRENT_THREAD_ID_HPP
+
+#include <boost/detail/winapi/basic_types.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+// Windows CE define GetCurrentThreadId as an inline function in kfuncs.h
+#if !defined( BOOST_USE_WINDOWS_H ) && !defined( UNDER_CE )
+extern "C" {
+BOOST_SYMBOL_IMPORT boost::detail::winapi::DWORD_ WINAPI GetCurrentThreadId(BOOST_DETAIL_WINAPI_VOID);
+}
+#endif
+
+namespace boost {
+namespace detail {
+namespace winapi {
+using ::GetCurrentThreadId;
+}
+}
+}
+
+#endif // BOOST_DETAIL_WINAPI_GET_CURRENT_THREAD_ID_HPP
diff --git a/boost/detail/winapi/get_last_error.hpp b/boost/detail/winapi/get_last_error.hpp
new file mode 100644
index 0000000000..543efaf9a0
--- /dev/null
+++ b/boost/detail/winapi/get_last_error.hpp
@@ -0,0 +1,33 @@
+// get_last_error.hpp --------------------------------------------------------------//
+
+// Copyright 2010 Vicente J. Botet Escriba
+// Copyright 2015 Andrey Semashev
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+
+#ifndef BOOST_DETAIL_WINAPI_GET_LAST_ERROR_HPP
+#define BOOST_DETAIL_WINAPI_GET_LAST_ERROR_HPP
+
+#include <boost/detail/winapi/basic_types.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if !defined( BOOST_USE_WINDOWS_H )
+extern "C" {
+BOOST_SYMBOL_IMPORT boost::detail::winapi::DWORD_ WINAPI GetLastError(BOOST_DETAIL_WINAPI_VOID);
+}
+#endif
+
+namespace boost {
+namespace detail {
+namespace winapi {
+using ::GetLastError;
+}
+}
+}
+
+#endif // BOOST_DETAIL_WINAPI_GET_LAST_ERROR_HPP
diff --git a/boost/detail/winapi/get_process_times.hpp b/boost/detail/winapi/get_process_times.hpp
new file mode 100644
index 0000000000..a79eeb0128
--- /dev/null
+++ b/boost/detail/winapi/get_process_times.hpp
@@ -0,0 +1,60 @@
+// get_process_times.hpp --------------------------------------------------------------//
+
+// Copyright 2010 Vicente J. Botet Escriba
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+
+#ifndef BOOST_DETAIL_WINAPI_GET_PROCESS_TIMES_HPP
+#define BOOST_DETAIL_WINAPI_GET_PROCESS_TIMES_HPP
+
+#include <boost/detail/winapi/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+// Windows CE does not define GetProcessTimes
+#if !defined( UNDER_CE )
+
+#include <boost/detail/winapi/basic_types.hpp>
+#include <boost/detail/winapi/time.hpp>
+
+#if !defined( BOOST_USE_WINDOWS_H )
+extern "C" {
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI
+GetProcessTimes(
+ boost::detail::winapi::HANDLE_ hProcess,
+ ::_FILETIME* lpCreationTime,
+ ::_FILETIME* lpExitTime,
+ ::_FILETIME* lpKernelTime,
+ ::_FILETIME* lpUserTime);
+}
+#endif
+
+namespace boost {
+namespace detail {
+namespace winapi {
+
+BOOST_FORCEINLINE BOOL_ GetProcessTimes(
+ HANDLE_ hProcess,
+ LPFILETIME_ lpCreationTime,
+ LPFILETIME_ lpExitTime,
+ LPFILETIME_ lpKernelTime,
+ LPFILETIME_ lpUserTime)
+{
+ return ::GetProcessTimes(
+ hProcess,
+ reinterpret_cast< ::_FILETIME* >(lpCreationTime),
+ reinterpret_cast< ::_FILETIME* >(lpExitTime),
+ reinterpret_cast< ::_FILETIME* >(lpKernelTime),
+ reinterpret_cast< ::_FILETIME* >(lpUserTime));
+}
+
+}
+}
+}
+
+#endif // !defined( UNDER_CE )
+#endif // BOOST_DETAIL_WINAPI_GET_PROCESS_TIMES_HPP
diff --git a/boost/detail/winapi/get_system_directory.hpp b/boost/detail/winapi/get_system_directory.hpp
new file mode 100644
index 0000000000..dd2d6807ce
--- /dev/null
+++ b/boost/detail/winapi/get_system_directory.hpp
@@ -0,0 +1,63 @@
+// get_system_directory.hpp --------------------------------------------------------------//
+
+// Copyright 2016 Klemens D. Morgenstern
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_DETAIL_WINAPI_GET_SYSTEM_DIRECTORY_HPP_
+#define BOOST_DETAIL_WINAPI_GET_SYSTEM_DIRECTORY_HPP_
+
+#include <boost/detail/winapi/basic_types.hpp>
+#include <boost/predef/platform.h>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if BOOST_PLAT_WINDOWS_DESKTOP
+
+#if !defined( BOOST_USE_WINDOWS_H )
+extern "C" {
+#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_SYMBOL_IMPORT boost::detail::winapi::UINT_ WINAPI
+GetSystemDirectoryA(
+ boost::detail::winapi::LPSTR_ lpBuffer,
+ boost::detail::winapi::UINT_ uSize);
+#endif
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::UINT_ WINAPI
+GetSystemDirectoryW(
+ boost::detail::winapi::LPWSTR_ lpBuffer,
+ boost::detail::winapi::UINT_ uSize);
+} // extern "C"
+#endif
+
+namespace boost {
+namespace detail {
+namespace winapi {
+
+#if !defined( BOOST_NO_ANSI_APIS )
+using ::GetSystemDirectoryA;
+#endif
+using ::GetSystemDirectoryW;
+
+#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_FORCEINLINE UINT_ get_system_directory(LPSTR_ lpBuffer, UINT_ uSize)
+{
+ return ::GetSystemDirectoryA(lpBuffer, uSize);
+}
+#endif
+
+BOOST_FORCEINLINE UINT_ get_system_directory(LPWSTR_ lpBuffer, UINT_ uSize)
+{
+ return ::GetSystemDirectoryW(lpBuffer, uSize);
+}
+
+}
+}
+}
+
+#endif // BOOST_PLAT_WINDOWS_DESKTOP
+
+#endif // BOOST_DETAIL_WINAPI_GET_SYSTEM_DIRECTORY_HPP_
diff --git a/boost/detail/winapi/get_thread_times.hpp b/boost/detail/winapi/get_thread_times.hpp
new file mode 100644
index 0000000000..13308d84da
--- /dev/null
+++ b/boost/detail/winapi/get_thread_times.hpp
@@ -0,0 +1,55 @@
+// get_thread_times.hpp --------------------------------------------------------------//
+
+// Copyright 2010 Vicente J. Botet Escriba
+// Copyright 2015 Andrey Semashev
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+
+#ifndef BOOST_DETAIL_WINAPI_GET_THREAD_TIMES_HPP
+#define BOOST_DETAIL_WINAPI_GET_THREAD_TIMES_HPP
+
+#include <boost/detail/winapi/basic_types.hpp>
+#include <boost/detail/winapi/time.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if !defined( BOOST_USE_WINDOWS_H )
+extern "C" {
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI
+GetThreadTimes(
+ boost::detail::winapi::HANDLE_ hThread,
+ ::_FILETIME* lpCreationTime,
+ ::_FILETIME* lpExitTime,
+ ::_FILETIME* lpKernelTime,
+ ::_FILETIME* lpUserTime);
+}
+#endif
+
+namespace boost {
+namespace detail {
+namespace winapi {
+
+BOOST_FORCEINLINE BOOL_ GetThreadTimes(
+ HANDLE_ hThread,
+ LPFILETIME_ lpCreationTime,
+ LPFILETIME_ lpExitTime,
+ LPFILETIME_ lpKernelTime,
+ LPFILETIME_ lpUserTime)
+{
+ return ::GetThreadTimes(
+ hThread,
+ reinterpret_cast< ::_FILETIME* >(lpCreationTime),
+ reinterpret_cast< ::_FILETIME* >(lpExitTime),
+ reinterpret_cast< ::_FILETIME* >(lpKernelTime),
+ reinterpret_cast< ::_FILETIME* >(lpUserTime));
+}
+
+}
+}
+}
+
+#endif // BOOST_DETAIL_WINAPI_GET_THREAD_TIMES_HPP
diff --git a/boost/detail/winapi/handle_info.hpp b/boost/detail/winapi/handle_info.hpp
new file mode 100644
index 0000000000..0fdcb25c98
--- /dev/null
+++ b/boost/detail/winapi/handle_info.hpp
@@ -0,0 +1,62 @@
+// handle_info.hpp --------------------------------------------------------------//
+
+// Copyright 2016 Klemens D. Morgenstern
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_DETAIL_HANDLE_INFO_HPP_
+#define BOOST_DETAIL_HANDLE_INFO_HPP_
+
+#include <boost/detail/winapi/basic_types.hpp>
+#include <boost/predef/platform.h>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if BOOST_PLAT_WINDOWS_DESKTOP
+
+#if !defined( BOOST_USE_WINDOWS_H )
+extern "C" {
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI
+GetHandleInformation(
+ boost::detail::winapi::HANDLE_ hObject,
+ boost::detail::winapi::LPDWORD_ lpdwFlags);
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI
+SetHandleInformation(
+ boost::detail::winapi::HANDLE_ hObject,
+ boost::detail::winapi::DWORD_ dwMask,
+ boost::detail::winapi::DWORD_ dwFlags);
+
+} // extern "C"
+#endif
+
+namespace boost {
+namespace detail {
+namespace winapi {
+
+using ::GetHandleInformation;
+using ::SetHandleInformation;
+
+#if defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ HANDLE_FLAG_INHERIT_ = HANDLE_FLAG_INHERIT;
+const DWORD_ HANDLE_FLAG_PROTECT_FROM_CLOSE_ = HANDLE_FLAG_PROTECT_FROM_CLOSE;
+
+#else
+
+const DWORD_ HANDLE_FLAG_INHERIT_ = 0x1;
+const DWORD_ HANDLE_FLAG_PROTECT_FROM_CLOSE_ = 0x2;
+
+#endif
+
+}
+}
+}
+
+#endif // BOOST_PLAT_WINDOWS_DESKTOP
+
+#endif // BOOST_DETAIL_HANDLE_INFO_HPP_
diff --git a/boost/detail/winapi/limits.hpp b/boost/detail/winapi/limits.hpp
new file mode 100644
index 0000000000..1a0faaa544
--- /dev/null
+++ b/boost/detail/winapi/limits.hpp
@@ -0,0 +1,51 @@
+// limits.hpp --------------------------------------------------------------//
+
+// Copyright 2016 Andrey Semashev
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_DETAIL_WINAPI_LIMITS_HPP_
+#define BOOST_DETAIL_WINAPI_LIMITS_HPP_
+
+#include <boost/detail/winapi/basic_types.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+namespace detail {
+namespace winapi {
+
+#if defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ MAX_PATH_ = MAX_PATH;
+
+#else
+
+const DWORD_ MAX_PATH_ = 260;
+
+#endif
+
+#if defined( BOOST_USE_WINDOWS_H ) && !defined( BOOST_WINAPI_IS_MINGW )
+
+const DWORD_ UNICODE_STRING_MAX_BYTES_ = UNICODE_STRING_MAX_BYTES;
+const DWORD_ UNICODE_STRING_MAX_CHARS_ = UNICODE_STRING_MAX_CHARS;
+
+#else
+
+const DWORD_ UNICODE_STRING_MAX_BYTES_ = 65534;
+const DWORD_ UNICODE_STRING_MAX_CHARS_ = 32767;
+
+#endif
+
+const DWORD_ max_path = MAX_PATH_;
+const DWORD_ unicode_string_max_bytes = UNICODE_STRING_MAX_BYTES_;
+const DWORD_ unicode_string_max_chars = UNICODE_STRING_MAX_CHARS_;
+
+}
+}
+}
+
+#endif // BOOST_DETAIL_WINAPI_LIMITS_HPP_
diff --git a/boost/detail/winapi/mutex.hpp b/boost/detail/winapi/mutex.hpp
index 8f1975ca5c..37b21a444c 100644
--- a/boost/detail/winapi/mutex.hpp
+++ b/boost/detail/winapi/mutex.hpp
@@ -85,13 +85,15 @@ using ::ReleaseMutex;
#if defined( BOOST_USE_WINDOWS_H )
const DWORD_ MUTEX_ALL_ACCESS_ = MUTEX_ALL_ACCESS;
+const DWORD_ MUTEX_MODIFY_STATE_ = MUTEX_MODIFY_STATE;
#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
const DWORD_ CREATE_MUTEX_INITIAL_OWNER_ = CREATE_MUTEX_INITIAL_OWNER;
#endif
#else // defined( BOOST_USE_WINDOWS_H )
-const DWORD_ MUTEX_ALL_ACCESS_ = 0x1F0001;
+const DWORD_ MUTEX_ALL_ACCESS_ = 0x001F0001;
+const DWORD_ MUTEX_MODIFY_STATE_ = 0x00000001;
#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
const DWORD_ CREATE_MUTEX_INITIAL_OWNER_ = 0x00000001;
#endif
@@ -99,6 +101,7 @@ const DWORD_ CREATE_MUTEX_INITIAL_OWNER_ = 0x00000001;
#endif // defined( BOOST_USE_WINDOWS_H )
const DWORD_ mutex_all_access = MUTEX_ALL_ACCESS_;
+const DWORD_ mutex_modify_state = MUTEX_MODIFY_STATE_;
#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
const DWORD_ create_mutex_initial_owner = CREATE_MUTEX_INITIAL_OWNER_;
#endif
diff --git a/boost/detail/winapi/overlapped.hpp b/boost/detail/winapi/overlapped.hpp
new file mode 100644
index 0000000000..17dcb2e079
--- /dev/null
+++ b/boost/detail/winapi/overlapped.hpp
@@ -0,0 +1,51 @@
+// overlapped.hpp --------------------------------------------------------------//
+
+// Copyright 2016 Klemens D. Morgenstern
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_DETAIL_WINAPI_OVERLAPPED_HPP_
+#define BOOST_DETAIL_WINAPI_OVERLAPPED_HPP_
+
+#include <boost/detail/winapi/basic_types.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if !defined( BOOST_USE_WINDOWS_H )
+extern "C" {
+struct _OVERLAPPED;
+}
+#endif
+
+namespace boost {
+namespace detail {
+namespace winapi {
+
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4201) // nonstandard extension used : nameless struct/union
+#endif
+
+typedef struct BOOST_DETAIL_WINAPI_MAY_ALIAS _OVERLAPPED {
+ ULONG_PTR_ Internal;
+ ULONG_PTR_ InternalHigh;
+ union {
+ struct {
+ DWORD_ Offset;
+ DWORD_ OffsetHigh;
+ };
+ PVOID_ Pointer;
+ };
+ HANDLE_ hEvent;
+} OVERLAPPED_, *LPOVERLAPPED_;
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+}}}
+
+#endif // BOOST_DETAIL_WINAPI_OVERLAPPED_HPP_
diff --git a/boost/detail/winapi/page_protection_flags.hpp b/boost/detail/winapi/page_protection_flags.hpp
new file mode 100644
index 0000000000..0dbcb2110b
--- /dev/null
+++ b/boost/detail/winapi/page_protection_flags.hpp
@@ -0,0 +1,56 @@
+// page_protection_flags.hpp --------------------------------------------------------------//
+
+// Copyright 2016 Andrey Semashev
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+
+#ifndef BOOST_DETAIL_WINAPI_PAGE_PROTECTION_FLAGS_HPP
+#define BOOST_DETAIL_WINAPI_PAGE_PROTECTION_FLAGS_HPP
+
+#include <boost/detail/winapi/basic_types.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+namespace detail {
+namespace winapi {
+
+#if defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ PAGE_NOACCESS_ = PAGE_NOACCESS;
+const DWORD_ PAGE_READONLY_ = PAGE_READONLY;
+const DWORD_ PAGE_READWRITE_ = PAGE_READWRITE;
+const DWORD_ PAGE_WRITECOPY_ = PAGE_WRITECOPY;
+const DWORD_ PAGE_EXECUTE_ = PAGE_EXECUTE;
+const DWORD_ PAGE_EXECUTE_READ_ = PAGE_EXECUTE_READ;
+const DWORD_ PAGE_EXECUTE_READWRITE_ = PAGE_EXECUTE_READWRITE;
+const DWORD_ PAGE_EXECUTE_WRITECOPY_ = PAGE_EXECUTE_WRITECOPY;
+const DWORD_ PAGE_GUARD_ = PAGE_GUARD;
+const DWORD_ PAGE_NOCACHE_ = PAGE_NOCACHE;
+const DWORD_ PAGE_WRITECOMBINE_ = PAGE_WRITECOMBINE;
+
+#else // defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ PAGE_NOACCESS_ = 0x01;
+const DWORD_ PAGE_READONLY_ = 0x02;
+const DWORD_ PAGE_READWRITE_ = 0x04;
+const DWORD_ PAGE_WRITECOPY_ = 0x08;
+const DWORD_ PAGE_EXECUTE_ = 0x10;
+const DWORD_ PAGE_EXECUTE_READ_ = 0x20;
+const DWORD_ PAGE_EXECUTE_READWRITE_ = 0x40;
+const DWORD_ PAGE_EXECUTE_WRITECOPY_ = 0x80;
+const DWORD_ PAGE_GUARD_ = 0x100;
+const DWORD_ PAGE_NOCACHE_ = 0x200;
+const DWORD_ PAGE_WRITECOMBINE_ = 0x400;
+
+#endif // defined( BOOST_USE_WINDOWS_H )
+
+}
+}
+}
+
+#endif // BOOST_DETAIL_WINAPI_PAGE_PROTECTION_FLAGS_HPP
diff --git a/boost/detail/winapi/pipes.hpp b/boost/detail/winapi/pipes.hpp
new file mode 100644
index 0000000000..147295054f
--- /dev/null
+++ b/boost/detail/winapi/pipes.hpp
@@ -0,0 +1,317 @@
+// pipes.hpp --------------------------------------------------------------//
+
+// Copyright 2016 Klemens D. Morgenstern
+// Copyright 2016 Andrey Semashev
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_DETAIL_WINAPI_PIPES_HPP_
+#define BOOST_DETAIL_WINAPI_PIPES_HPP_
+
+#include <boost/detail/winapi/basic_types.hpp>
+#include <boost/detail/winapi/config.hpp>
+#include <boost/detail/winapi/overlapped.hpp>
+#include <boost/predef/platform.h>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if BOOST_PLAT_WINDOWS_DESKTOP
+
+#if !defined( BOOST_USE_WINDOWS_H )
+extern "C" {
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI ImpersonateNamedPipeClient(
+ boost::detail::winapi::HANDLE_ hNamedPipe);
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI CreatePipe(
+ boost::detail::winapi::PHANDLE_ hReadPipe,
+ boost::detail::winapi::PHANDLE_ hWritePipe,
+ _SECURITY_ATTRIBUTES* lpPipeAttributes,
+ boost::detail::winapi::DWORD_ nSize);
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI ConnectNamedPipe(
+ boost::detail::winapi::HANDLE_ hNamedPipe,
+ _OVERLAPPED* lpOverlapped);
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI DisconnectNamedPipe(
+ boost::detail::winapi::HANDLE_ hNamedPipe);
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI SetNamedPipeHandleState(
+ boost::detail::winapi::HANDLE_ hNamedPipe,
+ boost::detail::winapi::LPDWORD_ lpMode,
+ boost::detail::winapi::LPDWORD_ lpMaxCollectionCount,
+ boost::detail::winapi::LPDWORD_ lpCollectDataTimeout);
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI PeekNamedPipe(
+ boost::detail::winapi::HANDLE_ hNamedPipe,
+ boost::detail::winapi::LPVOID_ lpBuffer,
+ boost::detail::winapi::DWORD_ nBufferSize,
+ boost::detail::winapi::LPDWORD_ lpBytesRead,
+ boost::detail::winapi::LPDWORD_ lpTotalBytesAvail,
+ boost::detail::winapi::LPDWORD_ lpBytesLeftThisMessage);
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI TransactNamedPipe(
+ boost::detail::winapi::HANDLE_ hNamedPipe,
+ boost::detail::winapi::LPVOID_ lpInBuffer,
+ boost::detail::winapi::DWORD_ nInBufferSize,
+ boost::detail::winapi::LPVOID_ lpOutBuffer,
+ boost::detail::winapi::DWORD_ nOutBufferSize,
+ boost::detail::winapi::LPDWORD_ lpBytesRead,
+ _OVERLAPPED* lpOverlapped);
+
+#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_SYMBOL_IMPORT boost::detail::winapi::HANDLE_ WINAPI CreateNamedPipeA(
+ boost::detail::winapi::LPCSTR_ lpName,
+ boost::detail::winapi::DWORD_ dwOpenMode,
+ boost::detail::winapi::DWORD_ dwPipeMode,
+ boost::detail::winapi::DWORD_ nMaxInstances,
+ boost::detail::winapi::DWORD_ nOutBufferSize,
+ boost::detail::winapi::DWORD_ nInBufferSize,
+ boost::detail::winapi::DWORD_ nDefaultTimeOut,
+ _SECURITY_ATTRIBUTES *lpSecurityAttributes);
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI WaitNamedPipeA(
+ boost::detail::winapi::LPCSTR_ lpNamedPipeName,
+ boost::detail::winapi::DWORD_ nTimeOut);
+#endif // !defined( BOOST_NO_ANSI_APIS )
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::HANDLE_ WINAPI CreateNamedPipeW(
+ boost::detail::winapi::LPCWSTR_ lpName,
+ boost::detail::winapi::DWORD_ dwOpenMode,
+ boost::detail::winapi::DWORD_ dwPipeMode,
+ boost::detail::winapi::DWORD_ nMaxInstances,
+ boost::detail::winapi::DWORD_ nOutBufferSize,
+ boost::detail::winapi::DWORD_ nInBufferSize,
+ boost::detail::winapi::DWORD_ nDefaultTimeOut,
+ _SECURITY_ATTRIBUTES* lpSecurityAttributes);
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI WaitNamedPipeW(
+ boost::detail::winapi::LPCWSTR_ lpNamedPipeName,
+ boost::detail::winapi::DWORD_ nTimeOut);
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI GetNamedPipeClientComputerNameA(
+ boost::detail::winapi::HANDLE_ Pipe,
+ boost::detail::winapi::LPSTR_ ClientComputerName,
+ boost::detail::winapi::ULONG_ ClientComputerNameLength);
+#endif // !defined( BOOST_NO_ANSI_APIS )
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI GetNamedPipeClientComputerNameW(
+ boost::detail::winapi::HANDLE_ Pipe,
+ boost::detail::winapi::LPWSTR_ ClientComputerName,
+ boost::detail::winapi::ULONG_ ClientComputerNameLength);
+#endif
+
+} // extern "C"
+#endif // !defined( BOOST_USE_WINDOWS_H )
+
+namespace boost {
+namespace detail {
+namespace winapi {
+
+#if defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ PIPE_ACCESS_DUPLEX_ = PIPE_ACCESS_DUPLEX;
+const DWORD_ PIPE_ACCESS_INBOUND_ = PIPE_ACCESS_INBOUND;
+const DWORD_ PIPE_ACCESS_OUTBOUND_ = PIPE_ACCESS_OUTBOUND;
+
+const DWORD_ PIPE_TYPE_BYTE_ = PIPE_TYPE_BYTE;
+const DWORD_ PIPE_TYPE_MESSAGE_ = PIPE_TYPE_MESSAGE;
+
+const DWORD_ PIPE_READMODE_BYTE_ = PIPE_READMODE_BYTE;
+const DWORD_ PIPE_READMODE_MESSAGE_ = PIPE_READMODE_MESSAGE;
+
+const DWORD_ PIPE_WAIT_ = PIPE_WAIT;
+const DWORD_ PIPE_NOWAIT_ = PIPE_NOWAIT;
+
+const DWORD_ PIPE_UNLIMITED_INSTANCES_ = PIPE_UNLIMITED_INSTANCES;
+
+const DWORD_ NMPWAIT_USE_DEFAULT_WAIT_ = NMPWAIT_USE_DEFAULT_WAIT;
+const DWORD_ NMPWAIT_NOWAIT_ = NMPWAIT_NOWAIT;
+const DWORD_ NMPWAIT_WAIT_FOREVER_ = NMPWAIT_WAIT_FOREVER;
+
+#else // defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ PIPE_ACCESS_DUPLEX_ = 0x00000003;
+const DWORD_ PIPE_ACCESS_INBOUND_ = 0x00000001;
+const DWORD_ PIPE_ACCESS_OUTBOUND_ = 0x00000002;
+
+const DWORD_ PIPE_TYPE_BYTE_ = 0x00000000;
+const DWORD_ PIPE_TYPE_MESSAGE_ = 0x00000004;
+
+const DWORD_ PIPE_READMODE_BYTE_ = 0x00000000;
+const DWORD_ PIPE_READMODE_MESSAGE_ = 0x00000002;
+
+const DWORD_ PIPE_WAIT_ = 0x00000000;
+const DWORD_ PIPE_NOWAIT_ = 0x00000001;
+
+const DWORD_ PIPE_UNLIMITED_INSTANCES_ = 255u;
+
+const DWORD_ NMPWAIT_USE_DEFAULT_WAIT_ = 0x00000000;
+const DWORD_ NMPWAIT_NOWAIT_ = 0x00000001;
+const DWORD_ NMPWAIT_WAIT_FOREVER_ = 0xFFFFFFFF;
+
+#endif // defined( BOOST_USE_WINDOWS_H )
+
+// These constants are not defined in Windows SDK prior to 7.0A
+const DWORD_ PIPE_ACCEPT_REMOTE_CLIENTS_ = 0x00000000;
+const DWORD_ PIPE_REJECT_REMOTE_CLIENTS_ = 0x00000008;
+
+using ::ImpersonateNamedPipeClient;
+using ::DisconnectNamedPipe;
+using ::SetNamedPipeHandleState;
+using ::PeekNamedPipe;
+
+#if !defined( BOOST_NO_ANSI_APIS )
+using ::WaitNamedPipeA;
+#endif
+using ::WaitNamedPipeW;
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+#if !defined( BOOST_NO_ANSI_APIS )
+using ::GetNamedPipeClientComputerNameA;
+#endif // !defined( BOOST_NO_ANSI_APIS )
+using ::GetNamedPipeClientComputerNameW;
+#endif // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+
+BOOST_FORCEINLINE BOOL_ CreatePipe(PHANDLE_ hReadPipe, PHANDLE_ hWritePipe, LPSECURITY_ATTRIBUTES_ lpPipeAttributes, DWORD_ nSize)
+{
+ return ::CreatePipe(hReadPipe, hWritePipe, reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpPipeAttributes), nSize);
+}
+
+BOOST_FORCEINLINE BOOL_ ConnectNamedPipe(HANDLE_ hNamedPipe, LPOVERLAPPED_ lpOverlapped)
+{
+ return ::ConnectNamedPipe(hNamedPipe, reinterpret_cast< ::_OVERLAPPED* >(lpOverlapped));
+}
+
+BOOST_FORCEINLINE BOOL_ TransactNamedPipe(HANDLE_ hNamedPipe, LPVOID_ lpInBuffer, DWORD_ nInBufferSize, LPVOID_ lpOutBuffer, DWORD_ nOutBufferSize, LPDWORD_ lpBytesRead, LPOVERLAPPED_ lpOverlapped)
+{
+ return ::TransactNamedPipe(hNamedPipe, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesRead, reinterpret_cast< ::_OVERLAPPED* >(lpOverlapped));
+}
+
+
+#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_FORCEINLINE HANDLE_ CreateNamedPipeA(
+ LPCSTR_ lpName,
+ DWORD_ dwOpenMode,
+ DWORD_ dwPipeMode,
+ DWORD_ nMaxInstances,
+ DWORD_ nOutBufferSize,
+ DWORD_ nInBufferSize,
+ DWORD_ nDefaultTimeOut,
+ LPSECURITY_ATTRIBUTES_ lpSecurityAttributes)
+{
+ return ::CreateNamedPipeA(
+ lpName,
+ dwOpenMode,
+ dwPipeMode,
+ nMaxInstances,
+ nOutBufferSize,
+ nInBufferSize,
+ nDefaultTimeOut,
+ reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpSecurityAttributes));
+}
+
+BOOST_FORCEINLINE HANDLE_ create_named_pipe(
+ LPCSTR_ lpName,
+ DWORD_ dwOpenMode,
+ DWORD_ dwPipeMode,
+ DWORD_ nMaxInstances,
+ DWORD_ nOutBufferSize,
+ DWORD_ nInBufferSize,
+ DWORD_ nDefaultTimeOut,
+ LPSECURITY_ATTRIBUTES_ lpSecurityAttributes)
+{
+ return ::CreateNamedPipeA(
+ lpName,
+ dwOpenMode,
+ dwPipeMode,
+ nMaxInstances,
+ nOutBufferSize,
+ nInBufferSize,
+ nDefaultTimeOut,
+ reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpSecurityAttributes));
+}
+#endif // !defined( BOOST_NO_ANSI_APIS )
+
+BOOST_FORCEINLINE HANDLE_ CreateNamedPipeW(
+ LPCWSTR_ lpName,
+ DWORD_ dwOpenMode,
+ DWORD_ dwPipeMode,
+ DWORD_ nMaxInstances,
+ DWORD_ nOutBufferSize,
+ DWORD_ nInBufferSize,
+ DWORD_ nDefaultTimeOut,
+ LPSECURITY_ATTRIBUTES_ lpSecurityAttributes)
+{
+ return ::CreateNamedPipeW(
+ lpName,
+ dwOpenMode,
+ dwPipeMode,
+ nMaxInstances,
+ nOutBufferSize,
+ nInBufferSize,
+ nDefaultTimeOut,
+ reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpSecurityAttributes));
+}
+
+BOOST_FORCEINLINE HANDLE_ create_named_pipe(
+ LPCWSTR_ lpName,
+ DWORD_ dwOpenMode,
+ DWORD_ dwPipeMode,
+ DWORD_ nMaxInstances,
+ DWORD_ nOutBufferSize,
+ DWORD_ nInBufferSize,
+ DWORD_ nDefaultTimeOut,
+ LPSECURITY_ATTRIBUTES_ lpSecurityAttributes)
+{
+ return ::CreateNamedPipeW(
+ lpName,
+ dwOpenMode,
+ dwPipeMode,
+ nMaxInstances,
+ nOutBufferSize,
+ nInBufferSize,
+ nDefaultTimeOut,
+ reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpSecurityAttributes));
+}
+
+#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_FORCEINLINE BOOL_ wait_named_pipe(LPCSTR_ lpNamedPipeName, DWORD_ nTimeOut)
+{
+ return ::WaitNamedPipeA(lpNamedPipeName, nTimeOut);
+}
+#endif //BOOST_NO_ANSI_APIS
+
+BOOST_FORCEINLINE BOOL_ wait_named_pipe(LPCWSTR_ lpNamedPipeName, DWORD_ nTimeOut)
+{
+ return ::WaitNamedPipeW(lpNamedPipeName, nTimeOut);
+}
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+
+#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_FORCEINLINE BOOL_ get_named_pipe_client_computer_name(HANDLE_ Pipe, LPSTR_ ClientComputerName, ULONG_ ClientComputerNameLength)
+{
+ return ::GetNamedPipeClientComputerNameA(Pipe, ClientComputerName, ClientComputerNameLength);
+}
+#endif // !defined( BOOST_NO_ANSI_APIS )
+
+BOOST_FORCEINLINE BOOL_ get_named_pipe_client_computer_name(HANDLE_ Pipe, LPWSTR_ ClientComputerName, ULONG_ ClientComputerNameLength)
+{
+ return ::GetNamedPipeClientComputerNameW(Pipe, ClientComputerName, ClientComputerNameLength);
+}
+
+#endif // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+
+}
+}
+}
+
+#endif // BOOST_PLAT_WINDOWS_DESKTOP
+
+#endif // BOOST_DETAIL_WINAPI_PIPES_HPP_
diff --git a/boost/detail/winapi/priority_class.hpp b/boost/detail/winapi/priority_class.hpp
new file mode 100644
index 0000000000..bfcb425a8b
--- /dev/null
+++ b/boost/detail/winapi/priority_class.hpp
@@ -0,0 +1,78 @@
+// priority_class.hpp --------------------------------------------------------------//
+
+// Copyright 2016 Klemens D. Morgenstern
+// Copyright 2016 Andrey Semashev
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_DETAIL_WINAPI_PRIORITY_CLASS_HPP_
+#define BOOST_DETAIL_WINAPI_PRIORITY_CLASS_HPP_
+
+#include <boost/detail/winapi/basic_types.hpp>
+#include <boost/predef/platform.h>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if BOOST_PLAT_WINDOWS_DESKTOP
+
+#if !defined( BOOST_USE_WINDOWS_H )
+extern "C" {
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::DWORD_ WINAPI
+GetPriorityClass(boost::detail::winapi::HANDLE_ hProcess);
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI
+SetPriorityClass(
+ boost::detail::winapi::HANDLE_ hProcess,
+ boost::detail::winapi::DWORD_ dwPriorityClass);
+
+} // extern "C"
+#endif //defined BOOST_WINDOWS_H
+
+namespace boost {
+namespace detail {
+namespace winapi {
+
+#if defined(BOOST_USE_WINDOWS_H)
+
+const DWORD_ NORMAL_PRIORITY_CLASS_ = NORMAL_PRIORITY_CLASS;
+const DWORD_ IDLE_PRIORITY_CLASS_ = IDLE_PRIORITY_CLASS;
+const DWORD_ HIGH_PRIORITY_CLASS_ = HIGH_PRIORITY_CLASS;
+const DWORD_ REALTIME_PRIORITY_CLASS_ = REALTIME_PRIORITY_CLASS;
+const DWORD_ BELOW_NORMAL_PRIORITY_CLASS_ = BELOW_NORMAL_PRIORITY_CLASS;
+const DWORD_ ABOVE_NORMAL_PRIORITY_CLASS_ = ABOVE_NORMAL_PRIORITY_CLASS;
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+const DWORD_ PROCESS_MODE_BACKGROUND_BEGIN_ = PROCESS_MODE_BACKGROUND_BEGIN;
+const DWORD_ PROCESS_MODE_BACKGROUND_END_ = PROCESS_MODE_BACKGROUND_END;
+#endif
+
+#else // defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ NORMAL_PRIORITY_CLASS_ = 0x20;
+const DWORD_ IDLE_PRIORITY_CLASS_ = 0x40;
+const DWORD_ HIGH_PRIORITY_CLASS_ = 0x80;
+const DWORD_ REALTIME_PRIORITY_CLASS_ = 0x100;
+const DWORD_ BELOW_NORMAL_PRIORITY_CLASS_ = 0x4000;
+const DWORD_ ABOVE_NORMAL_PRIORITY_CLASS_ = 0x8000;
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+const DWORD_ PROCESS_MODE_BACKGROUND_BEGIN_ = 0x100000;
+const DWORD_ PROCESS_MODE_BACKGROUND_END_ = 0x200000;
+#endif
+
+#endif // defined( BOOST_USE_WINDOWS_H )
+
+using ::GetPriorityClass;
+using ::SetPriorityClass;
+
+}
+}
+}
+
+#endif // BOOST_PLAT_WINDOWS_DESKTOP
+
+#endif // BOOST_DETAIL_WINAPI_PRIORITY_CLASS_HPP_
diff --git a/boost/detail/winapi/process.hpp b/boost/detail/winapi/process.hpp
index 3c3de56e3e..d980aa6d4b 100644
--- a/boost/detail/winapi/process.hpp
+++ b/boost/detail/winapi/process.hpp
@@ -1,34 +1,386 @@
// process.hpp --------------------------------------------------------------//
-// Copyright 2010 Vicente J. Botet Escriba
+// Copyright 2016 Klemens D. Morgenstern
+// Copyright 2016 Andrey Semashev
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
+#ifndef BOOST_DETAIL_WINAPI_PROCESS_HPP_
+#define BOOST_DETAIL_WINAPI_PROCESS_HPP_
-#ifndef BOOST_DETAIL_WINAPI_PROCESS_HPP
-#define BOOST_DETAIL_WINAPI_PROCESS_HPP
-
+#include <boost/detail/winapi/config.hpp>
#include <boost/detail/winapi/basic_types.hpp>
-#include <boost/detail/winapi/GetCurrentProcess.hpp>
+#include <boost/detail/winapi/get_current_process.hpp>
+#include <boost/detail/winapi/get_current_process_id.hpp>
+#include <boost/predef/platform.h>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
-// Windows CE define GetCurrentProcessId as an inline function in kfuncs.h
-#if !defined( BOOST_USE_WINDOWS_H ) && !defined( UNDER_CE )
+#if BOOST_PLAT_WINDOWS_DESKTOP
+
+#if !defined( BOOST_USE_WINDOWS_H )
extern "C" {
-BOOST_SYMBOL_IMPORT boost::detail::winapi::DWORD_ WINAPI GetCurrentProcessId(BOOST_DETAIL_WINAPI_VOID);
-}
+
+struct _PROCESS_INFORMATION;
+#if !defined( BOOST_NO_ANSI_APIS )
+struct _STARTUPINFOA;
#endif
+struct _STARTUPINFOW;
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+struct _PROC_THREAD_ATTRIBUTE_LIST;
+#if !defined( BOOST_NO_ANSI_APIS )
+struct _STARTUPINFOEXA;
+#endif
+struct _STARTUPINFOEXW;
+#endif
+
+BOOST_SYMBOL_IMPORT BOOST_NORETURN boost::detail::winapi::VOID_ WINAPI
+ExitProcess(boost::detail::winapi::UINT_ uExitCode);
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI TerminateProcess(
+ boost::detail::winapi::HANDLE_ hProcess,
+ boost::detail::winapi::UINT_ uExitCode);
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI GetExitCodeProcess(
+ boost::detail::winapi::HANDLE_ hProcess,
+ boost::detail::winapi::LPDWORD_ lpExitCode);
+
+#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI CreateProcessA(
+ boost::detail::winapi::LPCSTR_ lpApplicationName,
+ boost::detail::winapi::LPSTR_ lpCommandLine,
+ ::_SECURITY_ATTRIBUTES* lpProcessAttributes,
+ ::_SECURITY_ATTRIBUTES* lpThreadAttributes,
+ boost::detail::winapi::INT_ bInheritHandles,
+ boost::detail::winapi::DWORD_ dwCreationFlags,
+ boost::detail::winapi::LPVOID_ lpEnvironment,
+ boost::detail::winapi::LPCSTR_ lpCurrentDirectory,
+ ::_STARTUPINFOA* lpStartupInfo,
+ ::_PROCESS_INFORMATION* lpProcessInformation);
+#endif
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI CreateProcessW(
+ boost::detail::winapi::LPCWSTR_ lpApplicationName,
+ boost::detail::winapi::LPWSTR_ lpCommandLine,
+ ::_SECURITY_ATTRIBUTES* lpProcessAttributes,
+ ::_SECURITY_ATTRIBUTES* lpThreadAttributes,
+ boost::detail::winapi::INT_ bInheritHandles,
+ boost::detail::winapi::DWORD_ dwCreationFlags,
+ boost::detail::winapi::LPVOID_ lpEnvironment,
+ boost::detail::winapi::LPCWSTR_ lpCurrentDirectory,
+ ::_STARTUPINFOW* lpStartupInfo,
+ ::_PROCESS_INFORMATION* lpProcessInformation);
+
+} // extern "C"
+#endif //defined BOOST_WINDOWS_H
namespace boost {
namespace detail {
namespace winapi {
-using ::GetCurrentProcessId;
+
+#if defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ DEBUG_PROCESS_ = DEBUG_PROCESS;
+const DWORD_ DEBUG_ONLY_THIS_PROCESS_ = DEBUG_ONLY_THIS_PROCESS;
+const DWORD_ CREATE_SUSPENDED_ = CREATE_SUSPENDED;
+const DWORD_ DETACHED_PROCESS_ = DETACHED_PROCESS;
+const DWORD_ CREATE_NEW_CONSOLE_ = CREATE_NEW_CONSOLE;
+const DWORD_ CREATE_NEW_PROCESS_GROUP_ = CREATE_NEW_PROCESS_GROUP;
+const DWORD_ CREATE_UNICODE_ENVIRONMENT_ = CREATE_UNICODE_ENVIRONMENT;
+const DWORD_ CREATE_SEPARATE_WOW_VDM_ = CREATE_SEPARATE_WOW_VDM;
+const DWORD_ CREATE_SHARED_WOW_VDM_ = CREATE_SHARED_WOW_VDM;
+const DWORD_ CREATE_FORCEDOS_ = CREATE_FORCEDOS;
+const DWORD_ CREATE_BREAKAWAY_FROM_JOB_ = CREATE_BREAKAWAY_FROM_JOB;
+const DWORD_ CREATE_DEFAULT_ERROR_MODE_ = CREATE_DEFAULT_ERROR_MODE;
+const DWORD_ CREATE_NO_WINDOW_ = CREATE_NO_WINDOW;
+
+// Undocumented
+const DWORD_ PROFILE_USER_ = PROFILE_USER;
+const DWORD_ PROFILE_KERNEL_ = PROFILE_KERNEL;
+const DWORD_ PROFILE_SERVER_ = PROFILE_SERVER;
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+const DWORD_ CREATE_PROTECTED_PROCESS_ = CREATE_PROTECTED_PROCESS;
+const DWORD_ EXTENDED_STARTUPINFO_PRESENT_ = EXTENDED_STARTUPINFO_PRESENT;
+#endif
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN7
+const DWORD_ INHERIT_PARENT_AFFINITY_ = INHERIT_PARENT_AFFINITY;
+#endif
+
+// Only documented for Windows CE
+#if defined(UNDER_CE)
+const DWORD_ INHERIT_CALLER_PRIORITY_ = INHERIT_CALLER_PRIORITY;
+#endif
+
+const DWORD_ STARTF_USESHOWWINDOW_ = STARTF_USESHOWWINDOW;
+const DWORD_ STARTF_USESIZE_ = STARTF_USESIZE;
+const DWORD_ STARTF_USEPOSITION_ = STARTF_USEPOSITION;
+const DWORD_ STARTF_USECOUNTCHARS_ = STARTF_USECOUNTCHARS;
+const DWORD_ STARTF_USEFILLATTRIBUTE_ = STARTF_USEFILLATTRIBUTE;
+const DWORD_ STARTF_RUNFULLSCREEN_ = STARTF_RUNFULLSCREEN;
+const DWORD_ STARTF_FORCEONFEEDBACK_ = STARTF_FORCEONFEEDBACK;
+const DWORD_ STARTF_FORCEOFFFEEDBACK_ = STARTF_FORCEOFFFEEDBACK;
+const DWORD_ STARTF_USESTDHANDLES_ = STARTF_USESTDHANDLES;
+const DWORD_ STARTF_USEHOTKEY_ = STARTF_USEHOTKEY;
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN7
+const DWORD_ STARTF_TITLEISLINKNAME_ = STARTF_TITLEISLINKNAME;
+const DWORD_ STARTF_TITLEISAPPID_ = STARTF_TITLEISAPPID;
+const DWORD_ STARTF_PREVENTPINNING_ = STARTF_PREVENTPINNING;
+#endif
+
+#else // defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ DEBUG_PROCESS_ = 0x1;
+const DWORD_ DEBUG_ONLY_THIS_PROCESS_ = 0x2;
+const DWORD_ CREATE_SUSPENDED_ = 0x4;
+const DWORD_ DETACHED_PROCESS_ = 0x8;
+const DWORD_ CREATE_NEW_CONSOLE_ = 0x10;
+const DWORD_ CREATE_NEW_PROCESS_GROUP_ = 0x200;
+const DWORD_ CREATE_UNICODE_ENVIRONMENT_ = 0x400;
+const DWORD_ CREATE_SEPARATE_WOW_VDM_ = 0x800;
+const DWORD_ CREATE_SHARED_WOW_VDM_ = 0x1000;
+const DWORD_ CREATE_FORCEDOS_ = 0x2000;
+const DWORD_ CREATE_BREAKAWAY_FROM_JOB_ = 0x1000000;
+const DWORD_ CREATE_DEFAULT_ERROR_MODE_ = 0x4000000;
+const DWORD_ CREATE_NO_WINDOW_ = 0x8000000;
+
+// Undocumented
+const DWORD_ PROFILE_USER_ = 0x10000000;
+const DWORD_ PROFILE_KERNEL_ = 0x20000000;
+const DWORD_ PROFILE_SERVER_ = 0x40000000;
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+const DWORD_ CREATE_PROTECTED_PROCESS_ = 0x40000;
+const DWORD_ EXTENDED_STARTUPINFO_PRESENT_ = 0x80000;
+#endif
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN7
+const DWORD_ INHERIT_PARENT_AFFINITY_ = 0x10000;
+#endif
+
+// Only documented for Windows CE
+#if defined(UNDER_CE)
+const DWORD_ INHERIT_CALLER_PRIORITY_ = 0x20000;
+#endif
+
+const DWORD_ STARTF_USESHOWWINDOW_ = 0x00000001;
+const DWORD_ STARTF_USESIZE_ = 0x00000002;
+const DWORD_ STARTF_USEPOSITION_ = 0x00000004;
+const DWORD_ STARTF_USECOUNTCHARS_ = 0x00000008;
+const DWORD_ STARTF_USEFILLATTRIBUTE_ = 0x00000010;
+const DWORD_ STARTF_RUNFULLSCREEN_ = 0x00000020;
+const DWORD_ STARTF_FORCEONFEEDBACK_ = 0x00000040;
+const DWORD_ STARTF_FORCEOFFFEEDBACK_ = 0x00000080;
+const DWORD_ STARTF_USESTDHANDLES_ = 0x00000100;
+const DWORD_ STARTF_USEHOTKEY_ = 0x00000200;
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN7
+const DWORD_ STARTF_TITLEISLINKNAME_ = 0x00000800;
+const DWORD_ STARTF_TITLEISAPPID_ = 0x00001000;
+const DWORD_ STARTF_PREVENTPINNING_ = 0x00002000;
+#endif
+
+#endif // defined( BOOST_USE_WINDOWS_H )
+
+#if defined( BOOST_USE_WINDOWS_H ) && !defined( BOOST_WINAPI_IS_MINGW )
+
+const DWORD_ CREATE_PRESERVE_CODE_AUTHZ_LEVEL_ = CREATE_PRESERVE_CODE_AUTHZ_LEVEL;
+
+// Undocumented
+const DWORD_ CREATE_IGNORE_SYSTEM_DEFAULT_ = CREATE_IGNORE_SYSTEM_DEFAULT;
+
+#else // defined( BOOST_USE_WINDOWS_H ) && !defined( BOOST_WINAPI_IS_MINGW )
+
+const DWORD_ CREATE_PRESERVE_CODE_AUTHZ_LEVEL_ = 0x2000000;
+
+// Undocumented
+const DWORD_ CREATE_IGNORE_SYSTEM_DEFAULT_ = 0x80000000;
+
+#endif // defined( BOOST_USE_WINDOWS_H ) && !defined( BOOST_WINAPI_IS_MINGW )
+
+typedef struct BOOST_DETAIL_WINAPI_MAY_ALIAS _PROCESS_INFORMATION {
+ HANDLE_ hProcess;
+ HANDLE_ hThread;
+ DWORD_ dwProcessId;
+ DWORD_ dwThreadId;
+} PROCESS_INFORMATION_, *PPROCESS_INFORMATION_, *LPPROCESS_INFORMATION_;
+
+typedef struct BOOST_DETAIL_WINAPI_MAY_ALIAS _STARTUPINFOA {
+ DWORD_ cb;
+ LPSTR_ lpReserved;
+ LPSTR_ lpDesktop;
+ LPSTR_ lpTitle;
+ DWORD_ dwX;
+ DWORD_ dwY;
+ DWORD_ dwXSize;
+ DWORD_ dwYSize;
+ DWORD_ dwXCountChars;
+ DWORD_ dwYCountChars;
+ DWORD_ dwFillAttribute;
+ DWORD_ dwFlags;
+ WORD_ wShowWindow;
+ WORD_ cbReserved2;
+ LPBYTE_ lpReserved2;
+ HANDLE_ hStdInput;
+ HANDLE_ hStdOutput;
+ HANDLE_ hStdError;
+} STARTUPINFOA_, *LPSTARTUPINFOA_;
+
+typedef struct BOOST_DETAIL_WINAPI_MAY_ALIAS _STARTUPINFOW {
+ DWORD_ cb;
+ LPWSTR_ lpReserved;
+ LPWSTR_ lpDesktop;
+ LPWSTR_ lpTitle;
+ DWORD_ dwX;
+ DWORD_ dwY;
+ DWORD_ dwXSize;
+ DWORD_ dwYSize;
+ DWORD_ dwXCountChars;
+ DWORD_ dwYCountChars;
+ DWORD_ dwFillAttribute;
+ DWORD_ dwFlags;
+ WORD_ wShowWindow;
+ WORD_ cbReserved2;
+ LPBYTE_ lpReserved2;
+ HANDLE_ hStdInput;
+ HANDLE_ hStdOutput;
+ HANDLE_ hStdError;
+} STARTUPINFOW_, *LPSTARTUPINFOW_;
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+
+typedef struct _PROC_THREAD_ATTRIBUTE_LIST PROC_THREAD_ATTRIBUTE_LIST_, *PPROC_THREAD_ATTRIBUTE_LIST_;
+
+#if !defined(BOOST_NO_ANSI_APIS)
+typedef struct BOOST_DETAIL_WINAPI_MAY_ALIAS _STARTUPINFOEXA {
+ STARTUPINFOA_ StartupInfo;
+ PPROC_THREAD_ATTRIBUTE_LIST_ lpAttributeList;
+} STARTUPINFOEXA_, *LPSTARTUPINFOEXA_;
+#endif //BOOST_NO_ANSI_APIS
+
+typedef struct BOOST_DETAIL_WINAPI_MAY_ALIAS _STARTUPINFOEXW {
+ STARTUPINFOW_ StartupInfo;
+ PPROC_THREAD_ATTRIBUTE_LIST_ lpAttributeList;
+} STARTUPINFOEXW_, *LPSTARTUPINFOEXW_;
+
+#endif // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+
+using ::GetExitCodeProcess;
+using ::ExitProcess;
+using ::TerminateProcess;
+
+#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_FORCEINLINE BOOL_ CreateProcessA(
+ LPCSTR_ lpApplicationName,
+ LPSTR_ lpCommandLine,
+ LPSECURITY_ATTRIBUTES_ lpProcessAttributes,
+ LPSECURITY_ATTRIBUTES_ lpThreadAttributes,
+ INT_ bInheritHandles,
+ DWORD_ dwCreationFlags,
+ LPVOID_ lpEnvironment,
+ LPCSTR_ lpCurrentDirectory,
+ LPSTARTUPINFOA_ lpStartupInfo,
+ LPPROCESS_INFORMATION_ lpProcessInformation)
+{
+ return ::CreateProcessA(
+ lpApplicationName,
+ lpCommandLine,
+ reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpProcessAttributes),
+ reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpThreadAttributes),
+ bInheritHandles,
+ dwCreationFlags,
+ lpEnvironment,
+ lpCurrentDirectory,
+ reinterpret_cast< ::_STARTUPINFOA* >(lpStartupInfo),
+ reinterpret_cast< ::_PROCESS_INFORMATION* >(lpProcessInformation));
+}
+
+BOOST_FORCEINLINE BOOL_ create_process(
+ LPCSTR_ lpApplicationName,
+ LPSTR_ lpCommandLine,
+ LPSECURITY_ATTRIBUTES_ lpProcessAttributes,
+ LPSECURITY_ATTRIBUTES_ lpThreadAttributes,
+ INT_ bInheritHandles,
+ DWORD_ dwCreationFlags,
+ LPVOID_ lpEnvironment,
+ LPCSTR_ lpCurrentDirectory,
+ LPSTARTUPINFOA_ lpStartupInfo,
+ LPPROCESS_INFORMATION_ lpProcessInformation)
+{
+ return ::CreateProcessA(
+ lpApplicationName,
+ lpCommandLine,
+ reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpProcessAttributes),
+ reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpThreadAttributes),
+ bInheritHandles,
+ dwCreationFlags,
+ lpEnvironment,
+ lpCurrentDirectory,
+ reinterpret_cast< ::_STARTUPINFOA* >(lpStartupInfo),
+ reinterpret_cast< ::_PROCESS_INFORMATION* >(lpProcessInformation));
}
+#endif
+
+BOOST_FORCEINLINE BOOL_ CreateProcessW(
+ LPCWSTR_ lpApplicationName,
+ LPWSTR_ lpCommandLine,
+ LPSECURITY_ATTRIBUTES_ lpProcessAttributes,
+ LPSECURITY_ATTRIBUTES_ lpThreadAttributes,
+ INT_ bInheritHandles,
+ DWORD_ dwCreationFlags,
+ LPVOID_ lpEnvironment,
+ LPCWSTR_ lpCurrentDirectory,
+ LPSTARTUPINFOW_ lpStartupInfo,
+ LPPROCESS_INFORMATION_ lpProcessInformation)
+{
+ return ::CreateProcessW(
+ lpApplicationName,
+ lpCommandLine,
+ reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpProcessAttributes),
+ reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpThreadAttributes),
+ bInheritHandles,
+ dwCreationFlags,
+ lpEnvironment,
+ lpCurrentDirectory,
+ reinterpret_cast< ::_STARTUPINFOW* >(lpStartupInfo),
+ reinterpret_cast< ::_PROCESS_INFORMATION* >(lpProcessInformation));
+}
+
+BOOST_FORCEINLINE BOOL_ create_process(
+ LPCWSTR_ lpApplicationName,
+ LPWSTR_ lpCommandLine,
+ LPSECURITY_ATTRIBUTES_ lpProcessAttributes,
+ LPSECURITY_ATTRIBUTES_ lpThreadAttributes,
+ INT_ bInheritHandles,
+ DWORD_ dwCreationFlags,
+ LPVOID_ lpEnvironment,
+ LPCWSTR_ lpCurrentDirectory,
+ LPSTARTUPINFOW_ lpStartupInfo,
+ LPPROCESS_INFORMATION_ lpProcessInformation)
+{
+ return ::CreateProcessW(
+ lpApplicationName,
+ lpCommandLine,
+ reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpProcessAttributes),
+ reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpThreadAttributes),
+ bInheritHandles,
+ dwCreationFlags,
+ lpEnvironment,
+ lpCurrentDirectory,
+ reinterpret_cast< ::_STARTUPINFOW* >(lpStartupInfo),
+ reinterpret_cast< ::_PROCESS_INFORMATION* >(lpProcessInformation));
+}
+
}
}
+}
+
+#endif // BOOST_PLAT_WINDOWS_DESKTOP
-#endif // BOOST_DETAIL_WINAPI_PROCESS_HPP
+#endif // BOOST_DETAIL_WINAPI_PROCESS_HPP_
diff --git a/boost/detail/winapi/semaphore.hpp b/boost/detail/winapi/semaphore.hpp
index ba71aae20b..8415e087a5 100644
--- a/boost/detail/winapi/semaphore.hpp
+++ b/boost/detail/winapi/semaphore.hpp
@@ -92,14 +92,21 @@ using ::ReleaseSemaphore;
#if defined( BOOST_USE_WINDOWS_H )
const DWORD_ SEMAPHORE_ALL_ACCESS_ = SEMAPHORE_ALL_ACCESS;
+const DWORD_ SEMAPHORE_MODIFY_STATE_ = SEMAPHORE_MODIFY_STATE;
#else // defined( BOOST_USE_WINDOWS_H )
-const DWORD_ SEMAPHORE_ALL_ACCESS_ = 0x1F0003;
+const DWORD_ SEMAPHORE_ALL_ACCESS_ = 0x001F0003;
+const DWORD_ SEMAPHORE_MODIFY_STATE_ = 0x00000002;
#endif // defined( BOOST_USE_WINDOWS_H )
+// Undocumented and not present in Windows SDK. Enables NtQuerySemaphore.
+// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FEvent%2FNtQueryEvent.html
+const DWORD_ SEMAPHORE_QUERY_STATE_ = 0x00000001;
+
const DWORD_ semaphore_all_access = SEMAPHORE_ALL_ACCESS_;
+const DWORD_ semaphore_modify_state = SEMAPHORE_MODIFY_STATE_;
#if !defined( BOOST_NO_ANSI_APIS )
diff --git a/boost/detail/winapi/shell.hpp b/boost/detail/winapi/shell.hpp
new file mode 100644
index 0000000000..fbb9ad6f5c
--- /dev/null
+++ b/boost/detail/winapi/shell.hpp
@@ -0,0 +1,145 @@
+// shell.hpp --------------------------------------------------------------//
+
+// Copyright 2016 Klemens D. Morgenstern
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_DETAIL_WINAPI_SHELL_HPP_
+#define BOOST_DETAIL_WINAPI_SHELL_HPP_
+
+#include <boost/detail/winapi/basic_types.hpp>
+#include <boost/detail/winapi/limits.hpp>
+#if defined( BOOST_USE_WINDOWS_H )
+#include <shellapi.h>
+#endif
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if !defined( BOOST_USE_WINDOWS_H )
+extern "C" {
+
+BOOST_DETAIL_WINAPI_DECLARE_HANDLE(HICON);
+
+#if !defined( BOOST_NO_ANSI_APIS )
+struct _SHFILEINFOA;
+#endif
+struct _SHFILEINFOW;
+
+#if !defined( BOOST_NO_ANSI_APIS )
+BOOST_SYMBOL_IMPORT boost::detail::winapi::DWORD_PTR_ WINAPI SHGetFileInfoA(
+ boost::detail::winapi::LPCSTR_ pszPath,
+ boost::detail::winapi::DWORD_ dwFileAttributes,
+ ::_SHFILEINFOA *psfinsigned,
+ boost::detail::winapi::UINT_ cbFileInfons,
+ boost::detail::winapi::UINT_ uFlags);
+#endif
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::DWORD_PTR_ WINAPI SHGetFileInfoW(
+ boost::detail::winapi::LPCWSTR_ pszPath,
+ boost::detail::winapi::DWORD_ dwFileAttributes,
+ ::_SHFILEINFOW *psfinsigned,
+ boost::detail::winapi::UINT_ cbFileInfons,
+ boost::detail::winapi::UINT_ uFlags);
+
+} // extern "C"
+#endif // !defined( BOOST_USE_WINDOWS_H )
+
+namespace boost {
+namespace detail {
+namespace winapi {
+
+typedef ::HICON HICON_;
+
+#if defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ SHGFI_ICON_ = SHGFI_ICON;
+const DWORD_ SHGFI_DISPLAYNAME_ = SHGFI_DISPLAYNAME;
+const DWORD_ SHGFI_TYPENAME_ = SHGFI_TYPENAME;
+const DWORD_ SHGFI_ATTRIBUTES_ = SHGFI_ATTRIBUTES;
+const DWORD_ SHGFI_ICONLOCATION_ = SHGFI_ICONLOCATION;
+const DWORD_ SHGFI_EXETYPE_ = SHGFI_EXETYPE;
+const DWORD_ SHGFI_SYSICONINDEX_ = SHGFI_SYSICONINDEX;
+const DWORD_ SHGFI_LINKOVERLAY_ = SHGFI_LINKOVERLAY;
+const DWORD_ SHGFI_SELECTED_ = SHGFI_SELECTED;
+const DWORD_ SHGFI_ATTR_SPECIFIED_ = SHGFI_ATTR_SPECIFIED;
+const DWORD_ SHGFI_LARGEICON_ = SHGFI_LARGEICON;
+const DWORD_ SHGFI_SMALLICON_ = SHGFI_SMALLICON;
+const DWORD_ SHGFI_OPENICON_ = SHGFI_OPENICON;
+const DWORD_ SHGFI_SHELLICONSIZE_ = SHGFI_SHELLICONSIZE;
+const DWORD_ SHGFI_PIDL_ = SHGFI_PIDL;
+const DWORD_ SHGFI_USEFILEATTRIBUTES_ = SHGFI_USEFILEATTRIBUTES;
+
+#else // defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ SHGFI_ICON_ = 0x000000100;
+const DWORD_ SHGFI_DISPLAYNAME_ = 0x000000200;
+const DWORD_ SHGFI_TYPENAME_ = 0x000000400;
+const DWORD_ SHGFI_ATTRIBUTES_ = 0x000000800;
+const DWORD_ SHGFI_ICONLOCATION_ = 0x000001000;
+const DWORD_ SHGFI_EXETYPE_ = 0x000002000;
+const DWORD_ SHGFI_SYSICONINDEX_ = 0x000004000;
+const DWORD_ SHGFI_LINKOVERLAY_ = 0x000008000;
+const DWORD_ SHGFI_SELECTED_ = 0x000010000;
+const DWORD_ SHGFI_ATTR_SPECIFIED_ = 0x000020000;
+const DWORD_ SHGFI_LARGEICON_ = 0x000000000;
+const DWORD_ SHGFI_SMALLICON_ = 0x000000001;
+const DWORD_ SHGFI_OPENICON_ = 0x000000002;
+const DWORD_ SHGFI_SHELLICONSIZE_ = 0x000000004;
+const DWORD_ SHGFI_PIDL_ = 0x000000008;
+const DWORD_ SHGFI_USEFILEATTRIBUTES_ = 0x000000010;
+
+#endif // defined( BOOST_USE_WINDOWS_H )
+
+// These constants are only declared for _WIN32_IE >= 0x0500. We don't set IE version
+// and 5.0 is the default version since NT4 SP6, so just define the constants unconditionally.
+const DWORD_ SHGFI_ADDOVERLAYS_ = 0x000000020;
+const DWORD_ SHGFI_OVERLAYINDEX_ = 0x000000040;
+
+typedef struct BOOST_DETAIL_WINAPI_MAY_ALIAS _SHFILEINFOA {
+ HICON_ hIcon;
+ int iIcon;
+ DWORD_ dwAttributes;
+ CHAR_ szDisplayName[MAX_PATH_];
+ CHAR_ szTypeName[80];
+} SHFILEINFOA_;
+
+typedef struct BOOST_DETAIL_WINAPI_MAY_ALIAS _SHFILEINFOW {
+ HICON_ hIcon;
+ int iIcon;
+ DWORD_ dwAttributes;
+ WCHAR_ szDisplayName[MAX_PATH_];
+ WCHAR_ szTypeName[80];
+} SHFILEINFOW_;
+
+#if !defined( BOOST_NO_ANSI_APIS )
+
+BOOST_FORCEINLINE DWORD_PTR_ SHGetFileInfoA(LPCSTR_ pszPath, DWORD_ dwFileAttributes, SHFILEINFOA_* psfinsigned, UINT_ cbFileInfons, UINT_ uFlags)
+{
+ return ::SHGetFileInfoA(pszPath, dwFileAttributes, reinterpret_cast< ::_SHFILEINFOA* >(psfinsigned), cbFileInfons, uFlags);
+}
+
+BOOST_FORCEINLINE DWORD_PTR_ sh_get_file_info(LPCSTR_ pszPath, DWORD_ dwFileAttributes, SHFILEINFOA_* psfinsigned, UINT_ cbFileInfons, UINT_ uFlags)
+{
+ return ::SHGetFileInfoA(pszPath, dwFileAttributes, reinterpret_cast< ::_SHFILEINFOA* >(psfinsigned), cbFileInfons, uFlags);
+}
+
+#endif // BOOST_NO_ANSI_APIS
+
+BOOST_FORCEINLINE DWORD_PTR_ SHGetFileInfoW(LPCWSTR_ pszPath, DWORD_ dwFileAttributes, SHFILEINFOW_* psfinsigned, UINT_ cbFileInfons, UINT_ uFlags)
+{
+ return ::SHGetFileInfoW(pszPath, dwFileAttributes, reinterpret_cast< ::_SHFILEINFOW* >(psfinsigned), cbFileInfons, uFlags);
+}
+
+BOOST_FORCEINLINE DWORD_PTR_ sh_get_file_info(LPCWSTR_ pszPath, DWORD_ dwFileAttributes, SHFILEINFOW_* psfinsigned, UINT_ cbFileInfons, UINT_ uFlags)
+{
+ return ::SHGetFileInfoW(pszPath, dwFileAttributes, reinterpret_cast< ::_SHFILEINFOW* >(psfinsigned), cbFileInfons, uFlags);
+}
+
+}
+}
+}
+
+#endif // BOOST_DETAIL_WINAPI_SHELL_HPP_
diff --git a/boost/detail/winapi/show_window.hpp b/boost/detail/winapi/show_window.hpp
new file mode 100644
index 0000000000..a8839ae79e
--- /dev/null
+++ b/boost/detail/winapi/show_window.hpp
@@ -0,0 +1,105 @@
+// show_window.hpp --------------------------------------------------------------//
+
+// Copyright 2016 Klemens D. Morgenstern
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_DETAIL_WINAPI_SHOW_WINDOW_HPP_
+#define BOOST_DETAIL_WINAPI_SHOW_WINDOW_HPP_
+
+#include <boost/detail/winapi/basic_types.hpp>
+#include <boost/predef/platform.h>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if BOOST_PLAT_WINDOWS_DESKTOP
+
+#if !defined( BOOST_USE_WINDOWS_H )
+extern "C" {
+BOOST_DETAIL_WINAPI_DECLARE_HANDLE(HWND);
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI ShowWindow(
+ HWND hWnd,
+ int nCmdShow);
+
+BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI ShowWindowAsync(
+ HWND hWnd,
+ int nCmdShow);
+}
+#endif // BOOST_USE_WINDOWS_H
+
+namespace boost {
+namespace detail {
+namespace winapi {
+
+typedef ::HWND HWND_;
+using ::ShowWindow;
+using ::ShowWindowAsync;
+
+#if defined( BOOST_USE_WINDOWS_H ) && !defined( NOSHOWWINDOW )
+
+const DWORD_ SW_HIDE_ = SW_HIDE;
+const DWORD_ SW_SHOWNORMAL_ = SW_SHOWNORMAL;
+const DWORD_ SW_NORMAL_ = SW_NORMAL;
+const DWORD_ SW_SHOWMINIMIZED_ = SW_SHOWMINIMIZED;
+const DWORD_ SW_SHOWMAXIMIZED_ = SW_SHOWMAXIMIZED;
+const DWORD_ SW_MAXIMIZE_ = SW_MAXIMIZE;
+const DWORD_ SW_SHOWNOACTIVATE_ = SW_SHOWNOACTIVATE;
+const DWORD_ SW_SHOW_ = SW_SHOW;
+const DWORD_ SW_MINIMIZE_ = SW_MINIMIZE;
+const DWORD_ SW_SHOWMINNOACTIVE_ = SW_SHOWMINNOACTIVE;
+const DWORD_ SW_SHOWNA_ = SW_SHOWNA;
+const DWORD_ SW_RESTORE_ = SW_RESTORE;
+const DWORD_ SW_SHOWDEFAULT_ = SW_SHOWDEFAULT;
+const DWORD_ SW_FORCEMINIMIZE_ = SW_FORCEMINIMIZE;
+const DWORD_ SW_MAX_ = SW_MAX;
+const DWORD_ HIDE_WINDOW_ = HIDE_WINDOW;
+const DWORD_ SHOW_OPENWINDOW_ = SHOW_OPENWINDOW;
+const DWORD_ SHOW_ICONWINDOW_ = SHOW_ICONWINDOW;
+const DWORD_ SHOW_FULLSCREEN_ = SHOW_FULLSCREEN;
+const DWORD_ SHOW_OPENNOACTIVATE_ = SHOW_OPENNOACTIVATE;
+const DWORD_ SW_PARENTCLOSING_ = SW_PARENTCLOSING;
+const DWORD_ SW_OTHERZOOM_ = SW_OTHERZOOM;
+const DWORD_ SW_PARENTOPENING_ = SW_PARENTOPENING;
+const DWORD_ SW_OTHERUNZOOM_ = SW_OTHERUNZOOM;
+
+#else
+
+const DWORD_ SW_HIDE_ = 0;
+const DWORD_ SW_SHOWNORMAL_ = 1;
+const DWORD_ SW_NORMAL_ = 1;
+const DWORD_ SW_SHOWMINIMIZED_ = 2;
+const DWORD_ SW_SHOWMAXIMIZED_ = 3;
+const DWORD_ SW_MAXIMIZE_ = 3;
+const DWORD_ SW_SHOWNOACTIVATE_ = 4;
+const DWORD_ SW_SHOW_ = 5;
+const DWORD_ SW_MINIMIZE_ = 6;
+const DWORD_ SW_SHOWMINNOACTIVE_ = 7;
+const DWORD_ SW_SHOWNA_ = 8;
+const DWORD_ SW_RESTORE_ = 9;
+const DWORD_ SW_SHOWDEFAULT_ = 10;
+const DWORD_ SW_FORCEMINIMIZE_ = 11;
+const DWORD_ SW_MAX_ = 11;
+const DWORD_ HIDE_WINDOW_ = 0;
+const DWORD_ SHOW_OPENWINDOW_ = 1;
+const DWORD_ SHOW_ICONWINDOW_ = 2;
+const DWORD_ SHOW_FULLSCREEN_ = 3;
+const DWORD_ SHOW_OPENNOACTIVATE_ = 4;
+const DWORD_ SW_PARENTCLOSING_ = 1;
+const DWORD_ SW_OTHERZOOM_ = 2;
+const DWORD_ SW_PARENTOPENING_ = 3;
+const DWORD_ SW_OTHERUNZOOM_ = 4;
+
+#endif
+
+}
+
+}
+}
+
+#endif // BOOST_PLAT_WINDOWS_DESKTOP
+
+#endif // BOOST_DETAIL_WINAPI_SHOW_WINDOW_HPP_
diff --git a/boost/detail/winapi/srw_lock.hpp b/boost/detail/winapi/srw_lock.hpp
index c5318f5860..0dad858f6e 100644
--- a/boost/detail/winapi/srw_lock.hpp
+++ b/boost/detail/winapi/srw_lock.hpp
@@ -16,6 +16,13 @@
#pragma once
#endif
+#if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_WIN6 \
+ || (defined(_MSC_VER) && _MSC_VER < 1600)
+// Windows SDK 6.0A, which is used by MSVC 9, does not have TryAcquireSRWLock* neither in headers nor in .lib files,
+// although the functions are present in later SDKs since Windows API version 6.
+#define BOOST_WINAPI_NO_TRY_ACQUIRE_SRWLOCK
+#endif
+
#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
#include <boost/detail/winapi/basic_types.hpp>
@@ -39,11 +46,13 @@ AcquireSRWLockExclusive(::_RTL_SRWLOCK* SRWLock);
BOOST_SYMBOL_IMPORT boost::detail::winapi::VOID_ WINAPI
AcquireSRWLockShared(::_RTL_SRWLOCK* SRWLock);
+#if !defined( BOOST_WINAPI_NO_TRY_ACQUIRE_SRWLOCK )
BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOLEAN_ WINAPI
TryAcquireSRWLockExclusive(::_RTL_SRWLOCK* SRWLock);
BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOLEAN_ WINAPI
TryAcquireSRWLockShared(::_RTL_SRWLOCK* SRWLock);
+#endif
}
#endif
@@ -86,6 +95,7 @@ BOOST_FORCEINLINE VOID_ AcquireSRWLockShared(PSRWLOCK_ SRWLock)
::AcquireSRWLockShared(reinterpret_cast< ::_RTL_SRWLOCK* >(SRWLock));
}
+#if !defined( BOOST_WINAPI_NO_TRY_ACQUIRE_SRWLOCK )
BOOST_FORCEINLINE BOOLEAN_ TryAcquireSRWLockExclusive(PSRWLOCK_ SRWLock)
{
return ::TryAcquireSRWLockExclusive(reinterpret_cast< ::_RTL_SRWLOCK* >(SRWLock));
@@ -95,6 +105,7 @@ BOOST_FORCEINLINE BOOLEAN_ TryAcquireSRWLockShared(PSRWLOCK_ SRWLock)
{
return ::TryAcquireSRWLockShared(reinterpret_cast< ::_RTL_SRWLOCK* >(SRWLock));
}
+#endif
}
}
diff --git a/boost/detail/winapi/thread.hpp b/boost/detail/winapi/thread.hpp
index 9367d46bd0..6162708659 100644
--- a/boost/detail/winapi/thread.hpp
+++ b/boost/detail/winapi/thread.hpp
@@ -11,7 +11,8 @@
#define BOOST_DETAIL_WINAPI_THREAD_HPP
#include <boost/detail/winapi/basic_types.hpp>
-#include <boost/detail/winapi/GetCurrentThread.hpp>
+#include <boost/detail/winapi/get_current_thread.hpp>
+#include <boost/detail/winapi/get_current_thread_id.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -19,10 +20,6 @@
#if !defined( BOOST_USE_WINDOWS_H )
extern "C" {
-// Windows CE define GetCurrentThreadId as an inline function in kfuncs.h
-#if !defined( UNDER_CE )
-BOOST_SYMBOL_IMPORT boost::detail::winapi::DWORD_ WINAPI GetCurrentThreadId(BOOST_DETAIL_WINAPI_VOID);
-#endif
BOOST_SYMBOL_IMPORT boost::detail::winapi::DWORD_ WINAPI
SleepEx(
boost::detail::winapi::DWORD_ dwMilliseconds,
@@ -35,7 +32,6 @@ BOOST_SYMBOL_IMPORT boost::detail::winapi::BOOL_ WINAPI SwitchToThread(BOOST_DET
namespace boost {
namespace detail {
namespace winapi {
-using ::GetCurrentThreadId;
using ::SleepEx;
using ::Sleep;
using ::SwitchToThread;
diff --git a/boost/detail/winapi/waitable_timer.hpp b/boost/detail/winapi/waitable_timer.hpp
index 842cb040d4..c2bf6d5cf2 100644
--- a/boost/detail/winapi/waitable_timer.hpp
+++ b/boost/detail/winapi/waitable_timer.hpp
@@ -75,6 +75,25 @@ using ::OpenWaitableTimerA;
using ::OpenWaitableTimerW;
using ::CancelWaitableTimer;
+#if defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ TIMER_ALL_ACCESS_ = TIMER_ALL_ACCESS;
+const DWORD_ TIMER_MODIFY_STATE_ = TIMER_MODIFY_STATE;
+const DWORD_ TIMER_QUERY_STATE_ = TIMER_QUERY_STATE;
+
+#else // defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ TIMER_ALL_ACCESS_ = 0x001F0003;
+const DWORD_ TIMER_MODIFY_STATE_ = 0x00000002;
+const DWORD_ TIMER_QUERY_STATE_ = 0x00000001;
+
+#endif // defined( BOOST_USE_WINDOWS_H )
+
+const DWORD_ timer_all_access = TIMER_ALL_ACCESS_;
+const DWORD_ timer_modify_state = TIMER_MODIFY_STATE_;
+const DWORD_ timer_query_state = TIMER_QUERY_STATE_;
+
+
#if !defined( BOOST_NO_ANSI_APIS )
BOOST_FORCEINLINE HANDLE_ CreateWaitableTimerA(PSECURITY_ATTRIBUTES_ lpTimerAttributes, BOOL_ bManualReset, LPCSTR_ lpTimerName)
{
diff --git a/boost/dll.hpp b/boost/dll.hpp
new file mode 100644
index 0000000000..33e847ea14
--- /dev/null
+++ b/boost/dll.hpp
@@ -0,0 +1,27 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015-2016 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_DLL_DLL_HPP
+#define BOOST_DLL_DLL_HPP
+
+/// \file boost/dll.hpp
+/// \brief Includes all the non-experimental headers of the Boost.DLL library.
+
+#include <boost/config.hpp>
+#include <boost/dll/shared_library.hpp>
+#include <boost/dll/alias.hpp>
+#include <boost/dll/import.hpp>
+#include <boost/dll/library_info.hpp>
+#include <boost/dll/runtime_symbol_info.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#endif // BOOST_DLL_DLL_HPP
+
diff --git a/boost/dll/alias.hpp b/boost/dll/alias.hpp
new file mode 100644
index 0000000000..0cc986c279
--- /dev/null
+++ b/boost/dll/alias.hpp
@@ -0,0 +1,264 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015 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_DLL_ALIAS_HPP
+#define BOOST_DLL_ALIAS_HPP
+
+#include <boost/config.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/predef/compiler.h>
+#include <boost/predef/os.h>
+#include <boost/dll/detail/aggressive_ptr_cast.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+/// \file boost/dll/alias.hpp
+/// \brief Includes alias methods and macro. You can include this header or
+/// boost/dll/shared_library.hpp to reduce dependencies
+/// in case you do not use the refcountable functions.
+
+namespace boost { namespace dll {
+
+#ifdef BOOST_DLL_DOXYGEN
+/// Define this macro to explicitly specify translation unit in which alias must be instantiated.
+/// See section 'Limitations' for more info. You may find usage examples in source codes of almost each tutorial.
+/// Must be used in code, when \forcedmacrolink{BOOST_DLL_FORCE_NO_WEAK_EXPORTS} is defined
+#define BOOST_DLL_FORCE_ALIAS_INSTANTIATION
+
+/// Define this macro to disable exporting weak symbols and start using the \forcedmacrolink{BOOST_DLL_FORCE_ALIAS_INSTANTIATION}.
+/// This may be usefull for working around linker problems or to test your program for compatability with linkers that do not support export of weak symbols.
+#define BOOST_DLL_FORCE_NO_WEAK_EXPORTS
+#endif
+
+#if BOOST_COMP_MSVC
+
+#define BOOST_DLL_SELECTANY __declspec(selectany)
+
+#define BOOST_DLL_SECTION(SectionName, Permissions) \
+ BOOST_STATIC_ASSERT_MSG( \
+ sizeof(#SectionName) < 10, \
+ "Some platforms require section names to be at most 8 bytest" \
+ ); \
+ __pragma(section(#SectionName, Permissions)) __declspec(allocate(#SectionName)) \
+ /**/
+
+#else // #if BOOST_COMP_MSVC
+
+
+#if BOOST_OS_WINDOWS || BOOST_OS_ANDROID || BOOST_COMP_IBM
+// There are some problems with mixing `__dllexport__` and `weak` using MinGW
+// See https://sourceware.org/bugzilla/show_bug.cgi?id=17480
+//
+// Android had an issue with exporting weak symbols
+// https://code.google.com/p/android/issues/detail?id=70206
+#define BOOST_DLL_SELECTANY
+#else // #if BOOST_OS_WINDOWS
+/*!
+* \brief Macro that allows linker to select any occurrence of this symbol instead of
+* failing with 'multiple definitions' error at linktime.
+*
+* This macro does not work on Android, IBM XL C/C++ and MinGW+Windows
+* because of linker problems with exporting weak symbols
+* (See https://code.google.com/p/android/issues/detail?id=70206, https://sourceware.org/bugzilla/show_bug.cgi?id=17480)
+*/
+#define BOOST_DLL_SELECTANY __attribute__((weak))
+#endif // #if BOOST_OS_WINDOWS
+
+// TODO: improve section permissions using following info:
+// http://stackoverflow.com/questions/6252812/what-does-the-aw-flag-in-the-section-attribute-mean
+
+#if !BOOST_OS_MACOS && !BOOST_OS_IOS
+/*!
+* \brief Macro that puts symbol to a specific section. On MacOS all the sections are put into "__DATA" segment.
+* \param SectionName Name of the section. Must be a valid C identifier without quotes not longer than 8 bytes.
+* \param Permissions Can be "read" or "write" (without quotes!).
+*/
+#define BOOST_DLL_SECTION(SectionName, Permissions) \
+ BOOST_STATIC_ASSERT_MSG( \
+ sizeof(#SectionName) < 10, \
+ "Some platforms require section names to be at most 8 bytest" \
+ ); \
+ __attribute__ ((section (#SectionName))) \
+ /**/
+#else // #if !BOOST_OS_MACOS && !BOOST_OS_IOS
+
+#define BOOST_DLL_SECTION(SectionName, Permissions) \
+ BOOST_STATIC_ASSERT_MSG( \
+ sizeof(#SectionName) < 10, \
+ "Some platforms require section names to be at most 8 bytest" \
+ ); \
+ __attribute__ ((section ( "__DATA," #SectionName))) \
+ /**/
+
+#endif // #if #if !BOOST_OS_MACOS && !BOOST_OS_IOS
+
+#endif // #if BOOST_COMP_MSVC
+
+
+// Alias - is just a variable that pointers to original data
+//
+// A few attempts were made to avoid additional indirection:
+// 1)
+// // Does not work on Windows, work on Linux
+// extern "C" BOOST_SYMBOL_EXPORT void AliasName() {
+// reinterpret_cast<void (*)()>(Function)();
+// }
+//
+// 2)
+// // Does not work on Linux (changes permissions of .text section and produces incorrect DSO)
+// extern "C" BOOST_SYMBOL_EXPORT void* __attribute__ ((section(".text#")))
+// func_ptr = *reinterpret_cast<std::ptrdiff_t**>(&foo::bar);
+//
+// 3) // requires mangled name of `Function`
+// // AliasName() __attribute__ ((weak, alias ("Function")))
+//
+// // hard to use
+// `#pragma comment(linker, "/alternatename:_pWeakValue=_pDefaultWeakValue")`
+
+/*!
+* \brief Makes an alias name for exported function or variable.
+*
+* This macro is useful in cases of long mangled C++ names. For example some `void boost::foo(std::sting)`
+* function name will change to something like `N5boostN3foosE` after mangling.
+* Importing function by `N5boostN3foosE` name does not looks user friendly, especially assuming the fact
+* that different compilers have different mangling schemes. AliasName is the name that won't be mangled
+* and can be used as a portable import name.
+*
+*
+* Can be used in any namespace, including global. FunctionOrVar must be fully qualified,
+* so that address of it could be taken. Multiple different aliases for a single variable/function
+* are allowed.
+*
+* Make sure that AliasNames are unique per library/executable. Functions or variables
+* in global namespace must not have names same as AliasNames.
+*
+* Same AliasName in different translation units must point to the same FunctionOrVar.
+*
+* Puts all the aliases into the \b "boostdll" read only section of the binary. Equal to
+* \forcedmacrolink{BOOST_DLL_ALIAS_SECTIONED}(FunctionOrVar, AliasName, boostdll).
+*
+* \param FunctionOrVar Function or variable for which an alias must be made.
+* \param AliasName Name of the alias. Must be a valid C identifier.
+*
+* \b Example:
+* \code
+* namespace foo {
+* void bar(std::string&);
+*
+* BOOST_DLL_ALIAS(foo::bar, foo_bar)
+* }
+*
+* BOOST_DLL_ALIAS(foo::bar, foo_bar_another_alias_name)
+* \endcode
+*
+* \b See: \forcedmacrolink{BOOST_DLL_ALIAS_SECTIONED} for making alias in a specific section.
+*/
+#define BOOST_DLL_ALIAS(FunctionOrVar, AliasName) \
+ BOOST_DLL_ALIAS_SECTIONED(FunctionOrVar, AliasName, boostdll) \
+ /**/
+
+
+#if ((BOOST_COMP_GNUC && BOOST_OS_WINDOWS) || BOOST_OS_ANDROID || BOOST_COMP_IBM || defined(BOOST_DLL_FORCE_NO_WEAK_EXPORTS)) \
+ && !defined(BOOST_DLL_FORCE_ALIAS_INSTANTIATION) && !defined(BOOST_DLL_DOXYGEN)
+
+#define BOOST_DLL_ALIAS_SECTIONED(FunctionOrVar, AliasName, SectionName) \
+ namespace _autoaliases { \
+ extern "C" BOOST_SYMBOL_EXPORT const void *AliasName; \
+ } /* namespace _autoaliases */ \
+ /**/
+
+#define BOOST_DLL_AUTO_ALIAS(FunctionOrVar) \
+ namespace _autoaliases { \
+ extern "C" BOOST_SYMBOL_EXPORT const void *FunctionOrVar; \
+ } /* namespace _autoaliases */ \
+ /**/
+#else
+// Note: we can not use `aggressive_ptr_cast` here, because in that case GCC applies
+// different permissions to the section and it causes Segmentation fault.
+// Note: we can not use `boost::addressof()` here, because in that case GCC
+// may optimize away the FunctionOrVar instance and we'll get a pointer to unexisting symbol.
+/*!
+* \brief Same as \forcedmacrolink{BOOST_DLL_ALIAS} but puts alias name into the user specified section.
+*
+* \param FunctionOrVar Function or variable for which an alias must be made.
+* \param AliasName Name of the alias. Must be a valid C identifier.
+* \param SectionName Name of the section. Must be a valid C identifier without quotes not longer than 8 bytes.
+*
+* \b Example:
+* \code
+* namespace foo {
+* void bar(std::string&);
+*
+* BOOST_DLL_ALIAS_SECTIONED(foo::bar, foo_bar, sect_1) // section "sect_1" now exports "foo_bar"
+* }
+* \endcode
+*
+*/
+#define BOOST_DLL_ALIAS_SECTIONED(FunctionOrVar, AliasName, SectionName) \
+ namespace _autoaliases { \
+ extern "C" BOOST_SYMBOL_EXPORT const void *AliasName; \
+ BOOST_DLL_SECTION(SectionName, read) BOOST_DLL_SELECTANY \
+ const void * AliasName = reinterpret_cast<const void*>(reinterpret_cast<intptr_t>( \
+ &FunctionOrVar \
+ )); \
+ } /* namespace _autoaliases */ \
+ /**/
+
+/*!
+* \brief Exports variable or function with unmangled alias name.
+*
+* This macro is useful in cases of long mangled C++ names. For example some `void boost::foo(std::sting)`
+* function name will change to something like `N5boostN3foosE` after mangling.
+* Importing function by `N5boostN3foosE` name does not looks user friendly, especially assuming the fact
+* that different compilers have different mangling schemes.*
+*
+* Must be used in scope where FunctionOrVar declared. FunctionOrVar must be a valid C name, which means that
+* it must not contain `::`.
+*
+* Functions or variables
+* in global namespace must not have names same as FunctionOrVar.
+*
+* Puts all the aliases into the \b "boostdll" read only section of the binary. Almost same as
+* \forcedmacrolink{BOOST_DLL_ALIAS}(FunctionOrVar, FunctionOrVar).
+*
+* \param FunctionOrVar Function or variable for which an unmangled alias must be made.
+*
+* \b Example:
+* \code
+* namespace foo {
+* void bar(std::string&);
+* BOOST_DLL_AUTO_ALIAS(bar)
+* }
+*
+* \endcode
+*
+* \b See: \forcedmacrolink{BOOST_DLL_ALIAS} for making an alias with different names.
+*/
+
+#define BOOST_DLL_AUTO_ALIAS(FunctionOrVar) \
+ namespace _autoaliases { \
+ BOOST_DLL_SELECTANY const void * dummy_ ## FunctionOrVar \
+ = reinterpret_cast<const void*>(reinterpret_cast<intptr_t>( \
+ &FunctionOrVar \
+ )); \
+ extern "C" BOOST_SYMBOL_EXPORT const void *FunctionOrVar; \
+ BOOST_DLL_SECTION(boostdll, read) BOOST_DLL_SELECTANY \
+ const void * FunctionOrVar = dummy_ ## FunctionOrVar; \
+ } /* namespace _autoaliases */ \
+ /**/
+
+
+#endif
+
+
+}} // namespace boost::dll
+
+
+#endif // BOOST_DLL_ALIAS_HPP
+
diff --git a/boost/dll/detail/aggressive_ptr_cast.hpp b/boost/dll/detail/aggressive_ptr_cast.hpp
new file mode 100644
index 0000000000..a8887f4382
--- /dev/null
+++ b/boost/dll/detail/aggressive_ptr_cast.hpp
@@ -0,0 +1,130 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015-2016 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_DLL_DETAIL_AGGRESSIVE_PTR_CAST_HPP
+#define BOOST_DLL_DETAIL_AGGRESSIVE_PTR_CAST_HPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/type_traits/is_member_pointer.hpp>
+#include <boost/type_traits/is_void.hpp>
+#include <boost/type_traits/is_reference.hpp>
+#include <boost/type_traits/remove_pointer.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/cstdint.hpp> // boost::uintptr_t
+#include <cstring> // std::memcpy
+
+namespace boost { namespace dll { namespace detail {
+
+// GCC warns when reinterpret_cast between function pointer and object pointer occur.
+// This method suppress the warnings and ensures that such casts are safe.
+template <class To, class From>
+BOOST_FORCEINLINE typename boost::disable_if_c<boost::is_member_pointer<To>::value || boost::is_reference<To>::value || boost::is_member_pointer<From>::value, To>::type
+ aggressive_ptr_cast(From v) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT_MSG(
+ boost::is_pointer<To>::value && boost::is_pointer<From>::value,
+ "`agressive_ptr_cast` function must be used only for pointer casting."
+ );
+
+ BOOST_STATIC_ASSERT_MSG(
+ boost::is_void< typename boost::remove_pointer<To>::type >::value
+ || boost::is_void< typename boost::remove_pointer<From>::type >::value,
+ "`agressive_ptr_cast` function must be used only for casting to or from void pointers."
+ );
+
+ BOOST_STATIC_ASSERT_MSG(
+ sizeof(v) == sizeof(To),
+ "Pointer to function and pointer to object differ in size on your platform."
+ );
+
+ return reinterpret_cast<To>(
+ reinterpret_cast<boost::uintptr_t>(v)
+ );
+}
+
+template <class To, class From>
+BOOST_FORCEINLINE typename boost::disable_if_c<!boost::is_reference<To>::value || boost::is_member_pointer<From>::value, To>::type
+ aggressive_ptr_cast(From v) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT_MSG(
+ boost::is_pointer<From>::value,
+ "`agressive_ptr_cast` function must be used only for pointer casting."
+ );
+
+ BOOST_STATIC_ASSERT_MSG(
+ boost::is_void< typename boost::remove_pointer<From>::type >::value,
+ "`agressive_ptr_cast` function must be used only for casting to or from void pointers."
+ );
+
+ BOOST_STATIC_ASSERT_MSG(
+ sizeof(v) == sizeof(typename boost::remove_reference<To>::type*),
+ "Pointer to function and pointer to object differ in size on your platform."
+ );
+
+ return static_cast<To>(
+ *reinterpret_cast<typename boost::remove_reference<To>::type*>(
+ *reinterpret_cast<boost::uintptr_t*>(
+ reinterpret_cast<unsigned char*>(
+ v
+ )
+ )
+ )
+ );
+}
+
+template <class To, class From>
+BOOST_FORCEINLINE typename boost::disable_if_c<!boost::is_member_pointer<To>::value || boost::is_member_pointer<From>::value, To>::type
+ aggressive_ptr_cast(From v) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT_MSG(
+ boost::is_pointer<From>::value,
+ "`agressive_ptr_cast` function must be used only for pointer casting."
+ );
+
+ BOOST_STATIC_ASSERT_MSG(
+ boost::is_void< typename boost::remove_pointer<From>::type >::value,
+ "`agressive_ptr_cast` function must be used only for casting to or from void pointers."
+ );
+
+ To res = 0;
+ std::memcpy(&res, &v, sizeof(To));
+ return res;
+}
+
+template <class To, class From>
+BOOST_FORCEINLINE typename boost::disable_if_c<boost::is_member_pointer<To>::value || !boost::is_member_pointer<From>::value, To>::type
+ aggressive_ptr_cast(From v) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT_MSG(
+ boost::is_pointer<To>::value,
+ "`agressive_ptr_cast` function must be used only for pointer casting."
+ );
+
+ BOOST_STATIC_ASSERT_MSG(
+ boost::is_void< typename boost::remove_pointer<To>::type >::value,
+ "`agressive_ptr_cast` function must be used only for casting to or from void pointers."
+ );
+
+ BOOST_STATIC_ASSERT_MSG(
+ !sizeof(From),
+ "Casting from member pointers to void pointer is not implemnted in `agressive_ptr_cast`."
+ );
+
+ return 0;
+}
+
+}}} // boost::dll::detail
+
+#endif // BOOST_DLL_DETAIL_AGGRESSIVE_PTR_CAST_HPP
+
diff --git a/boost/dll/detail/ctor_dtor.hpp b/boost/dll/detail/ctor_dtor.hpp
new file mode 100644
index 0000000000..5950d9e60a
--- /dev/null
+++ b/boost/dll/detail/ctor_dtor.hpp
@@ -0,0 +1,176 @@
+// Copyright 2016 Klemens Morgenstern, 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)
+
+// For more information, see http://www.boost.org
+
+#ifndef INCLUDE_BOOST_DLL_DETAIL_CTOR_DTOR_HPP_
+#define INCLUDE_BOOST_DLL_DETAIL_CTOR_DTOR_HPP_
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/dll/detail/aggressive_ptr_cast.hpp>
+#include <boost/dll/detail/get_mem_fn_type.hpp>
+
+#if defined(BOOST_MSVC) || defined(BOOST_MSVC_VER)
+# include <boost/dll/detail/demangling/msvc.hpp>
+#else
+# include <boost/dll/detail/demangling/itanium.hpp>
+#endif
+
+namespace boost { namespace dll { namespace detail {
+
+/*!
+ * This class stores a constructor.
+ *
+ * In some compilers there are several constructors in code, which may include an allocating one.
+ * This can be used if the imported class shall be put on the heap, which is why the class provied both types.
+ */
+template<typename Signature>
+struct constructor;
+
+template<typename Class, typename ...Args>
+struct constructor<Class(Args...)> {
+ typedef typename detail::get_mem_fn_type<Class, void(Args...)>::mem_fn standard_t;
+ typedef Class*(*allocating_t)(Args...);
+
+
+ //! The standard, i.e. not allocating constructor. @warning May differ with the compiler. Use @ref constructor::call_standard instead.
+ standard_t standard;
+ //! The allocating constructor. @warning May differ with the compiler. Use @ref constructor::call_allocating instead.
+ allocating_t allocating;
+
+ //! Call the standard contructor
+ void call_standard (Class * const ptr, Args...args){ (ptr->*standard)(static_cast<Args>(args)...); }
+
+ //! Call the deleting destructor
+ Class * call_allocating(Args...args){ return allocating(static_cast<Args>(args)...); }
+
+
+ //! True if a allocating constructor could be loaded.
+ bool has_allocating() const { return allocating != nullptr; }
+
+ //! False if neither the allocating nor the standard constructor is available.
+ bool is_empty() const { return !((allocating == nullptr) && (standard != nullptr)) ; }
+
+ constructor() = delete;
+ constructor(const constructor &) = default;
+
+ explicit constructor(standard_t standard, allocating_t allocating = nullptr)
+ : standard(standard)
+ , allocating(allocating)
+ {}
+};
+
+
+
+template <typename Class>
+struct destructor {
+#if !defined(BOOST_MSVC) && !defined(BOOST_MSVC_VER)
+ typedef void( *type)(Class* const);
+#elif !defined(_WIN64)
+ typedef void(__thiscall * type)(Class* const);
+#else
+ typedef void(__cdecl * type)(Class* const);
+#endif
+
+ typedef type standard_t;
+ typedef type deleting_t;
+
+ //! The standard, i.e. not deleting destructor. @warning May differ with the compiler. Use @ref destructor::call_standard instead.
+ standard_t standard;
+ //! The deleting destructor. @warning May differ with the compiler. Use @ref destructor::call_deallocating instead.
+ deleting_t deleting;
+
+ //! Call the standard contructor
+ void call_standard(Class * const ptr){ standard(ptr); }
+
+ //! Call the deleting destructor
+ void call_deleting(Class * const ptr){ deleting(ptr); }
+
+ //! True if a deleting destructor could be loaded.
+ bool has_deleting() const { return deleting != nullptr; }
+
+ //! False if neither the deleting nor the standard destructor is available.
+ bool is_empty() const { return !((deleting == nullptr) && (standard != nullptr)) ; }
+ destructor() = delete;
+
+ //! Copy destructor.
+ destructor(const destructor &) = default;
+
+ //! Construct it from both the standard destructor and the allocating destructor
+ explicit destructor(const standard_t &standard, const deleting_t &deleting = nullptr)
+ : standard(standard)
+ , deleting(deleting)
+ {}
+};
+
+#if defined(BOOST_MSVC) || defined(BOOST_MSVC_VER)
+template<typename Signature, typename Lib>
+constructor<Signature> load_ctor(Lib & lib, const mangled_storage_impl::ctor_sym & ct) {
+ typedef typename constructor<Signature>::standard_t standard_t;
+ standard_t ctor = lib.template get<standard_t>(ct);
+ return constructor<Signature>(ctor);
+}
+
+template<typename Class, typename Lib>
+destructor<Class> load_dtor(Lib & lib, const mangled_storage_impl::dtor_sym & dt) {
+ typedef typename destructor<Class>::standard_t standard_t;
+ standard_t dtor = &lib.template get< typename boost::remove_pointer<standard_t>::type >(dt);
+ return destructor<Class>(dtor);
+}
+
+#else
+
+template<typename Signature, typename Lib>
+constructor<Signature> load_ctor(Lib & lib, const mangled_storage_impl::ctor_sym & ct) {
+ typedef typename constructor<Signature>::standard_t stand;
+ typedef typename constructor<Signature>::allocating_t alloc;
+
+ stand s = nullptr;
+ alloc a = nullptr;
+
+ //see here for the abi http://mentorembedded.github.io/cxx-abi/abi.html#mangling-special-ctor-dtor
+
+ if (!ct.C1.empty()) {
+ s = lib.template get<stand>(ct.C1);
+ }
+
+ if (!ct.C3.empty()) {
+ a = lib.template get<alloc>(ct.C3);
+ }
+
+ return constructor<Signature>(s,a);
+}
+
+template<typename Class, typename Lib>
+destructor<Class> load_dtor(Lib & lib, const mangled_storage_impl::dtor_sym & dt) {
+ typedef typename destructor<Class>::standard_t stand;
+ typedef typename destructor<Class>::deleting_t delet;
+
+ stand s = nullptr;
+ delet d = nullptr;
+
+ //see here for the abi http://mentorembedded.github.io/cxx-abi/abi.html#mangling-special-ctor-dtor
+ if (!dt.D1.empty()) {
+ s = &lib.template get< typename boost::remove_pointer<stand>::type >(dt.D1);
+ }
+
+ if (!dt.D0.empty()) {
+ d = &lib.template get< typename boost::remove_pointer<delet>::type >(dt.D0);
+ }
+
+ return destructor<Class>(s,d);
+
+}
+
+#endif
+
+}}} // namespace boost::dll::detail
+
+#endif /* INCLUDE_BOOST_DLL_DETAIL_CTOR_DTOR_HPP_ */
diff --git a/boost/dll/detail/demangling/demangle_symbol.hpp b/boost/dll/detail/demangling/demangle_symbol.hpp
new file mode 100644
index 0000000000..e0590b38fa
--- /dev/null
+++ b/boost/dll/detail/demangling/demangle_symbol.hpp
@@ -0,0 +1,83 @@
+// Copyright 2015 Klemens Morgenstern
+//
+// This file provides a demangling for function names, i.e. entry points of a dll.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_DLL_DEMANGLE_SYMBOL_HPP_
+#define BOOST_DLL_DEMANGLE_SYMBOL_HPP_
+
+#include <boost/config.hpp>
+#include <string>
+#include <algorithm>
+
+#if defined(BOOST_MSVC) || defined(BOOST_MSVC_FULL_VER)
+#include <boost/detail/winapi/dbghelp.hpp>
+
+namespace boost
+{
+namespace dll
+{
+namespace detail
+{
+
+
+inline std::string demangle_symbol(const char *mangled_name)
+{
+ char unmangled_name[2048];
+
+ ::boost::detail::winapi::
+ UnDecorateSymbolName(mangled_name, unmangled_name, 2048, 0);
+
+ return std::string(unmangled_name);
+}
+inline std::string demangle_symbol(const std::string& mangled_name)
+{
+ return demangle_symbol(mangled_name.c_str());
+}
+
+
+}}}
+#else
+
+#include <boost/core/demangle.hpp>
+
+namespace boost
+{
+namespace dll
+{
+namespace detail
+{
+
+inline std::string demangle_symbol(const char *mangled_name)
+{
+
+ if (*mangled_name == '_')
+ {
+ //because it start's with an underline _
+ auto dm = boost::core::demangle(mangled_name);
+ if (!dm.empty())
+ return dm;
+ else
+ return (mangled_name);
+ }
+
+ //could not demangled
+ return "";
+
+
+}
+
+//for my personal convinience
+inline std::string demangle_symbol(const std::string& mangled_name)
+{
+ return demangle_symbol(mangled_name.c_str());
+}
+
+
+}}}
+
+#endif
+
+#endif /* INCLUDE_BOOST_DEMANGLE_HPP_ */
diff --git a/boost/dll/detail/demangling/itanium.hpp b/boost/dll/detail/demangling/itanium.hpp
new file mode 100644
index 0000000000..356a5eca82
--- /dev/null
+++ b/boost/dll/detail/demangling/itanium.hpp
@@ -0,0 +1,285 @@
+// Copyright 2016 Klemens 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_DLL_DETAIL_DEMANGLING_ITANIUM_HPP_
+#define BOOST_DLL_DETAIL_DEMANGLING_ITANIUM_HPP_
+
+#include <boost/dll/detail/demangling/mangled_storage_base.hpp>
+#include <iterator>
+#include <algorithm>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_volatile.hpp>
+#include <boost/type_traits/is_rvalue_reference.hpp>
+#include <boost/type_traits/is_lvalue_reference.hpp>
+#include <boost/type_traits/function_traits.hpp>
+
+
+namespace boost { namespace dll { namespace detail {
+
+
+
+class mangled_storage_impl : public mangled_storage_base
+{
+ template<typename T>
+ struct dummy {};
+
+ template<typename Return, typename ...Args>
+ std::vector<std::string> get_func_params(dummy<Return(Args...)>)
+ {
+ return {get_name<Args>()...};
+ }
+ template<typename Return, typename ...Args>
+ std::string get_return_type(dummy<Return(Args...)>)
+ {
+ return get_name<Return>();
+ }
+public:
+ using mangled_storage_base::mangled_storage_base;
+ struct ctor_sym
+ {
+ std::string C1;
+ std::string C2;
+ std::string C3;
+
+ bool empty() const
+ {
+ return C1.empty() && C2.empty() && C3.empty();
+ }
+ };
+
+ struct dtor_sym
+ {
+ std::string D0;
+ std::string D1;
+ std::string D2;
+ bool empty() const
+ {
+ return D0.empty() && D1.empty() && D2.empty();
+ }
+ };
+
+ template<typename T>
+ std::string get_variable(const std::string &name);
+
+ template<typename Func>
+ std::string get_function(const std::string &name);
+
+ template<typename Class, typename Func>
+ std::string get_mem_fn(const std::string &name);
+
+ template<typename Signature>
+ ctor_sym get_constructor();
+
+ template<typename Class>
+ dtor_sym get_destructor();
+
+};
+
+
+
+namespace parser
+{
+
+ inline std::string const_rule_impl(true_type ) {return " const";}
+ inline std::string const_rule_impl(false_type) {return "";}
+ template<typename T>
+ auto const_rule() {using t = is_const<typename remove_reference<T>::type>; return const_rule_impl(t());}
+
+ inline std::string volatile_rule_impl(true_type ) {return " volatile";}
+ inline std::string volatile_rule_impl(false_type) {return "";}
+ template<typename T>
+ auto volatile_rule() {using t = is_volatile<typename remove_reference<T>::type>; return volatile_rule_impl(t());}
+
+ inline std::string reference_rule_impl(false_type, false_type) {return "";}
+ inline std::string reference_rule_impl(true_type, false_type) {return "&" ;}
+ inline std::string reference_rule_impl(false_type, true_type ) {return "&&";}
+
+
+ template<typename T>
+ auto reference_rule() {using t_l = is_lvalue_reference<T>; using t_r = is_rvalue_reference<T>; return reference_rule_impl(t_l(), t_r());}
+
+ //it takes a string, because it may be overloaded.
+ template<typename T>
+ auto type_rule(const std::string & type_name)
+ {
+ using namespace std;
+
+ return type_name +
+ const_rule<T>() +
+ volatile_rule<T>() +
+ reference_rule<T>();
+ }
+
+
+ template<typename Return, typename Arg>
+ std::string arg_list(const mangled_storage_impl & ms, Return (*)(Arg))
+ {
+ using namespace std;
+ auto str = ms.get_name<Arg>();
+ return type_rule<Arg>(str);
+ }
+
+ template<typename Return, typename First, typename Second, typename ...Args>
+ std::string arg_list(const mangled_storage_impl & ms, Return (*)(First, Second, Args...))
+ {
+ auto st = ms.get_name<First>();
+
+ using next_type = Return (*)(Second, Args...);
+ return type_rule<First>(st) + ", " + arg_list(ms, next_type());
+ }
+
+ template<typename Return>
+ std::string arg_list(const mangled_storage_impl &, Return (*)())
+ {
+ return "";
+ }
+}
+
+
+
+template<typename T> std::string mangled_storage_impl::get_variable(const std::string &name)
+{
+ auto found = std::find_if(storage_.begin(), storage_.end(),
+ [&](const entry& e) {return e.demangled == name;});
+
+ if (found != storage_.end())
+ return found->mangled;
+ else
+ return "";
+}
+
+template<typename Func> std::string mangled_storage_impl::get_function(const std::string &name)
+{
+ using func_type = Func*;
+
+ auto matcher = name + '(' + parser::arg_list(*this, func_type()) + ')';
+
+ auto found = std::find_if(storage_.begin(), storage_.end(), [&](const entry& e) {return e.demangled == matcher;});
+ if (found != storage_.end())
+ return found->mangled;
+ else
+ return "";
+
+}
+
+template<typename Class, typename Func>
+std::string mangled_storage_impl::get_mem_fn(const std::string &name)
+{
+ using namespace parser;
+
+ using func_type = Func*;
+
+ std::string cname = get_name<Class>();
+
+ auto matcher = cname + "::" + name +
+ '(' + parser::arg_list(*this, func_type()) + ')'
+ + const_rule<Class>() + volatile_rule<Class>();
+
+ auto found = std::find_if(storage_.begin(), storage_.end(), [&](const entry& e) {return e.demangled == matcher;});
+
+ if (found != storage_.end())
+ return found->mangled;
+ else
+ return "";
+
+}
+
+
+template<typename Signature>
+auto mangled_storage_impl::get_constructor() -> ctor_sym
+{
+ using namespace parser;
+
+ using func_type = Signature*;
+
+ std::string ctor_name; // = class_name + "::" + name;
+ std::string unscoped_cname; //the unscoped class-name
+ {
+ auto class_name = get_return_type(dummy<Signature>());
+ auto pos = class_name.rfind("::");
+ if (pos == std::string::npos)
+ {
+ ctor_name = class_name+ "::" +class_name ;
+ unscoped_cname = class_name;
+ }
+ else
+ {
+ unscoped_cname = class_name.substr(pos+2) ;
+ ctor_name = class_name+ "::" + unscoped_cname;
+ }
+ }
+
+ auto matcher =
+ ctor_name + '(' + parser::arg_list(*this, func_type()) + ')';
+
+
+ std::vector<entry> findings;
+ std::copy_if(storage_.begin(), storage_.end(),
+ std::back_inserter(findings), [&](const entry& e) {return e.demangled == matcher;});
+
+ ctor_sym ct;
+
+ for (auto & e : findings)
+ {
+
+ if (e.mangled.find(unscoped_cname +"C1E") != std::string::npos)
+ ct.C1 = e.mangled;
+ else if (e.mangled.find(unscoped_cname +"C2E") != std::string::npos)
+ ct.C2 = e.mangled;
+ else if (e.mangled.find(unscoped_cname +"C3E") != std::string::npos)
+ ct.C3 = e.mangled;
+ }
+ return ct;
+}
+
+template<typename Class>
+auto mangled_storage_impl::get_destructor() -> dtor_sym
+{
+ std::string dtor_name; // = class_name + "::" + name;
+ std::string unscoped_cname; //the unscoped class-name
+ {
+ auto class_name = get_name<Class>();
+ auto pos = class_name.rfind("::");
+ if (pos == std::string::npos)
+ {
+ dtor_name = class_name+ "::~" + class_name + "()";
+ unscoped_cname = class_name;
+ }
+ else
+ {
+ unscoped_cname = class_name.substr(pos+2) ;
+ dtor_name = class_name+ "::~" + unscoped_cname + "()";
+ }
+ }
+
+ auto d0 = unscoped_cname + "D0Ev";
+ auto d1 = unscoped_cname + "D1Ev";
+ auto d2 = unscoped_cname + "D2Ev";
+
+ dtor_sym dt;
+ //this is so simple, i don#t need a predicate
+ for (auto & s : storage_)
+ {
+ //alright, name fits
+ if (s.demangled == dtor_name)
+ {
+ if (s.mangled.find(d0) != std::string::npos)
+ dt.D0 = s.mangled;
+ else if (s.mangled.find(d1) != std::string::npos)
+ dt.D1 = s.mangled;
+ else if (s.mangled.find(d2) != std::string::npos)
+ dt.D2 = s.mangled;
+
+ }
+ }
+ return dt;
+
+}
+
+}}}
+
+
+#endif /* INCLUDE_BOOST_DLL_DETAIL_DEMANGLING_ITANIUM_HPP_ */
diff --git a/boost/dll/detail/demangling/mangled_storage_base.hpp b/boost/dll/detail/demangling/mangled_storage_base.hpp
new file mode 100644
index 0000000000..e4bf3753f9
--- /dev/null
+++ b/boost/dll/detail/demangling/mangled_storage_base.hpp
@@ -0,0 +1,118 @@
+// Copyright 2016 Klemens 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_DLL_DETAIL_MANGLE_STORAGE_BASE_HPP_
+#define BOOST_DLL_DETAIL_MANGLE_STORAGE_BASE_HPP_
+
+#include <vector>
+#include <string>
+#include <map>
+#include <boost/dll/detail/demangling/demangle_symbol.hpp>
+#include <boost/dll/library_info.hpp>
+#include <boost/type_index/stl_type_index.hpp>
+
+namespace boost { namespace dll { namespace detail {
+
+///stores the mangled names with the demangled name.
+struct mangled_storage_base
+{
+ struct entry
+ {
+ std::string mangled;
+ std::string demangled;
+ entry() = default;
+ entry(const std::string & m, const std::string &d) : mangled(m), demangled(d) {}
+ entry(const entry&) = default;
+ entry(entry&&) = default;
+ entry &operator= (const entry&) = default;
+ entry &operator= (entry&&) = default;
+ };
+protected:
+ std::vector<entry> storage_;
+ ///if a unknown class is imported it can be overloaded by this type
+ std::map<boost::typeindex::stl_type_index, std::string> aliases_;
+public:
+ void assign(const mangled_storage_base & storage)
+ {
+ aliases_ = storage.aliases_;
+ storage_ = storage.storage_;
+ }
+ void swap( mangled_storage_base & storage)
+ {
+ aliases_.swap(storage.aliases_);
+ storage_.swap(storage.storage_);
+ }
+ void clear()
+ {
+ storage_.clear();
+ aliases_.clear();
+ }
+ const std::vector<entry> & get_storage() const {return storage_;};
+ template<typename T>
+ std::string get_name() const
+ {
+ auto tx = boost::typeindex::stl_type_index::type_id<T>();
+ auto val = (aliases_.count(tx) > 0) ? aliases_.at(tx) : tx.pretty_name();
+ return val;
+ }
+
+ mangled_storage_base() = default;
+ mangled_storage_base(mangled_storage_base&&) = default;
+ mangled_storage_base(const mangled_storage_base&) = default;
+
+ mangled_storage_base(const std::vector<std::string> & symbols) { add_symbols(symbols);}
+
+ explicit mangled_storage_base(library_info & li) : mangled_storage_base(li.symbols()) {}
+
+ explicit mangled_storage_base(
+ const boost::filesystem::path& library_path,
+ bool throw_if_not_native_format = true)
+ : mangled_storage_base(library_info(library_path, throw_if_not_native_format).symbols())
+ {
+
+ }
+
+ void load(library_info & li) { storage_.clear(); add_symbols(li.symbols()); };
+ void load(const boost::filesystem::path& library_path,
+ bool throw_if_not_native_format = true)
+ {
+ storage_.clear();
+ add_symbols(library_info(library_path, throw_if_not_native_format).symbols());
+ };
+
+ /*! Allows do add a class as alias, if the class imported is not known
+ * in this binary.
+ * @tparam Alias The Alias type
+ * @param The name to create the alias for.
+ *
+ * @note There can be multiple aliases, this is on purpose.
+ */
+ template<typename Alias> void add_alias(const std::string& name)
+ {
+ aliases_.emplace(
+ boost::typeindex::stl_type_index::type_id<Alias>(),
+ name
+ );
+ }
+ void add_symbols(const std::vector<std::string> & symbols)
+ {
+ for (auto & sym : symbols)
+ {
+ auto dm = demangle_symbol(sym);
+ if (!dm.empty())
+ storage_.emplace_back(sym, dm);
+ else
+ storage_.emplace_back(sym, sym);
+ }
+ }
+
+
+};
+
+
+}}}
+
+#endif /* INCLUDE_BOOST_DLL_DETAIL_MANGLE_STORAGE_HPP_ */
diff --git a/boost/dll/detail/demangling/msvc.hpp b/boost/dll/detail/demangling/msvc.hpp
new file mode 100644
index 0000000000..4cab143266
--- /dev/null
+++ b/boost/dll/detail/demangling/msvc.hpp
@@ -0,0 +1,400 @@
+// Copyright 2016 Klemens 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_DLL_DETAIL_DEMANGLING_MSVC_HPP_
+#define BOOST_DLL_DETAIL_DEMANGLING_MSVC_HPP_
+
+#include <boost/dll/detail/demangling/mangled_storage_base.hpp>
+#include <iterator>
+#include <algorithm>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_volatile.hpp>
+#include <boost/type_traits/is_lvalue_reference.hpp>
+#include <boost/type_traits/is_rvalue_reference.hpp>
+#include <boost/type_traits/function_traits.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+
+#include <boost/spirit/home/x3.hpp>
+
+namespace boost { namespace dll { namespace detail {
+
+class mangled_storage_impl : public mangled_storage_base
+{
+ template<typename T>
+ struct dummy {};
+
+ template<typename Return, typename ...Args>
+ std::vector<std::string> get_func_params(dummy<Return(Args...)>)
+ {
+ return {get_name<Args>()...};
+ }
+ template<typename Return, typename ...Args>
+ std::string get_return_type(dummy<Return(Args...)>)
+ {
+ return get_name<Return>();
+ }
+ //function to remove preceeding 'class ' or 'struct ' if the are given in this format.
+
+ inline static void trim_typename(std::string & val);
+public:
+ using ctor_sym = std::string;
+ using dtor_sym = std::string;
+
+ using mangled_storage_base::mangled_storage_base;
+
+ template<typename T>
+ std::string get_variable(const std::string &name);
+
+ template<typename Func>
+ std::string get_function(const std::string &name);
+
+ template<typename Class, typename Func>
+ std::string get_mem_fn(const std::string &name);
+
+ template<typename Signature>
+ ctor_sym get_constructor();
+
+ template<typename Class>
+ dtor_sym get_destructor();
+
+ template<typename T> //overload, does not need to virtual.
+ std::string get_name() const
+ {
+ auto nm = mangled_storage_base::get_name<T>();
+ trim_typename(nm);
+ return nm;
+ }
+};
+
+void mangled_storage_impl::trim_typename(std::string & val)
+{
+ //remove preceeding class or struct, because you might want to use a struct as class, et vice versa
+ if (val.size() >= 6)
+ {
+ using namespace std;
+ static constexpr char class_ [7] = "class ";
+ static constexpr char struct_[8] = "struct ";
+
+ if (equal(begin(class_), end(class_)-1, val.begin())) //aklright, starts with 'class '
+ val.erase(0, 6);
+ else if (val.size() >= 7)
+ if (equal(begin(struct_), end(struct_)-1, val.begin()))
+ val.erase(0, 7);
+ }
+}
+
+
+namespace parser
+{
+ namespace x3 = spirit::x3;
+
+ auto ptr_rule_impl(std::integral_constant<std::size_t, 32>)
+ {
+ return -((-x3::space) >> "__ptr32");
+ }
+ auto ptr_rule_impl(std::integral_constant<std::size_t, 64>)
+ {
+ return -((-x3::space) >> "__ptr64");
+ }
+
+ auto ptr_rule() { return ptr_rule_impl(std::integral_constant<std::size_t, sizeof(std::size_t)*8>());}
+
+ auto const visibility = ("public:" | x3::lit("protected:") | "private:");
+ auto const virtual_ = x3::space >> "virtual";
+ auto const static_ = x3::space >> x3::lit("static") ;
+
+ auto const_rule_impl(true_type ) {return x3::space >> "const";};
+ auto const_rule_impl(false_type) {return x3::eps;};
+ template<typename T>
+ auto const_rule() {using t = is_const<typename remove_reference<T>::type>; return const_rule_impl(t());}
+
+ auto volatile_rule_impl(true_type ) {return x3::space >> "volatile";};
+ auto volatile_rule_impl(false_type) {return x3::eps;};
+ template<typename T>
+ auto volatile_rule() {using t = is_volatile<typename remove_reference<T>::type>; return volatile_rule_impl(t());}
+
+
+ auto inv_const_rule_impl(true_type ) {return "const" >> x3::space ;};
+ auto inv_const_rule_impl(false_type) {return x3::eps;};
+ template<typename T>
+ auto inv_const_rule() {using t = is_const<typename remove_reference<T>::type>; return inv_const_rule_impl(t());}
+
+ auto inv_volatile_rule_impl(true_type ) {return "volatile" >> x3::space;};
+ auto inv_volatile_rule_impl(false_type) {return x3::eps;};
+ template<typename T>
+ auto inv_volatile_rule() {using t = is_volatile<typename remove_reference<T>::type>; return inv_volatile_rule_impl(t());}
+
+
+ auto reference_rule_impl(false_type, false_type) {return x3::eps;}
+ auto reference_rule_impl(true_type, false_type) {return x3::space >>"&" ;}
+ auto reference_rule_impl(false_type, true_type ) {return x3::space >>"&&" ;}
+
+
+ template<typename T>
+ auto reference_rule() {using t_l = is_lvalue_reference<T>; using t_r = is_rvalue_reference<T>; return reference_rule_impl(t_l(), t_r());}
+
+ auto const class_ = ("class" | x3::lit("struct"));
+
+ //it takes a string, because it may be overloaded.
+ template<typename T>
+ auto type_rule(const std::string & type_name)
+ {
+ using namespace std;
+
+ return -(class_ >> x3::space)>> x3::string(type_name) >>
+ const_rule<T>() >>
+ volatile_rule<T>() >>
+ reference_rule<T>() >>
+ ptr_rule();
+ }
+ template<>
+ auto type_rule<void>(const std::string &) { return x3::string("void"); };
+
+ auto const cdecl_ = "__cdecl" >> x3::space;
+ auto const stdcall = "__stdcall" >> x3::space;
+#if defined(_WIN64)//seems to be necessary by msvc 14-x64
+ auto const thiscall = "__cdecl" >> x3::space;
+#else
+ auto const thiscall = "__thiscall" >> x3::space;
+#endif
+
+ template<typename Return, typename Arg>
+ auto arg_list(const mangled_storage_impl & ms, Return (*)(Arg))
+ {
+ using namespace std;
+
+ return type_rule<Arg>(ms.get_name<Arg>());
+ }
+
+ template<typename Return, typename First, typename Second, typename ...Args>
+ auto arg_list(const mangled_storage_impl & ms, Return (*)(First, Second, Args...))
+ {
+
+ using next_type = Return (*)(Second, Args...);
+ return type_rule<First>(ms.get_name<First>()) >> x3::char_(',') >> arg_list(ms, next_type());
+ }
+
+ template<typename Return>
+ auto arg_list(const mangled_storage_impl & ms, Return (*)())
+ {
+ return x3::string("void");
+ }
+}
+
+
+template<typename T> std::string mangled_storage_impl::get_variable(const std::string &name)
+{
+ using namespace std;
+ using namespace boost;
+
+ namespace x3 = spirit::x3;
+ using namespace parser;
+
+ auto type_name = get_name<T>();
+
+ auto matcher =
+ -(visibility >> static_ >> x3::space) >> //it may be a static class-member
+ parser::type_rule<T>(type_name) >> x3::space >>
+ name;
+
+ auto predicate = [&](const mangled_storage_base::entry & e)
+ {
+ if (e.demangled == name)//maybe not mangled,
+ return true;
+
+ auto itr = e.demangled.begin();
+ auto end = e.demangled.end();
+ auto res = x3::parse(itr, end, matcher);
+ return res && (itr == end);
+ };
+
+ auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
+
+ if (found != storage_.end())
+ return found->mangled;
+ else
+ return "";
+}
+
+template<typename Func> std::string mangled_storage_impl::get_function(const std::string &name)
+{
+ namespace x3 = spirit::x3;
+ using namespace parser;
+ using func_type = Func*;
+ using return_type = typename function_traits<Func>::result_type;
+ std::string return_type_name = get_name<return_type>();
+
+
+ auto matcher =
+ -(visibility >> static_ >> x3::space) >> //it may be a static class-member, which does however not have the static attribute.
+ parser::type_rule<return_type>(return_type_name) >> x3::space >>
+ cdecl_ >> //cdecl declaration for methods. stdcall cannot be
+ name >> x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >> parser::ptr_rule();
+
+
+ auto predicate = [&](const mangled_storage_base::entry & e)
+ {
+ if (e.demangled == name)//maybe not mangled,
+ return true;
+
+ auto itr = e.demangled.begin();
+ auto end = e.demangled.end();
+ auto res = x3::parse(itr, end, matcher);
+
+ return res && (itr == end);
+ };
+
+ auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
+
+ if (found != storage_.end())
+ return found->mangled;
+ else
+ return "";
+
+}
+
+template<typename Class, typename Func>
+std::string mangled_storage_impl::get_mem_fn(const std::string &name)
+{
+ namespace x3 = spirit::x3;
+ using namespace parser;
+ using func_type = Func*;
+ using return_type = typename function_traits<Func>::result_type;
+ auto return_type_name = get_name<return_type>();
+
+
+ auto cname = get_name<Class>();
+
+ auto matcher =
+ visibility >> -virtual_ >> x3::space >>
+ parser::type_rule<return_type>(return_type_name) >> x3::space >>
+ thiscall >> //cdecl declaration for methods. stdcall cannot be
+ cname >> "::" >> name >>
+ x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >>
+ inv_const_rule<Class>() >> inv_volatile_rule<Class>() >> parser::ptr_rule();
+
+ auto predicate = [&](const mangled_storage_base::entry & e)
+ {
+ auto itr = e.demangled.begin();
+ auto end = e.demangled.end();
+ auto res = x3::parse(itr, end, matcher);
+
+ return res && (itr == end);
+ };
+
+ auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
+
+ if (found != storage_.end())
+ return found->mangled;
+ else
+ return "";
+}
+
+
+template<typename Signature>
+auto mangled_storage_impl::get_constructor() -> ctor_sym
+{
+ namespace x3 = spirit::x3;
+ using namespace parser;
+
+ using func_type = Signature*;
+
+
+ std::string ctor_name; // = class_name + "::" + name;
+ std::string unscoped_cname; //the unscoped class-name
+ {
+ auto class_name = get_return_type(dummy<Signature>());
+ auto pos = class_name.rfind("::");
+ if (pos == std::string::npos)
+ {
+ ctor_name = class_name+ "::" + class_name ;
+ unscoped_cname = class_name;
+ }
+ else
+ {
+ unscoped_cname = class_name.substr(pos+2) ;
+ ctor_name = class_name+ "::" + unscoped_cname;
+ }
+ }
+
+ auto matcher =
+ visibility >> x3::space >>
+ thiscall >> //cdecl declaration for methods. stdcall cannot be
+ ctor_name >>
+ x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >> parser::ptr_rule();
+
+
+ auto predicate = [&](const mangled_storage_base::entry & e)
+ {
+ auto itr = e.demangled.begin();
+ auto end = e.demangled.end();
+ auto res = x3::parse(itr, end, matcher);
+
+ return res && (itr == end);
+ };
+
+ auto f = std::find_if(storage_.begin(), storage_.end(), predicate);
+
+ if (f != storage_.end())
+ return f->mangled;
+ else
+ return "";
+}
+
+template<typename Class>
+auto mangled_storage_impl::get_destructor() -> dtor_sym
+{
+ namespace x3 = spirit::x3;
+ using namespace parser;
+ std::string dtor_name; // = class_name + "::" + name;
+ std::string unscoped_cname; //the unscoped class-name
+ {
+ auto class_name = get_name<Class>();
+ auto pos = class_name.rfind("::");
+ if (pos == std::string::npos)
+ {
+ dtor_name = class_name+ "::~" + class_name + "(void)";
+ unscoped_cname = class_name;
+ }
+ else
+ {
+ unscoped_cname = class_name.substr(pos+2) ;
+ dtor_name = class_name+ "::~" + unscoped_cname + "(void)";
+ }
+ }
+
+ auto matcher =
+ visibility >> -virtual_ >> x3::space >>
+ thiscall >> //cdecl declaration for methods. stdcall cannot be
+ dtor_name >> parser::ptr_rule();
+
+
+ auto predicate = [&](const mangled_storage_base::entry & e)
+ {
+ auto itr = e.demangled.begin();
+ auto end = e.demangled.end();
+ auto res = x3::parse(itr, end, matcher);
+
+ return res && (itr == end);
+ };
+
+ auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
+
+
+ if (found != storage_.end())
+ return found->mangled;
+ else
+ return "";
+}
+
+
+
+
+}}}
+
+
+
+#endif /* INCLUDE_BOOST_DLL_DETAIL_DEMANGLING_MSVC_HPP_ */
diff --git a/boost/dll/detail/elf_info.hpp b/boost/dll/detail/elf_info.hpp
new file mode 100644
index 0000000000..325df9cb10
--- /dev/null
+++ b/boost/dll/detail/elf_info.hpp
@@ -0,0 +1,285 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015 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_DLL_DETAIL_POSIX_ELF_INFO_HPP
+#define BOOST_DLL_DETAIL_POSIX_ELF_INFO_HPP
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <cstring>
+#include <boost/filesystem/fstream.hpp>
+#include <boost/dll/detail/x_info_interface.hpp>
+
+namespace boost { namespace dll { namespace detail {
+
+template <class AddressOffsetT>
+struct Elf_Ehdr_template {
+ unsigned char e_ident[16]; /* Magic number and other info */
+ boost::uint16_t e_type; /* Object file type */
+ boost::uint16_t e_machine; /* Architecture */
+ boost::uint32_t e_version; /* Object file version */
+ AddressOffsetT e_entry; /* Entry point virtual address */
+ AddressOffsetT e_phoff; /* Program header table file offset */
+ AddressOffsetT e_shoff; /* Section header table file offset */
+ boost::uint32_t e_flags; /* Processor-specific flags */
+ boost::uint16_t e_ehsize; /* ELF header size in bytes */
+ boost::uint16_t e_phentsize; /* Program header table entry size */
+ boost::uint16_t e_phnum; /* Program header table entry count */
+ boost::uint16_t e_shentsize; /* Section header table entry size */
+ boost::uint16_t e_shnum; /* Section header table entry count */
+ boost::uint16_t e_shstrndx; /* Section header string table index */
+};
+
+typedef Elf_Ehdr_template<boost::uint32_t> Elf32_Ehdr_;
+typedef Elf_Ehdr_template<boost::uint64_t> Elf64_Ehdr_;
+
+template <class AddressOffsetT>
+struct Elf_Shdr_template {
+ boost::uint32_t sh_name; /* Section name (string tbl index) */
+ boost::uint32_t sh_type; /* Section type */
+ AddressOffsetT sh_flags; /* Section flags */
+ AddressOffsetT sh_addr; /* Section virtual addr at execution */
+ AddressOffsetT sh_offset; /* Section file offset */
+ AddressOffsetT sh_size; /* Section size in bytes */
+ boost::uint32_t sh_link; /* Link to another section */
+ boost::uint32_t sh_info; /* Additional section information */
+ AddressOffsetT sh_addralign; /* Section alignment */
+ AddressOffsetT sh_entsize; /* Entry size if section holds table */
+};
+
+typedef Elf_Shdr_template<boost::uint32_t> Elf32_Shdr_;
+typedef Elf_Shdr_template<boost::uint64_t> Elf64_Shdr_;
+
+template <class AddressOffsetT>
+struct Elf_Sym_template;
+
+template <>
+struct Elf_Sym_template<boost::uint32_t> {
+ typedef boost::uint32_t AddressOffsetT;
+
+ boost::uint32_t st_name; /* Symbol name (string tbl index) */
+ AddressOffsetT st_value; /* Symbol value */
+ AddressOffsetT st_size; /* Symbol size */
+ unsigned char st_info; /* Symbol type and binding */
+ unsigned char st_other; /* Symbol visibility */
+ boost::uint16_t st_shndx; /* Section index */
+};
+
+template <>
+struct Elf_Sym_template<boost::uint64_t> {
+ typedef boost::uint64_t AddressOffsetT;
+
+ boost::uint32_t st_name; /* Symbol name (string tbl index) */
+ unsigned char st_info; /* Symbol type and binding */
+ unsigned char st_other; /* Symbol visibility */
+ boost::uint16_t st_shndx; /* Section index */
+ AddressOffsetT st_value; /* Symbol value */
+ AddressOffsetT st_size; /* Symbol size */
+};
+
+
+typedef Elf_Sym_template<boost::uint32_t> Elf32_Sym_;
+typedef Elf_Sym_template<boost::uint64_t> Elf64_Sym_;
+
+template <class AddressOffsetT>
+class elf_info: public x_info_interface {
+ boost::filesystem::ifstream& f_;
+
+ typedef boost::dll::detail::Elf_Ehdr_template<AddressOffsetT> header_t;
+ typedef boost::dll::detail::Elf_Shdr_template<AddressOffsetT> section_t;
+ typedef boost::dll::detail::Elf_Sym_template<AddressOffsetT> symbol_t;
+
+ BOOST_STATIC_CONSTANT(boost::uint32_t, SHT_SYMTAB_ = 2);
+ BOOST_STATIC_CONSTANT(boost::uint32_t, SHT_STRTAB_ = 3);
+
+ BOOST_STATIC_CONSTANT(unsigned char, STB_LOCAL_ = 0); /* Local symbol */
+ BOOST_STATIC_CONSTANT(unsigned char, STB_GLOBAL_ = 1); /* Global symbol */
+ BOOST_STATIC_CONSTANT(unsigned char, STB_WEAK_ = 2); /* Weak symbol */
+
+ /* Symbol visibility specification encoded in the st_other field. */
+ BOOST_STATIC_CONSTANT(unsigned char, STV_DEFAULT_ = 0); /* Default symbol visibility rules */
+ BOOST_STATIC_CONSTANT(unsigned char, STV_INTERNAL_ = 1); /* Processor specific hidden class */
+ BOOST_STATIC_CONSTANT(unsigned char, STV_HIDDEN_ = 2); /* Sym unavailable in other modules */
+ BOOST_STATIC_CONSTANT(unsigned char, STV_PROTECTED_ = 3); /* Not preemptible, not exported */
+
+public:
+ static bool parsing_supported(boost::filesystem::ifstream& f) {
+ const unsigned char magic_bytes[5] = {
+ 0x7f, 'E', 'L', 'F', sizeof(boost::uint32_t) == sizeof(AddressOffsetT) ? 1 : 2
+ };
+
+ unsigned char ch;
+ f.seekg(0);
+ for (std::size_t i = 0; i < sizeof(magic_bytes); ++i) {
+ f >> ch;
+ if (ch != magic_bytes[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ explicit elf_info(boost::filesystem::ifstream& f) BOOST_NOEXCEPT
+ : f_(f)
+ {}
+
+ std::vector<std::string> sections() {
+ std::vector<std::string> ret;
+ std::vector<char> names;
+ sections_names_raw(names);
+
+ const char* name_begin = &names[0];
+ const char* const name_end = name_begin + names.size();
+ ret.reserve(header().e_shnum);
+ do {
+ ret.push_back(name_begin);
+ name_begin += ret.back().size() + 1;
+ } while (name_begin != name_end);
+
+ return ret;
+ }
+
+private:
+ template <class T>
+ inline void read_raw(T& value, std::size_t size = sizeof(T)) const {
+ f_.read(reinterpret_cast<char*>(&value), size);
+ }
+
+ inline header_t header() {
+ header_t elf;
+
+ f_.seekg(0);
+ read_raw(elf);
+
+ return elf;
+ }
+
+ void sections_names_raw(std::vector<char>& sections) {
+ const header_t elf = header();
+
+ section_t section_names_section;
+ f_.seekg(elf.e_shoff + elf.e_shstrndx * sizeof(section_t));
+ read_raw(section_names_section);
+
+ sections.resize(static_cast<std::size_t>(section_names_section.sh_size));
+ f_.seekg(section_names_section.sh_offset);
+ read_raw(sections[0], static_cast<std::size_t>(section_names_section.sh_size));
+ }
+
+ void symbols_text(std::vector<symbol_t>& symbols, std::vector<char>& text) {
+ const header_t elf = header();
+ f_.seekg(elf.e_shoff);
+
+ for (std::size_t i = 0; i < elf.e_shnum; ++i) {
+ section_t section;
+ read_raw(section);
+
+ if (section.sh_type == SHT_SYMTAB_) {
+ symbols.resize(static_cast<std::size_t>(section.sh_size / sizeof(symbol_t)));
+
+ const boost::filesystem::ifstream::pos_type pos = f_.tellg();
+ f_.seekg(section.sh_offset);
+ read_raw(symbols[0], static_cast<std::size_t>(section.sh_size - (section.sh_size % sizeof(symbol_t))) );
+ f_.seekg(pos);
+ } else if (section.sh_type == SHT_STRTAB_) {
+ text.resize(static_cast<std::size_t>(section.sh_size));
+
+ const boost::filesystem::ifstream::pos_type pos = f_.tellg();
+ f_.seekg(section.sh_offset);
+ read_raw(text[0], static_cast<std::size_t>(section.sh_size));
+ f_.seekg(pos);
+ }
+ }
+ }
+
+ static bool is_visible(const symbol_t& sym) BOOST_NOEXCEPT {
+ // `(sym.st_info >> 4) != STB_LOCAL_ && !!sym.st_size` check also workarounds the
+ // GCC's issue https://sourceware.org/bugzilla/show_bug.cgi?id=13621
+ return (sym.st_other & 0x03) == STV_DEFAULT_ && (sym.st_info >> 4) != STB_LOCAL_ && !!sym.st_size;
+ }
+
+public:
+ std::vector<std::string> symbols() {
+ std::vector<std::string> ret;
+
+ std::vector<symbol_t> symbols;
+ std::vector<char> text;
+ symbols_text(symbols, text);
+
+ ret.reserve(symbols.size());
+ for (std::size_t i = 0; i < symbols.size(); ++i) {
+ if (is_visible(symbols[i])) {
+ ret.push_back(&text[0] + symbols[i].st_name);
+ if (ret.back().empty()) {
+ ret.pop_back(); // Do not show empty names
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ std::vector<std::string> symbols(const char* section_name) {
+ std::vector<std::string> ret;
+
+ std::size_t index = 0;
+ std::size_t ptrs_in_section_count = 0;
+ {
+ std::vector<char> names;
+ sections_names_raw(names);
+
+ const header_t elf = header();
+
+ for (; index < elf.e_shnum; ++index) {
+ section_t section;
+ f_.seekg(elf.e_shoff + index * sizeof(section_t));
+ read_raw(section);
+
+ if (!std::strcmp(&names[0] + section.sh_name, section_name)) {
+ if (!section.sh_entsize) {
+ section.sh_entsize = 1;
+ }
+ ptrs_in_section_count = static_cast<std::size_t>(section.sh_size / section.sh_entsize);
+ break;
+ }
+ }
+ }
+
+ std::vector<symbol_t> symbols;
+ std::vector<char> text;
+ symbols_text(symbols, text);
+
+ if (ptrs_in_section_count < symbols.size()) {
+ ret.reserve(ptrs_in_section_count);
+ } else {
+ ret.reserve(symbols.size());
+ }
+
+ for (std::size_t i = 0; i < symbols.size(); ++i) {
+ if (symbols[i].st_shndx == index && is_visible(symbols[i])) {
+ ret.push_back(&text[0] + symbols[i].st_name);
+ if (ret.back().empty()) {
+ ret.pop_back(); // Do not show empty names
+ }
+ }
+ }
+
+ return ret;
+ }
+};
+
+typedef elf_info<boost::uint32_t> elf_info32;
+typedef elf_info<boost::uint64_t> elf_info64;
+
+}}} // namespace boost::dll::detail
+
+#endif // BOOST_DLL_DETAIL_POSIX_ELF_INFO_HPP
diff --git a/boost/dll/detail/get_mem_fn_type.hpp b/boost/dll/detail/get_mem_fn_type.hpp
new file mode 100644
index 0000000000..65cead20bc
--- /dev/null
+++ b/boost/dll/detail/get_mem_fn_type.hpp
@@ -0,0 +1,40 @@
+// Copyright 2016 Klemens 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)
+
+// For more information, see http://www.boost.org
+
+#ifndef BOOST_DLL_SMART_LIBRARY_HPP_
+#define BOOST_DLL_SMART_LIBRARY_HPP_
+
+namespace boost { namespace dll { namespace detail {
+
+template<typename Class, typename Func>
+struct get_mem_fn_type;
+
+template<typename Class, typename Return, typename ...Args>
+struct get_mem_fn_type<Class, Return(Args...)> {
+ typedef Return (Class::*mem_fn)(Args...);
+};
+
+template<typename Class, typename Return, typename ...Args>
+struct get_mem_fn_type<const Class, Return(Args...)> {
+ typedef Return (Class::*mem_fn)(Args...) const ;
+};
+
+template<typename Class, typename Return, typename ...Args>
+struct get_mem_fn_type<volatile Class, Return(Args...)> {
+ typedef Return (Class::*mem_fn)(Args...) volatile;
+};
+
+template<typename Class, typename Return, typename ...Args>
+struct get_mem_fn_type<const volatile Class, Return(Args...)> {
+ typedef Return (Class::*mem_fn)(Args...) const volatile ;
+};
+
+}}} // namespace boost::dll::detail
+
+
+#endif /* INCLUDE_BOOST_DLL_SMART_LIBRARY_HPP_ */
diff --git a/boost/dll/detail/macho_info.hpp b/boost/dll/detail/macho_info.hpp
new file mode 100644
index 0000000000..6911908238
--- /dev/null
+++ b/boost/dll/detail/macho_info.hpp
@@ -0,0 +1,321 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015 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_DLL_DETAIL_MACHO_INFO_HPP
+#define BOOST_DLL_DETAIL_MACHO_INFO_HPP
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/filesystem/fstream.hpp>
+#include <boost/dll/detail/x_info_interface.hpp>
+
+namespace boost { namespace dll { namespace detail {
+
+typedef int integer_t;
+typedef int vm_prot_t;
+typedef integer_t cpu_type_t;
+typedef integer_t cpu_subtype_t;
+
+template <class AddressOffsetT>
+struct mach_header_template {
+ boost::uint32_t magic;
+ cpu_type_t cputype;
+ cpu_subtype_t cpusubtype;
+ boost::uint32_t filetype;
+ boost::uint32_t ncmds;
+ boost::uint32_t sizeofcmds;
+ boost::uint32_t flags[sizeof(AddressOffsetT) / sizeof(uint32_t)]; // Flags and reserved
+};
+
+typedef mach_header_template<boost::uint32_t> mach_header_32_;
+typedef mach_header_template<boost::uint64_t> mach_header_64_;
+
+struct load_command_ {
+ boost::uint32_t cmd; /* type of command */
+ boost::uint32_t cmdsize;
+};
+
+struct load_command_types {
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SEGMENT_ = 0x1); /* segment of this file to be mapped */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SYMTAB_ = 0x2); /* link-edit stab symbol table info */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SYMSEG_ = 0x3); /* link-edit gdb symbol table info (obsolete) */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_THREAD_ = 0x4); /* thread */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_UNIXTHREAD_ = 0x5); /* unix thread (includes a stack) */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LOADFVMLIB_ = 0x6); /* load a specified fixed VM shared library */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_IDFVMLIB_ = 0x7); /* fixed VM shared library identification */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_IDENT_ = 0x8); /* object identification info (obsolete) */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_FVMFILE_ = 0x9); /* fixed VM file inclusion (internal use) */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_PREPAGE_ = 0xa); /* prepage command (internal use) */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_DYSYMTAB_ = 0xb); /* dynamic link-edit symbol table info */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LOAD_DYLIB_ = 0xc); /* load a dynamically linked shared library */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ID_DYLIB_ = 0xd); /* dynamically linked shared lib ident */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LOAD_DYLINKER_ = 0xe); /* load a dynamic linker */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ID_DYLINKER_ = 0xf); /* dynamic linker identification */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_PREBOUND_DYLIB_ = 0x10); /* modules prebound for a dynamically linked shared library */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ROUTINES_ = 0x11); /* image routines */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SUB_FRAMEWORK_ = 0x12); /* sub framework */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SUB_UMBRELLA_ = 0x13); /* sub umbrella */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SUB_CLIENT_ = 0x14); /* sub client */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SUB_LIBRARY_ = 0x15); /* sub library */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_TWOLEVEL_HINTS_ = 0x16); /* two-level namespace lookup hints */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_PREBIND_CKSUM_ = 0x17); /* prebind checksum */
+/*
+ * After MacOS X 10.1 when a new load command is added that is required to be
+ * understood by the dynamic linker for the image to execute properly the
+ * LC_REQ_DYLD bit will be or'ed into the load command constant. If the dynamic
+ * linker sees such a load command it it does not understand will issue a
+ * "unknown load command required for execution" error and refuse to use the
+ * image. Other load commands without this bit that are not understood will
+ * simply be ignored.
+ */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_REQ_DYLD_ = 0x80000000);
+
+/*
+ * load a dynamically linked shared library that is allowed to be missing
+ * (all symbols are weak imported).
+ */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LOAD_WEAK_DYLIB_ = (0x18 | LC_REQ_DYLD_));
+
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SEGMENT_64_ = 0x19); /* 64-bit segment of this file to be mapped */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ROUTINES_64_ = 0x1a); /* 64-bit image routines */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_UUID_ = 0x1b); /* the uuid */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_RPATH_ = (0x1c | LC_REQ_DYLD_)); /* runpath additions */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_CODE_SIGNATURE_ = 0x1d); /* local of code signature */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SEGMENT_SPLIT_INFO_= 0x1e); /* local of info to split segments */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_REEXPORT_DYLIB_ = (0x1f | LC_REQ_DYLD_)); /* load and re-export dylib */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LAZY_LOAD_DYLIB_ = 0x20); /* delay load of dylib until first use */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ENCRYPTION_INFO_ = 0x21); /* encrypted segment information */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_DYLD_INFO_ = 0x22); /* compressed dyld information */
+ BOOST_STATIC_CONSTANT(boost::uint32_t, LC_DYLD_INFO_ONLY_ = (0x22|LC_REQ_DYLD_)); /* compressed dyld information only */
+};
+
+template <class AddressOffsetT>
+struct segment_command_template {
+ boost::uint32_t cmd; /* LC_SEGMENT_ */
+ boost::uint32_t cmdsize; /* includes sizeof section structs */
+ char segname[16]; /* segment name */
+ AddressOffsetT vmaddr; /* memory address of this segment */
+ AddressOffsetT vmsize; /* memory size of this segment */
+ AddressOffsetT fileoff; /* file offset of this segment */
+ AddressOffsetT filesize; /* amount to map from the file */
+ vm_prot_t maxprot; /* maximum VM protection */
+ vm_prot_t initprot; /* initial VM protection */
+ boost::uint32_t nsects; /* number of sections in segment */
+ boost::uint32_t flags; /* flags */
+};
+
+typedef segment_command_template<boost::uint32_t> segment_command_32_;
+typedef segment_command_template<boost::uint64_t> segment_command_64_;
+
+template <class AddressOffsetT>
+struct section_template {
+ char sectname[16]; /* name of this section */
+ char segname[16]; /* segment this section goes in */
+ AddressOffsetT addr; /* memory address of this section */
+ AddressOffsetT size; /* size in bytes of this section */
+ boost::uint32_t offset; /* file offset of this section */
+ boost::uint32_t align; /* section alignment (power of 2) */
+ boost::uint32_t reloff; /* file offset of relocation entries */
+ boost::uint32_t nreloc; /* number of relocation entries */
+ boost::uint32_t flags; /* flags (section type and attributes)*/
+ boost::uint32_t reserved[1 + sizeof(AddressOffsetT) / sizeof(uint32_t)];
+};
+
+typedef section_template<boost::uint32_t> section_32_;
+typedef section_template<boost::uint64_t> section_64_;
+
+struct symtab_command_ {
+ boost::uint32_t cmd; /* LC_SYMTAB_ */
+ boost::uint32_t cmdsize; /* sizeof(struct symtab_command) */
+ boost::uint32_t symoff; /* symbol table offset */
+ boost::uint32_t nsyms; /* number of symbol table entries */
+ boost::uint32_t stroff; /* string table offset */
+ boost::uint32_t strsize; /* string table size in bytes */
+};
+
+template <class AddressOffsetT>
+struct nlist_template {
+ boost::uint32_t n_strx;
+ boost::uint8_t n_type;
+ boost::uint8_t n_sect;
+ boost::uint16_t n_desc;
+ AddressOffsetT n_value;
+};
+
+typedef nlist_template<boost::uint32_t> nlist_32_;
+typedef nlist_template<boost::uint64_t> nlist_64_;
+
+template <class AddressOffsetT>
+class macho_info: public x_info_interface {
+ boost::filesystem::ifstream& f_;
+
+ typedef boost::dll::detail::mach_header_template<AddressOffsetT> header_t;
+ typedef boost::dll::detail::load_command_ load_command_t;
+ typedef boost::dll::detail::segment_command_template<AddressOffsetT> segment_t;
+ typedef boost::dll::detail::section_template<AddressOffsetT> section_t;
+ typedef boost::dll::detail::symtab_command_ symbol_header_t;
+ typedef boost::dll::detail::nlist_template<AddressOffsetT> nlist_t;
+
+ BOOST_STATIC_CONSTANT(boost::uint32_t, SEGMENT_CMD_NUMBER = (sizeof(AddressOffsetT) > 4 ? load_command_types::LC_SEGMENT_64_ : load_command_types::LC_SEGMENT_));
+
+public:
+ static bool parsing_supported(boost::filesystem::ifstream& f) {
+ static const uint32_t magic_bytes = (sizeof(AddressOffsetT) <= sizeof(uint32_t) ? 0xfeedface : 0xfeedfacf);
+
+ uint32_t magic;
+ f.seekg(0);
+ f.read(reinterpret_cast<char*>(&magic), sizeof(magic));
+ return (magic_bytes == magic);
+ }
+
+ explicit macho_info(boost::filesystem::ifstream& f) BOOST_NOEXCEPT
+ : f_(f)
+ {}
+
+private:
+ template <class T>
+ inline void read_raw(T& value, std::size_t size = sizeof(T)) const {
+ f_.read(reinterpret_cast<char*>(&value), size);
+ }
+
+ template <class F>
+ void command_finder(uint32_t cmd_num, F callback_f) {
+ const header_t h = header();
+ load_command_t command;
+ f_.seekg(sizeof(header_t));
+ for (std::size_t i = 0; i < h.ncmds; ++i) {
+ const boost::filesystem::ifstream::pos_type pos = f_.tellg();
+ read_raw(command);
+ if (command.cmd != cmd_num) {
+ f_.seekg(pos + static_cast<boost::filesystem::ifstream::pos_type>(command.cmdsize));
+ continue;
+ }
+
+ f_.seekg(pos);
+ callback_f(*this);
+ f_.seekg(pos + static_cast<boost::filesystem::ifstream::pos_type>(command.cmdsize));
+ }
+ }
+
+ struct section_names_gather {
+ std::vector<std::string>& ret;
+
+ void operator()(const macho_info& f) const {
+ segment_t segment;
+ f.read_raw(segment);
+
+ section_t section;
+ ret.reserve(ret.size() + segment.nsects);
+ for (std::size_t j = 0; j < segment.nsects; ++j) {
+ f.read_raw(section);
+ // `segname` goes right after the `sectname`.
+ // Forcing `sectname` to end on '\0'
+ section.segname[0] = '\0';
+ ret.push_back(section.sectname);
+ if (ret.back().empty()) {
+ ret.pop_back(); // Do not show empty names
+ }
+ }
+ }
+ };
+
+ struct symbol_names_gather {
+ std::vector<std::string>& ret;
+ std::size_t section_index;
+
+ void operator()(const macho_info& f) const {
+ symbol_header_t symbh;
+ f.read_raw(symbh);
+ ret.reserve(ret.size() + symbh.nsyms);
+
+ nlist_t symbol;
+ std::string symbol_name;
+ for (std::size_t j = 0; j < symbh.nsyms; ++j) {
+ f.f_.seekg(symbh.symoff + j * sizeof(nlist_t));
+ f.read_raw(symbol);
+ if (!symbol.n_strx) {
+ continue; // Symbol has no name
+ }
+
+ if ((symbol.n_type & 0x0e) != 0xe || !symbol.n_sect) {
+ continue; // Symbol has no section
+ }
+
+ if (section_index && section_index != symbol.n_sect) {
+ continue; // Not in the required section
+ }
+
+ f.f_.seekg(symbh.stroff + symbol.n_strx);
+ getline(f.f_, symbol_name, '\0');
+ if (symbol_name.empty()) {
+ continue;
+ }
+
+ if (symbol_name[0] == '_') {
+ // Linker adds additional '_' symbol. Could not find official docs for that case.
+ ret.push_back(symbol_name.c_str() + 1);
+ } else {
+ ret.push_back(symbol_name);
+ }
+ }
+ }
+ };
+
+public:
+ std::vector<std::string> sections() {
+ std::vector<std::string> ret;
+ section_names_gather f = { ret };
+ command_finder(SEGMENT_CMD_NUMBER, f);
+ return ret;
+ }
+
+private:
+ inline header_t header() {
+ header_t h;
+
+ f_.seekg(0);
+ read_raw(h);
+
+ return h;
+ }
+
+public:
+ std::vector<std::string> symbols() {
+ std::vector<std::string> ret;
+ symbol_names_gather f = { ret, 0 };
+ command_finder(load_command_types::LC_SYMTAB_, f);
+ return ret;
+ }
+
+ std::vector<std::string> symbols(const char* section_name) {
+ // Not very optimal solution
+ std::vector<std::string> ret = sections();
+ std::vector<std::string>::iterator it = std::find(ret.begin(), ret.end(), section_name);
+ if (it == ret.end()) {
+ // No section with such name
+ ret.clear();
+ return ret;
+ }
+
+ // section indexes start from 1
+ symbol_names_gather f = { ret, static_cast<std::size_t>(1 + (it - ret.begin())) };
+ ret.clear();
+ command_finder(load_command_types::LC_SYMTAB_, f);
+ return ret;
+ }
+};
+
+typedef macho_info<boost::uint32_t> macho_info32;
+typedef macho_info<boost::uint64_t> macho_info64;
+
+}}} // namespace boost::dll::detail
+
+#endif // BOOST_DLL_DETAIL_MACHO_INFO_HPP
diff --git a/boost/dll/detail/pe_info.hpp b/boost/dll/detail/pe_info.hpp
new file mode 100644
index 0000000000..7f1584a656
--- /dev/null
+++ b/boost/dll/detail/pe_info.hpp
@@ -0,0 +1,427 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015 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_DLL_DETAIL_WINDOWS_PE_INFO_HPP
+#define BOOST_DLL_DETAIL_WINDOWS_PE_INFO_HPP
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <boost/filesystem/fstream.hpp>
+#include <boost/dll/detail/x_info_interface.hpp>
+
+namespace boost { namespace dll { namespace detail {
+
+// reference:
+// http://www.joachim-bauch.de/tutorials/loading-a-dll-from-memory/
+// http://msdn.microsoft.com/en-us/magazine/ms809762.aspx
+// http://msdn.microsoft.com/en-us/magazine/cc301808.aspx
+//
+
+// Basic Windows typedefs. We can not use <boost/detail/winapi/basic_types.hpp> header
+// because that header must be included only on Windows platform
+typedef unsigned char BYTE_;
+typedef unsigned short WORD_;
+typedef unsigned long DWORD_;
+typedef long LONG_;
+typedef unsigned long ULONG_;
+typedef boost::int64_t LONGLONG_;
+typedef boost::uint64_t ULONGLONG_;
+
+struct IMAGE_DOS_HEADER_ { // 32/64 independent header
+ boost::dll::detail::WORD_ e_magic; // Magic number
+ boost::dll::detail::WORD_ e_cblp; // Bytes on last page of file
+ boost::dll::detail::WORD_ e_cp; // Pages in file
+ boost::dll::detail::WORD_ e_crlc; // Relocations
+ boost::dll::detail::WORD_ e_cparhdr; // Size of header in paragraphs
+ boost::dll::detail::WORD_ e_minalloc; // Minimum extra paragraphs needed
+ boost::dll::detail::WORD_ e_maxalloc; // Maximum extra paragraphs needed
+ boost::dll::detail::WORD_ e_ss; // Initial (relative) SS value
+ boost::dll::detail::WORD_ e_sp; // Initial SP value
+ boost::dll::detail::WORD_ e_csum; // Checksum
+ boost::dll::detail::WORD_ e_ip; // Initial IP value
+ boost::dll::detail::WORD_ e_cs; // Initial (relative) CS value
+ boost::dll::detail::WORD_ e_lfarlc; // File address of relocation table
+ boost::dll::detail::WORD_ e_ovno; // Overlay number
+ boost::dll::detail::WORD_ e_res[4]; // Reserved words
+ boost::dll::detail::WORD_ e_oemid; // OEM identifier (for e_oeminfo)
+ boost::dll::detail::WORD_ e_oeminfo; // OEM information; e_oemid specific
+ boost::dll::detail::WORD_ e_res2[10]; // Reserved words
+ boost::dll::detail::LONG_ e_lfanew; // File address of new exe header
+};
+
+struct IMAGE_FILE_HEADER_ { // 32/64 independent header
+ boost::dll::detail::WORD_ Machine;
+ boost::dll::detail::WORD_ NumberOfSections;
+ boost::dll::detail::DWORD_ TimeDateStamp;
+ boost::dll::detail::DWORD_ PointerToSymbolTable;
+ boost::dll::detail::DWORD_ NumberOfSymbols;
+ boost::dll::detail::WORD_ SizeOfOptionalHeader;
+ boost::dll::detail::WORD_ Characteristics;
+};
+
+struct IMAGE_DATA_DIRECTORY_ { // 32/64 independent header
+ boost::dll::detail::DWORD_ VirtualAddress;
+ boost::dll::detail::DWORD_ Size;
+};
+
+struct IMAGE_EXPORT_DIRECTORY_ { // 32/64 independent header
+ boost::dll::detail::DWORD_ Characteristics;
+ boost::dll::detail::DWORD_ TimeDateStamp;
+ boost::dll::detail::WORD_ MajorVersion;
+ boost::dll::detail::WORD_ MinorVersion;
+ boost::dll::detail::DWORD_ Name;
+ boost::dll::detail::DWORD_ Base;
+ boost::dll::detail::DWORD_ NumberOfFunctions;
+ boost::dll::detail::DWORD_ NumberOfNames;
+ boost::dll::detail::DWORD_ AddressOfFunctions;
+ boost::dll::detail::DWORD_ AddressOfNames;
+ boost::dll::detail::DWORD_ AddressOfNameOrdinals;
+};
+
+struct IMAGE_SECTION_HEADER_ { // 32/64 independent header
+ static const std::size_t IMAGE_SIZEOF_SHORT_NAME_ = 8;
+
+ boost::dll::detail::BYTE_ Name[IMAGE_SIZEOF_SHORT_NAME_];
+ union {
+ boost::dll::detail::DWORD_ PhysicalAddress;
+ boost::dll::detail::DWORD_ VirtualSize;
+ } Misc;
+ boost::dll::detail::DWORD_ VirtualAddress;
+ boost::dll::detail::DWORD_ SizeOfRawData;
+ boost::dll::detail::DWORD_ PointerToRawData;
+ boost::dll::detail::DWORD_ PointerToRelocations;
+ boost::dll::detail::DWORD_ PointerToLinenumbers;
+ boost::dll::detail::WORD_ NumberOfRelocations;
+ boost::dll::detail::WORD_ NumberOfLinenumbers;
+ boost::dll::detail::DWORD_ Characteristics;
+};
+
+
+template <class AddressOffsetT>
+struct IMAGE_OPTIONAL_HEADER_template {
+ static const std::size_t IMAGE_NUMBEROF_DIRECTORY_ENTRIES_ = 16;
+
+ boost::dll::detail::WORD_ Magic;
+ boost::dll::detail::BYTE_ MajorLinkerVersion;
+ boost::dll::detail::BYTE_ MinorLinkerVersion;
+ boost::dll::detail::DWORD_ SizeOfCode;
+ boost::dll::detail::DWORD_ SizeOfInitializedData;
+ boost::dll::detail::DWORD_ SizeOfUninitializedData;
+ boost::dll::detail::DWORD_ AddressOfEntryPoint;
+ union {
+ boost::dll::detail::DWORD_ BaseOfCode;
+ unsigned char padding_[sizeof(AddressOffsetT) == 8 ? 4 : 8]; // in x64 version BaseOfData does not exist
+ } BaseOfCode_and_BaseOfData;
+
+ AddressOffsetT ImageBase;
+ boost::dll::detail::DWORD_ SectionAlignment;
+ boost::dll::detail::DWORD_ FileAlignment;
+ boost::dll::detail::WORD_ MajorOperatingSystemVersion;
+ boost::dll::detail::WORD_ MinorOperatingSystemVersion;
+ boost::dll::detail::WORD_ MajorImageVersion;
+ boost::dll::detail::WORD_ MinorImageVersion;
+ boost::dll::detail::WORD_ MajorSubsystemVersion;
+ boost::dll::detail::WORD_ MinorSubsystemVersion;
+ boost::dll::detail::DWORD_ Win32VersionValue;
+ boost::dll::detail::DWORD_ SizeOfImage;
+ boost::dll::detail::DWORD_ SizeOfHeaders;
+ boost::dll::detail::DWORD_ CheckSum;
+ boost::dll::detail::WORD_ Subsystem;
+ boost::dll::detail::WORD_ DllCharacteristics;
+ AddressOffsetT SizeOfStackReserve;
+ AddressOffsetT SizeOfStackCommit;
+ AddressOffsetT SizeOfHeapReserve;
+ AddressOffsetT SizeOfHeapCommit;
+ boost::dll::detail::DWORD_ LoaderFlags;
+ boost::dll::detail::DWORD_ NumberOfRvaAndSizes;
+ IMAGE_DATA_DIRECTORY_ DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES_];
+};
+
+typedef IMAGE_OPTIONAL_HEADER_template<boost::dll::detail::DWORD_> IMAGE_OPTIONAL_HEADER32_;
+typedef IMAGE_OPTIONAL_HEADER_template<boost::dll::detail::ULONGLONG_> IMAGE_OPTIONAL_HEADER64_;
+
+template <class AddressOffsetT>
+struct IMAGE_NT_HEADERS_template {
+ boost::dll::detail::DWORD_ Signature;
+ IMAGE_FILE_HEADER_ FileHeader;
+ IMAGE_OPTIONAL_HEADER_template<AddressOffsetT> OptionalHeader;
+};
+
+typedef IMAGE_NT_HEADERS_template<boost::dll::detail::DWORD_> IMAGE_NT_HEADERS32_;
+typedef IMAGE_NT_HEADERS_template<boost::dll::detail::ULONGLONG_> IMAGE_NT_HEADERS64_;
+
+
+template <class AddressOffsetT>
+class pe_info: public x_info_interface {
+ boost::filesystem::ifstream& f_;
+
+ typedef IMAGE_NT_HEADERS_template<AddressOffsetT> header_t;
+ typedef IMAGE_EXPORT_DIRECTORY_ exports_t;
+ typedef IMAGE_SECTION_HEADER_ section_t;
+ typedef IMAGE_DOS_HEADER_ dos_t;
+
+ template <class T>
+ inline void read_raw(T& value, std::size_t size = sizeof(T)) const {
+ f_.read(reinterpret_cast<char*>(&value), size);
+ }
+
+public:
+ static bool parsing_supported(boost::filesystem::ifstream& f) {
+ dos_t dos;
+ f.seekg(0);
+ f.read(reinterpret_cast<char*>(&dos), sizeof(dos));
+
+ // 'MZ' and 'ZM' according to Wikipedia
+ if (dos.e_magic != 0x4D5A && dos.e_magic != 0x5A4D) {
+ return false;
+ }
+
+ header_t h;
+ f.seekg(dos.e_lfanew);
+ f.read(reinterpret_cast<char*>(&h), sizeof(h));
+
+ return h.Signature == 0x00004550 // 'PE00'
+ && h.OptionalHeader.Magic == (sizeof(boost::uint32_t) == sizeof(AddressOffsetT) ? 0x10B : 0x20B);
+ }
+
+
+ explicit pe_info(boost::filesystem::ifstream& f) BOOST_NOEXCEPT
+ : f_(f)
+ {}
+
+private:
+ inline header_t header() {
+ header_t h;
+
+ dos_t dos;
+ f_.seekg(0);
+ read_raw(dos);
+
+ f_.seekg(dos.e_lfanew);
+ read_raw(h);
+
+ return h;
+ }
+
+ inline exports_t exports(const header_t& h) {
+ exports_t exports;
+
+ static const unsigned int IMAGE_DIRECTORY_ENTRY_EXPORT_ = 0;
+ const std::size_t exp_virtual_address = h.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT_].VirtualAddress;
+
+ const std::size_t real_offset = get_file_offset(exp_virtual_address, h);
+ BOOST_ASSERT(real_offset);
+
+ f_.seekg(real_offset);
+ read_raw(exports);
+
+ return exports;
+ }
+
+ std::size_t get_file_offset(std::size_t virtual_address, const header_t& h) {
+ section_t image_section_header;
+
+ { // f_.seekg to the beginning on section headers
+ dos_t dos;
+ f_.seekg(0);
+ read_raw(dos);
+ f_.seekg(dos.e_lfanew + sizeof(header_t));
+ }
+
+ for (std::size_t i = 0;i < h.FileHeader.NumberOfSections;++i) {
+ read_raw(image_section_header);
+ if (virtual_address >= image_section_header.VirtualAddress
+ && virtual_address < image_section_header.VirtualAddress + image_section_header.SizeOfRawData)
+ {
+ return image_section_header.PointerToRawData + virtual_address - image_section_header.VirtualAddress;
+ }
+ }
+
+ return 0;
+ }
+
+public:
+ std::vector<std::string> sections() {
+ std::vector<std::string> ret;
+
+ const header_t h = header();
+ ret.reserve(h.FileHeader.NumberOfSections);
+
+ // get names, e.g: .text .rdata .data .rsrc .reloc
+ section_t image_section_header;
+ char name_helper[section_t::IMAGE_SIZEOF_SHORT_NAME_ + 1];
+ std::memset(name_helper, 0, sizeof(name_helper));
+ for (std::size_t i = 0;i < h.FileHeader.NumberOfSections;++i) {
+ // There is no terminating null character if the string is exactly eight characters long
+ read_raw(image_section_header);
+ std::memcpy(name_helper, image_section_header.Name, section_t::IMAGE_SIZEOF_SHORT_NAME_);
+
+ if (name_helper[0] != '/') {
+ ret.push_back(name_helper);
+ } else {
+ // For longer names, image_section_header.Name contains a slash (/) followed by ASCII representation of a decimal number.
+ // this number is an offset into the string table.
+ // TODO: fixme
+ ret.push_back(name_helper);
+ }
+ }
+
+ return ret;
+ }
+
+ std::vector<std::string> symbols() {
+ std::vector<std::string> ret;
+
+ const header_t h = header();
+ const exports_t exprt = exports(h);
+ const std::size_t exported_symbols = exprt.NumberOfNames;
+ const std::size_t fixed_names_addr = get_file_offset(exprt.AddressOfNames, h);
+
+ ret.reserve(exported_symbols);
+ boost::dll::detail::DWORD_ name_offset;
+ std::string symbol_name;
+ for (std::size_t i = 0;i < exported_symbols;++i) {
+ f_.seekg(fixed_names_addr + i * sizeof(name_offset));
+ read_raw(name_offset);
+ f_.seekg(get_file_offset(name_offset, h));
+ getline(f_, symbol_name, '\0');
+ ret.push_back(symbol_name);
+ }
+
+ return ret;
+ }
+
+ std::vector<std::string> symbols(const char* section_name) {
+ std::vector<std::string> ret;
+
+ const header_t h = header();
+
+ std::size_t section_begin_addr = 0;
+ std::size_t section_end_addr = 0;
+
+ { // getting address range for the section
+ section_t image_section_header;
+ char name_helper[section_t::IMAGE_SIZEOF_SHORT_NAME_ + 1];
+ std::memset(name_helper, 0, sizeof(name_helper));
+ for (std::size_t i = 0;i < h.FileHeader.NumberOfSections;++i) {
+ // There is no terminating null character if the string is exactly eight characters long
+ read_raw(image_section_header);
+ std::memcpy(name_helper, image_section_header.Name, section_t::IMAGE_SIZEOF_SHORT_NAME_);
+ if (!std::strcmp(section_name, name_helper)) {
+ section_begin_addr = image_section_header.PointerToRawData;
+ section_end_addr = section_begin_addr + image_section_header.SizeOfRawData;
+ }
+ }
+ BOOST_ASSERT(section_begin_addr);
+ BOOST_ASSERT(section_end_addr);
+ }
+
+ const exports_t exprt = exports(h);
+ const std::size_t exported_symbols = exprt.NumberOfFunctions;
+ const std::size_t fixed_names_addr = get_file_offset(exprt.AddressOfNames, h);
+ const std::size_t fixed_ordinals_addr = get_file_offset(exprt.AddressOfNameOrdinals, h);
+ const std::size_t fixed_functions_addr = get_file_offset(exprt.AddressOfFunctions, h);
+
+ ret.reserve(exported_symbols);
+ boost::dll::detail::DWORD_ ptr;
+ boost::dll::detail::WORD_ ordinal;
+ std::string symbol_name;
+ for (std::size_t i = 0;i < exported_symbols;++i) {
+ // getting ordinal
+ f_.seekg(fixed_ordinals_addr + i * sizeof(ordinal));
+ read_raw(ordinal);
+
+ // getting function addr
+ f_.seekg(fixed_functions_addr + ordinal * sizeof(ptr));
+ read_raw(ptr);
+ ptr = static_cast<boost::dll::detail::DWORD_>( get_file_offset(ptr, h) );
+
+ if (ptr >= section_end_addr || ptr < section_begin_addr) {
+ continue;
+ }
+
+ f_.seekg(fixed_names_addr + i * sizeof(ptr));
+ read_raw(ptr);
+ f_.seekg(get_file_offset(ptr, h));
+ getline(f_, symbol_name, '\0');
+ ret.push_back(symbol_name);
+ }
+
+ return ret;
+ }
+
+ // a test method to get dependents modules,
+ // who my plugin imports (1st level only)
+ /*
+ e.g. for myself I get:
+ KERNEL32.dll
+ MSVCP110D.dll
+ boost_system-vc-mt-gd-1_56.dll
+ MSVCR110D.dll
+ */
+ /*
+ std::vector<std::string> depend_of(boost::system::error_code &ec) BOOST_NOEXCEPT {
+ std::vector<std::string> ret;
+
+ IMAGE_DOS_HEADER* image_dos_header = (IMAGE_DOS_HEADER*)native();
+ if(!image_dos_header) {
+ // ERROR_BAD_EXE_FORMAT
+ ec = boost::system::error_code(
+ boost::system::errc::executable_format_error,
+ boost::system::generic_category()
+ );
+
+ return ret;
+ }
+
+ IMAGE_OPTIONAL_HEADER* image_optional_header = (IMAGE_OPTIONAL_HEADER*)((boost::dll::detail::BYTE_*)native() + image_dos_header->e_lfanew + 24);
+ if(!image_optional_header) {
+ // ERROR_BAD_EXE_FORMAT
+ ec = boost::system::error_code(
+ boost::system::errc::executable_format_error,
+ boost::system::generic_category()
+ );
+
+ return ret;
+ }
+
+ IMAGE_IMPORT_DESCRIPTOR* image_import_descriptor = (IMAGE_IMPORT_DESCRIPTOR*)((boost::dll::detail::BYTE_*)native() + image_optional_header->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
+ if(!image_import_descriptor) {
+ // ERROR_BAD_EXE_FORMAT
+ ec = boost::system::error_code(
+ boost::system::errc::executable_format_error,
+ boost::system::generic_category()
+ );
+
+ return ret;
+ }
+
+ while(image_import_descriptor->FirstThunk) {
+ std::string module_name = reinterpret_cast<char*>((boost::dll::detail::BYTE_*)native() + image_import_descriptor->Name);
+
+ if(module_name.size()) {
+ ret.push_back(module_name);
+ }
+
+ image_import_descriptor++;
+ }
+
+ return ret;
+ }
+*/
+};
+
+typedef pe_info<boost::dll::detail::DWORD_> pe_info32;
+typedef pe_info<boost::dll::detail::ULONGLONG_> pe_info64;
+
+}}} // namespace boost::dll::detail
+
+#endif // BOOST_DLL_DETAIL_WINDOWS_PE_INFO_HPP
diff --git a/boost/dll/detail/posix/path_from_handle.hpp b/boost/dll/detail/posix/path_from_handle.hpp
new file mode 100644
index 0000000000..a2787623d6
--- /dev/null
+++ b/boost/dll/detail/posix/path_from_handle.hpp
@@ -0,0 +1,169 @@
+// Copyright 2014-2015 Renato Tegon Forti, 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_DLL_DETAIL_POSIX_PATH_FROM_HANDLE_HPP
+#define BOOST_DLL_DETAIL_POSIX_PATH_FROM_HANDLE_HPP
+
+#include <boost/config.hpp>
+#include <boost/dll/detail/system_error.hpp>
+#include <boost/dll/detail/posix/program_location_impl.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/predef/os.h>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#if BOOST_OS_MACOS || BOOST_OS_IOS
+
+# include <mach-o/dyld.h>
+# include <mach-o/nlist.h>
+# include <cstddef> // for std::ptrdiff_t
+
+namespace boost { namespace dll { namespace detail {
+ inline void* strip_handle(void* handle) BOOST_NOEXCEPT {
+ return reinterpret_cast<void*>(
+ (reinterpret_cast<std::ptrdiff_t>(handle) >> 2) << 2
+ );
+ }
+
+ inline boost::filesystem::path path_from_handle(void* handle, boost::system::error_code &ec) {
+ handle = strip_handle(handle);
+
+ // Iterate through all images currently in memory
+ // https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dyld.3.html
+ const std::size_t count = _dyld_image_count(); // not thread safe: other thread my [un]load images
+ for (std::size_t i = 0; i <= count; ++i) {
+ // on last iteration `i` is equal to `count` which is out of range, so `_dyld_get_image_name`
+ // will return NULL. `dlopen(NULL, RTLD_LAZY)` call will open the current executable.
+ const char* image_name = _dyld_get_image_name(i);
+
+ // dlopen/dlclose must not affect `_dyld_image_count()`, because libraries are already loaded and only the internal counter is affected
+ void* probe_handle = dlopen(image_name, RTLD_LAZY);
+ dlclose(probe_handle);
+
+ // If the handle is the same as what was passed in (modulo mode bits), return this image name
+ if (handle == strip_handle(probe_handle)) {
+ boost::dll::detail::reset_dlerror();
+ return image_name;
+ }
+ }
+
+ boost::dll::detail::reset_dlerror();
+ ec = boost::system::error_code(
+ boost::system::errc::bad_file_descriptor,
+ boost::system::generic_category()
+ );
+
+ return boost::filesystem::path();
+ }
+
+}}} // namespace boost::dll::detail
+
+#elif BOOST_OS_ANDROID
+
+#include <boost/dll/runtime_symbol_info.hpp>
+
+namespace boost { namespace dll { namespace detail {
+
+ struct soinfo {
+ // if defined(__work_around_b_24465209__), then an array of char[128] goes here.
+ // Unfortunately, __work_around_b_24465209__ is visible only during compilation of Android's linker
+ const void* phdr;
+ size_t phnum;
+ void* entry;
+ void* base;
+ // ... // Ignoring remaning parts of the structure
+ };
+
+ inline boost::filesystem::path path_from_handle(const void* handle, boost::system::error_code &ec) {
+ static const std::size_t work_around_b_24465209__offset = 128;
+ const struct soinfo* si = reinterpret_cast<const struct soinfo*>(
+ static_cast<const char*>(handle) + work_around_b_24465209__offset
+ );
+ boost::filesystem::path ret = boost::dll::detail::symbol_location_impl(si->base, ec);
+
+ if (ec) {
+ ec.clear();
+ si = static_cast<const struct soinfo*>(handle);
+ return boost::dll::detail::symbol_location_impl(si->base, ec);
+ }
+
+ return ret;
+ }
+
+}}} // namespace boost::dll::detail
+
+#else // #if BOOST_OS_MACOS || BOOST_OS_IOS || BOOST_OS_ANDROID
+
+// for dlinfo
+#include <dlfcn.h>
+
+#if BOOST_OS_QNX
+// QNX's copy of <elf.h> and <link.h> reside in sys folder
+# include <sys/link.h>
+#else
+# include <link.h> // struct link_map
+#endif
+
+namespace boost { namespace dll { namespace detail {
+
+#if BOOST_OS_QNX
+ // Android and QNX miss struct link_map. QNX misses ElfW macro, so avoiding it.
+ struct link_map {
+ void *l_addr; // Base address shared object is loaded at
+ char *l_name; // Absolute file name object was found in
+ // ... // Ignoring remaning parts of the structure
+ };
+#endif // #if BOOST_OS_QNX
+
+ inline boost::filesystem::path path_from_handle(void* handle, boost::system::error_code &ec) {
+ // RTLD_DI_LINKMAP (RTLD_DI_ORIGIN returns only folder and is not suitable for this case)
+ // Obtain the Link_map for the handle that is specified.
+ // The p argument points to a Link_map pointer (Link_map
+ // **p). The actual storage for the Link_map structure is
+ // maintained by ld.so.1.
+ //
+ // Unfortunately we can not use `dlinfo(handle, RTLD_DI_LINKMAP, &link_map) < 0`
+ // because it is not supported on MacOS X 10.3, NetBSD 3.0, OpenBSD 3.8, AIX 5.1,
+ // HP-UX 11, IRIX 6.5, OSF/1 5.1, Cygwin, mingw, Interix 3.5, BeOS.
+ // Fortunately investigating the sources of open source projects brought the understanding, that
+ // `handle` is just a `struct link_map*` that contains full library name.
+
+ const struct link_map* link_map = 0;
+#if BOOST_OS_BSD_FREE
+ // FreeBSD has it's own logic http://code.metager.de/source/xref/freebsd/libexec/rtld-elf/rtld.c
+ // Fortunately it has the dlinfo call.
+ if (dlinfo(handle, RTLD_DI_LINKMAP, &link_map) < 0) {
+ link_map = 0;
+ }
+#else
+ link_map = static_cast<const struct link_map*>(handle);
+#endif
+ if (!link_map) {
+ boost::dll::detail::reset_dlerror();
+ ec = boost::system::error_code(
+ boost::system::errc::bad_file_descriptor,
+ boost::system::generic_category()
+ );
+
+ return boost::filesystem::path();
+ }
+
+ if (!link_map->l_name || *link_map->l_name == '\0') {
+ return program_location_impl(ec);
+ }
+
+ return boost::filesystem::path(link_map->l_name);
+ }
+
+}}} // namespace boost::dll::detail
+
+#endif // #if BOOST_OS_MACOS || BOOST_OS_IOS
+
+#endif // BOOST_DLL_DETAIL_POSIX_PATH_FROM_HANDLE_HPP
+
+
diff --git a/boost/dll/detail/posix/program_location_impl.hpp b/boost/dll/detail/posix/program_location_impl.hpp
new file mode 100644
index 0000000000..bca9b8caef
--- /dev/null
+++ b/boost/dll/detail/posix/program_location_impl.hpp
@@ -0,0 +1,140 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015 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_DLL_DETAIL_POSIX_PROGRAM_LOCATION_IMPL_HPP
+#define BOOST_DLL_DETAIL_POSIX_PROGRAM_LOCATION_IMPL_HPP
+
+#include <boost/config.hpp>
+#include <boost/dll/detail/system_error.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/predef/os.h>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#if BOOST_OS_MACOS || BOOST_OS_IOS
+
+#include <mach-o/dyld.h>
+
+namespace boost { namespace dll { namespace detail {
+ inline boost::filesystem::path program_location_impl(boost::system::error_code &ec) {
+ ec.clear();
+
+ char path[1024];
+ uint32_t size = sizeof(path);
+ if (_NSGetExecutablePath(path, &size) == 0)
+ return boost::filesystem::path(path);
+
+ char *p = new char[size];
+ if (_NSGetExecutablePath(p, &size) != 0) {
+ ec = boost::system::error_code(
+ boost::system::errc::bad_file_descriptor,
+ boost::system::generic_category()
+ );
+ }
+
+ boost::filesystem::path ret(p);
+ delete[] p;
+ return ret;
+ }
+}}} // namespace boost::dll::detail
+
+#elif BOOST_OS_SOLARIS
+
+#include <stdlib.h>
+namespace boost { namespace dll { namespace detail {
+ inline boost::filesystem::path program_location_impl(boost::system::error_code& ec) {
+ ec.clear();
+
+ return boost::filesystem::path(getexecname());
+ }
+}}} // namespace boost::dll::detail
+
+#elif BOOST_OS_BSD_FREE
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <stdlib.h>
+
+namespace boost { namespace dll { namespace detail {
+ inline boost::filesystem::path program_location_impl(boost::system::error_code& ec) {
+ ec.clear();
+
+ int mib[4];
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PATHNAME;
+ mib[3] = -1;
+ char buf[10240];
+ size_t cb = sizeof(buf);
+ sysctl(mib, 4, buf, &cb, NULL, 0);
+
+ return boost::filesystem::path(buf);
+ }
+}}} // namespace boost::dll::detail
+
+
+
+#elif BOOST_OS_BSD_NET
+
+#include <boost/filesystem/operations.hpp>
+namespace boost { namespace dll { namespace detail {
+ inline boost::filesystem::path program_location_impl(boost::system::error_code &ec) {
+ return boost::filesystem::read_symlink("/proc/curproc/exe", ec);
+ }
+}}} // namespace boost::dll::detail
+
+#elif BOOST_OS_BSD_DRAGONFLY
+
+#include <boost/filesystem/operations.hpp>
+namespace boost { namespace dll { namespace detail {
+ inline boost::filesystem::path program_location_impl(boost::system::error_code &ec) {
+ return boost::filesystem::read_symlink("/proc/curproc/file", ec);
+ }
+}}} // namespace boost::dll::detail
+
+#elif BOOST_OS_QNX
+
+#include <fstream>
+#include <string> // for std::getline
+namespace boost { namespace dll { namespace detail {
+ inline boost::filesystem::path program_location_impl(boost::system::error_code &ec) {
+ ec.clear();
+
+ std::string s;
+ std::ifstream ifs("/proc/self/exefile");
+ std::getline(ifs, s);
+
+ if (ifs.fail() || s.empty()) {
+ ec = boost::system::error_code(
+ boost::system::errc::bad_file_descriptor,
+ boost::system::generic_category()
+ );
+ }
+
+ return boost::filesystem::path(s);
+ }
+}}} // namespace boost::dll::detail
+
+#else // BOOST_OS_LINUX || BOOST_OS_UNIX || BOOST_OS_HPUX || BOOST_OS_ANDROID
+
+#include <boost/filesystem/operations.hpp>
+namespace boost { namespace dll { namespace detail {
+ inline boost::filesystem::path program_location_impl(boost::system::error_code &ec) {
+ // We can not use
+ // boost::dll::detail::path_from_handle(dlopen(NULL, RTLD_LAZY | RTLD_LOCAL), ignore);
+ // because such code returns empty path.
+
+ return boost::filesystem::read_symlink("/proc/self/exe", ec); // Linux specific
+ }
+}}} // namespace boost::dll::detail
+
+#endif
+
+#endif // BOOST_DLL_DETAIL_POSIX_PROGRAM_LOCATION_IMPL_HPP
+
diff --git a/boost/dll/detail/posix/shared_library_impl.hpp b/boost/dll/detail/posix/shared_library_impl.hpp
new file mode 100644
index 0000000000..509e6c7487
--- /dev/null
+++ b/boost/dll/detail/posix/shared_library_impl.hpp
@@ -0,0 +1,215 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015-2016 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_DLL_SHARED_LIBRARY_IMPL_HPP
+#define BOOST_DLL_SHARED_LIBRARY_IMPL_HPP
+
+#include <boost/config.hpp>
+#include <boost/dll/shared_library_load_mode.hpp>
+#include <boost/dll/detail/posix/path_from_handle.hpp>
+#include <boost/dll/detail/posix/program_location_impl.hpp>
+
+#include <boost/move/utility.hpp>
+#include <boost/swap.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/predef/os.h>
+
+#include <dlfcn.h>
+#include <cstring> // strncmp
+#if !BOOST_OS_MACOS && !BOOST_OS_IOS && !BOOST_OS_QNX
+# include <link.h>
+#elif BOOST_OS_QNX
+// QNX's copy of <elf.h> and <link.h> reside in sys folder
+# include <sys/link.h>
+#endif
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+namespace boost { namespace dll { namespace detail {
+
+class shared_library_impl {
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(shared_library_impl)
+
+public:
+ typedef void* native_handle_t;
+
+ shared_library_impl() BOOST_NOEXCEPT
+ : handle_(NULL)
+ {}
+
+ ~shared_library_impl() BOOST_NOEXCEPT {
+ unload();
+ }
+
+ shared_library_impl(BOOST_RV_REF(shared_library_impl) sl) BOOST_NOEXCEPT
+ : handle_(sl.handle_)
+ {
+ sl.handle_ = NULL;
+ }
+
+ shared_library_impl & operator=(BOOST_RV_REF(shared_library_impl) sl) BOOST_NOEXCEPT {
+ swap(sl);
+ return *this;
+ }
+
+ void load(boost::filesystem::path sl, load_mode::type mode, boost::system::error_code &ec) {
+ typedef int native_mode_t;
+ unload();
+
+ // Do not allow opening NULL paths. User must use program_location() instead
+ if (sl.empty()) {
+ boost::dll::detail::reset_dlerror();
+ ec = boost::system::error_code(
+ boost::system::errc::bad_file_descriptor,
+ boost::system::generic_category()
+ );
+
+ return;
+ }
+
+ // Fixing modes
+ if (!(mode & load_mode::rtld_now)) {
+ mode |= load_mode::rtld_lazy;
+ }
+
+ if (!(mode & load_mode::rtld_global)) {
+ mode |= load_mode::rtld_local;
+ }
+
+#if BOOST_OS_LINUX || BOOST_OS_ANDROID
+ if (!sl.has_parent_path() && !(mode & load_mode::search_system_folders)) {
+ sl = "." / sl;
+ }
+#else
+ if (!sl.is_absolute() && !(mode & load_mode::search_system_folders)) {
+ boost::system::error_code current_path_ec;
+ boost::filesystem::path prog_loc = boost::filesystem::current_path(current_path_ec);
+ if (!current_path_ec) {
+ prog_loc /= sl;
+ sl.swap(prog_loc);
+ }
+ }
+#endif
+
+ mode &= ~load_mode::search_system_folders;
+
+ // Trying to open with appended decorations
+ if (!!(mode & load_mode::append_decorations)) {
+ mode &= ~load_mode::append_decorations;
+
+ boost::filesystem::path actual_path = (
+ std::strncmp(sl.filename().string().c_str(), "lib", 3)
+ ? (sl.has_parent_path() ? sl.parent_path() / L"lib" : L"lib").native() + sl.filename().native()
+ : sl
+ );
+ actual_path += suffix();
+
+ handle_ = dlopen(actual_path.c_str(), static_cast<native_mode_t>(mode));
+ if (handle_) {
+ boost::dll::detail::reset_dlerror();
+ return;
+ }
+ }
+
+ // Opening by exactly specified path
+ handle_ = dlopen(sl.c_str(), static_cast<native_mode_t>(mode));
+ if (handle_) {
+ boost::dll::detail::reset_dlerror();
+ return;
+ }
+
+ ec = boost::system::error_code(
+ boost::system::errc::bad_file_descriptor,
+ boost::system::generic_category()
+ );
+
+ // Maybe user wanted to load the executable itself? Checking...
+ // We assume that usually user wants to load a dynamic library not the executable itself, that's why
+ // we try this only after traditional load fails.
+ boost::system::error_code prog_loc_err;
+ boost::filesystem::path loc = boost::dll::detail::program_location_impl(prog_loc_err);
+ if (!prog_loc_err && boost::filesystem::equivalent(sl, loc, prog_loc_err) && !prog_loc_err) {
+ // As is known the function dlopen() loads the dynamic library file
+ // named by the null-terminated string filename and returns an opaque
+ // "handle" for the dynamic library. If filename is NULL, then the
+ // returned handle is for the main program.
+ ec.clear();
+ boost::dll::detail::reset_dlerror();
+ handle_ = dlopen(NULL, static_cast<native_mode_t>(mode));
+ if (!handle_) {
+ ec = boost::system::error_code(
+ boost::system::errc::bad_file_descriptor,
+ boost::system::generic_category()
+ );
+ }
+ }
+ }
+
+ bool is_loaded() const BOOST_NOEXCEPT {
+ return (handle_ != 0);
+ }
+
+ void unload() BOOST_NOEXCEPT {
+ if (!is_loaded()) {
+ return;
+ }
+
+ dlclose(handle_);
+ handle_ = 0;
+ }
+
+ void swap(shared_library_impl& rhs) BOOST_NOEXCEPT {
+ boost::swap(handle_, rhs.handle_);
+ }
+
+ boost::filesystem::path full_module_path(boost::system::error_code &ec) const {
+ return boost::dll::detail::path_from_handle(handle_, ec);
+ }
+
+ static boost::filesystem::path suffix() {
+ // https://sourceforge.net/p/predef/wiki/OperatingSystems/
+#if BOOST_OS_MACOS || BOOST_OS_IOS
+ return ".dylib";
+#else
+ return ".so";
+#endif
+ }
+
+ void* symbol_addr(const char* sb, boost::system::error_code &ec) const BOOST_NOEXCEPT {
+ // dlsym - obtain the address of a symbol from a dlopen object
+ void* const symbol = dlsym(handle_, sb);
+ if (symbol == NULL) {
+ ec = boost::system::error_code(
+ boost::system::errc::invalid_seek,
+ boost::system::generic_category()
+ );
+ }
+
+ // If handle does not refer to a valid object opened by dlopen(),
+ // or if the named symbol cannot be found within any of the objects
+ // associated with handle, dlsym() shall return NULL.
+ // More detailed diagnostic information shall be available through dlerror().
+
+ return symbol;
+ }
+
+ native_handle_t native() const BOOST_NOEXCEPT {
+ return handle_;
+ }
+
+private:
+ native_handle_t handle_;
+};
+
+}}} // boost::dll::detail
+
+#endif // BOOST_DLL_SHARED_LIBRARY_IMPL_HPP
+
diff --git a/boost/dll/detail/system_error.hpp b/boost/dll/detail/system_error.hpp
new file mode 100644
index 0000000000..c032633a0b
--- /dev/null
+++ b/boost/dll/detail/system_error.hpp
@@ -0,0 +1,56 @@
+// Copyright 2014 Renato Tegon Forti, 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_DLL_SYSTEM_ERROR_HPP
+#define BOOST_DLL_SYSTEM_ERROR_HPP
+
+#include <boost/config.hpp>
+#include <boost/predef/os.h>
+#include <boost/system/error_code.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/throw_exception.hpp>
+
+#if !BOOST_OS_WINDOWS
+# include <dlfcn.h>
+#endif
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+namespace boost { namespace dll { namespace detail {
+
+ inline void reset_dlerror() BOOST_NOEXCEPT {
+#if !BOOST_OS_WINDOWS
+ const char* const error_txt = dlerror();
+ (void)error_txt;
+#endif
+ }
+
+ inline void report_error(const boost::system::error_code& ec, const char* message) {
+#if !BOOST_OS_WINDOWS
+ const char* const error_txt = dlerror();
+ if (error_txt) {
+ boost::throw_exception(
+ boost::system::system_error(
+ ec,
+ message + std::string(" (dlerror system message: ") + error_txt + std::string(")")
+ )
+ );
+ }
+#endif
+
+ boost::throw_exception(
+ boost::system::system_error(
+ ec, message
+ )
+ );
+ }
+
+}}} // boost::dll::detail
+
+#endif // BOOST_DLL_SYSTEM_ERROR_HPP
+
diff --git a/boost/dll/detail/windows/path_from_handle.hpp b/boost/dll/detail/windows/path_from_handle.hpp
new file mode 100644
index 0000000000..37eee86428
--- /dev/null
+++ b/boost/dll/detail/windows/path_from_handle.hpp
@@ -0,0 +1,62 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015 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_DLL_DETAIL_WINDOWS_PATH_FROM_HANDLE_HPP
+#define BOOST_DLL_DETAIL_WINDOWS_PATH_FROM_HANDLE_HPP
+
+#include <boost/config.hpp>
+#include <boost/dll/detail/system_error.hpp>
+#include <boost/detail/winapi/dll.hpp>
+#include <boost/detail/winapi/get_last_error.hpp>
+#include <boost/filesystem/path.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+namespace boost { namespace dll { namespace detail {
+
+ static inline boost::system::error_code last_error_code() BOOST_NOEXCEPT {
+ boost::detail::winapi::DWORD_ err = boost::detail::winapi::GetLastError();
+ return boost::system::error_code(
+ err,
+ boost::system::system_category()
+ );
+ }
+
+ inline boost::filesystem::path path_from_handle(boost::detail::winapi::HMODULE_ handle, boost::system::error_code &ec) {
+ BOOST_STATIC_CONSTANT(boost::detail::winapi::DWORD_, ERROR_INSUFFICIENT_BUFFER_ = 0x7A);
+ BOOST_STATIC_CONSTANT(boost::detail::winapi::DWORD_, DEFAULT_PATH_SIZE_ = 260);
+
+ // If `handle` parameter is NULL, GetModuleFileName retrieves the path of the
+ // executable file of the current process.
+ boost::detail::winapi::WCHAR_ path_hldr[DEFAULT_PATH_SIZE_];
+ boost::detail::winapi::GetModuleFileNameW(handle, path_hldr, DEFAULT_PATH_SIZE_);
+ ec = last_error_code();
+ if (!ec) {
+ return boost::filesystem::path(path_hldr);
+ }
+
+ for (unsigned i = 2; i < 1025 && static_cast<boost::detail::winapi::DWORD_>(ec.value()) == ERROR_INSUFFICIENT_BUFFER_; i *= 2) {
+ std::wstring p(DEFAULT_PATH_SIZE_ * i, L'\0');
+ const std::size_t size = boost::detail::winapi::GetModuleFileNameW(handle, &p[0], DEFAULT_PATH_SIZE_ * i);
+ ec = last_error_code();
+
+ if (!ec) {
+ p.resize(size);
+ return boost::filesystem::path(p);
+ }
+ }
+
+ // Error other than ERROR_INSUFFICIENT_BUFFER_ occurred or failed to allocate buffer big enough
+ return boost::filesystem::path();
+ }
+
+}}} // namespace boost::dll::detail
+
+#endif // BOOST_DLL_DETAIL_WINDOWS_PATH_FROM_HANDLE_HPP
+
diff --git a/boost/dll/detail/windows/shared_library_impl.hpp b/boost/dll/detail/windows/shared_library_impl.hpp
new file mode 100644
index 0000000000..48156505f4
--- /dev/null
+++ b/boost/dll/detail/windows/shared_library_impl.hpp
@@ -0,0 +1,177 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015-2016 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_DLL_SHARED_LIBRARY_IMPL_HPP
+#define BOOST_DLL_SHARED_LIBRARY_IMPL_HPP
+
+#include <boost/config.hpp>
+#include <boost/dll/shared_library_load_mode.hpp>
+#include <boost/dll/detail/aggressive_ptr_cast.hpp>
+#include <boost/dll/detail/system_error.hpp>
+#include <boost/dll/detail/windows/path_from_handle.hpp>
+
+#include <boost/move/utility.hpp>
+#include <boost/swap.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/operations.hpp>
+
+#include <boost/detail/winapi/dll.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+namespace boost { namespace dll { namespace detail {
+
+class shared_library_impl {
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(shared_library_impl)
+
+public:
+ typedef boost::detail::winapi::HMODULE_ native_handle_t;
+
+ shared_library_impl() BOOST_NOEXCEPT
+ : handle_(NULL)
+ {}
+
+ ~shared_library_impl() BOOST_NOEXCEPT {
+ unload();
+ }
+
+ shared_library_impl(BOOST_RV_REF(shared_library_impl) sl) BOOST_NOEXCEPT
+ : handle_(sl.handle_)
+ {
+ sl.handle_ = NULL;
+ }
+
+ shared_library_impl & operator=(BOOST_RV_REF(shared_library_impl) sl) BOOST_NOEXCEPT {
+ swap(sl);
+ return *this;
+ }
+
+ void load(boost::filesystem::path sl, load_mode::type mode, boost::system::error_code &ec) {
+ typedef boost::detail::winapi::DWORD_ native_mode_t;
+ unload();
+
+ if (!sl.is_absolute() && !(mode & load_mode::search_system_folders)) {
+
+ boost::system::error_code current_path_ec;
+ boost::filesystem::path prog_loc = boost::filesystem::current_path(current_path_ec);
+ if (!current_path_ec) {
+ prog_loc /= sl;
+ sl.swap(prog_loc);
+ }
+ }
+ mode &= ~load_mode::search_system_folders;
+
+ // Trying to open with appended decorations
+ if (!!(mode & load_mode::append_decorations)) {
+ mode &= ~load_mode::append_decorations;
+
+ handle_ = boost::detail::winapi::LoadLibraryExW((sl.native() + L".dll").c_str(), 0, static_cast<native_mode_t>(mode));
+ if (!handle_) {
+ // MinGW loves 'lib' prefix and puts it even on Windows platform
+ const boost::filesystem::path load_path = (sl.has_parent_path() ? sl.parent_path() / L"lib" : L"lib").native() + sl.filename().native() + L".dll";
+ handle_ = boost::detail::winapi::LoadLibraryExW(
+ load_path.c_str(),
+ 0,
+ static_cast<native_mode_t>(mode)
+ );
+ }
+
+ if (handle_) {
+ return;
+ }
+ }
+
+ // From MSDN: If the string specifies a module name without a path and the
+ // file name extension is omitted, the function appends the default library
+ // extension .dll to the module name.
+ //
+ // From experiments: Default library extension appended to the module name even if
+ // we have some path. So we do not check for path, only for extension. We can not be sure that
+ // such behavior remain across all platforms, so we add L"." by hand.
+ if (sl.has_extension()) {
+ handle_ = boost::detail::winapi::LoadLibraryExW(sl.c_str(), 0, static_cast<native_mode_t>(mode));
+ } else {
+ handle_ = boost::detail::winapi::LoadLibraryExW((sl.native() + L".").c_str(), 0, static_cast<native_mode_t>(mode));
+ }
+
+ // LoadLibraryExW method is capable of self loading from program_location() path. No special actions
+ // must be taken to allow self loading.
+
+ if (!handle_) {
+ ec = boost::dll::detail::last_error_code();
+ }
+ }
+
+ bool is_loaded() const BOOST_NOEXCEPT {
+ return (handle_ != 0);
+ }
+
+ void unload() BOOST_NOEXCEPT {
+ if (handle_) {
+ boost::detail::winapi::FreeLibrary(handle_);
+ handle_ = 0;
+ }
+ }
+
+ void swap(shared_library_impl& rhs) BOOST_NOEXCEPT {
+ boost::swap(handle_, rhs.handle_);
+ }
+
+ boost::filesystem::path full_module_path(boost::system::error_code &ec) const {
+ return boost::dll::detail::path_from_handle(handle_, ec);
+ }
+
+ static boost::filesystem::path suffix() {
+ return L".dll";
+ }
+
+ void* symbol_addr(const char* sb, boost::system::error_code &ec) const BOOST_NOEXCEPT {
+ if (is_resource()) {
+ // `GetProcAddress` could not be called for libraries loaded with
+ // `LOAD_LIBRARY_AS_DATAFILE`, `LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE`
+ // or `LOAD_LIBRARY_AS_IMAGE_RESOURCE`.
+ ec = boost::system::error_code(
+ boost::system::errc::operation_not_supported,
+ boost::system::generic_category()
+ );
+
+ return NULL;
+ }
+
+ // Judging by the documentation of GetProcAddress
+ // there is no version for UNICODE on desktop/server Windows, because
+ // names of functions are stored in narrow characters.
+ void* const symbol = boost::dll::detail::aggressive_ptr_cast<void*>(
+ boost::detail::winapi::get_proc_address(handle_, sb)
+ );
+ if (symbol == NULL) {
+ ec = boost::dll::detail::last_error_code();
+ }
+
+ return symbol;
+ }
+
+ native_handle_t native() const BOOST_NOEXCEPT {
+ return handle_;
+ }
+
+private:
+ bool is_resource() const BOOST_NOEXCEPT {
+ return false; /*!!(
+ reinterpret_cast<boost::detail::winapi::ULONG_PTR_>(handle_) & static_cast<boost::detail::winapi::ULONG_PTR_>(3)
+ );*/
+ }
+
+ native_handle_t handle_;
+};
+
+}}} // boost::dll::detail
+
+#endif // BOOST_DLL_SHARED_LIBRARY_IMPL_HPP
+
diff --git a/boost/dll/detail/x_info_interface.hpp b/boost/dll/detail/x_info_interface.hpp
new file mode 100644
index 0000000000..e53214e1cd
--- /dev/null
+++ b/boost/dll/detail/x_info_interface.hpp
@@ -0,0 +1,32 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015 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_DLL_DETAIL_X_INFO_INTERFACE_HPP
+#define BOOST_DLL_DETAIL_X_INFO_INTERFACE_HPP
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <string>
+#include <vector>
+
+namespace boost { namespace dll { namespace detail {
+
+class x_info_interface {
+public:
+ virtual std::vector<std::string> sections() = 0;
+ virtual std::vector<std::string> symbols() = 0;
+ virtual std::vector<std::string> symbols(const char* section_name) = 0;
+
+ virtual ~x_info_interface() BOOST_NOEXCEPT {}
+};
+
+}}} // namespace boost::dll::detail
+
+#endif // BOOST_DLL_DETAIL_X_INFO_INTERFACE_HPP
diff --git a/boost/dll/import.hpp b/boost/dll/import.hpp
new file mode 100644
index 0000000000..dcf3086a18
--- /dev/null
+++ b/boost/dll/import.hpp
@@ -0,0 +1,277 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015-2016 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_DLL_IMPORT_HPP
+#define BOOST_DLL_IMPORT_HPP
+
+#include <boost/config.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/is_object.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/dll/shared_library.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/move/move.hpp>
+
+#if defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) || defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+# include <boost/function.hpp>
+#endif
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+/// \file boost/dll/import.hpp
+/// \brief Contains all the boost::dll::import* reference counting
+/// functions that hold a shared pointer to the instance of
+/// boost::dll::shared_library.
+
+namespace boost { namespace dll {
+
+
+namespace detail {
+
+ template <class T>
+ class library_function {
+ // Copying of `boost::dll::shared_library` is very expensive, so we use a `shared_ptr` to make it faster.
+ boost::shared_ptr<T> f_;
+
+ public:
+ inline library_function(const boost::shared_ptr<shared_library>& lib, T* func_ptr) BOOST_NOEXCEPT
+ : f_(lib, func_ptr)
+ {}
+
+#if defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) || defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ operator T*() const BOOST_NOEXCEPT {
+ return f_.get();
+ }
+#else
+
+ // Compilation error at this point means that imported function
+ // was called with unmatching parameters.
+ //
+ // Example:
+ // auto f = dll::import<void(int)>("function", "lib.so");
+ // f("Hello"); // error: invalid conversion from 'const char*' to 'int'
+ // f(1, 2); // error: too many arguments to function
+ // f(); // error: too few arguments to function
+ template <class... Args>
+ inline auto operator()(Args&&... args) const
+ -> decltype( (*f_)(static_cast<Args&&>(args)...) )
+ {
+ return (*f_)(static_cast<Args&&>(args)...);
+ }
+#endif
+ };
+
+ template <class T, class = void>
+ struct import_type;
+
+ template <class T>
+ struct import_type<T, typename boost::disable_if<boost::is_object<T> >::type> {
+ typedef boost::dll::detail::library_function<T> base_type;
+
+#if defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) || defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ typedef boost::function<T> type;
+#else
+ typedef boost::dll::detail::library_function<T> type;
+#endif
+ };
+
+ template <class T>
+ struct import_type<T, typename boost::enable_if<boost::is_object<T> >::type> {
+ typedef boost::shared_ptr<T> base_type;
+ typedef boost::shared_ptr<T> type;
+ };
+} // namespace detail
+
+
+#ifndef BOOST_DLL_DOXYGEN
+# define BOOST_DLL_IMPORT_RESULT_TYPE inline typename boost::dll::detail::import_type<T>::type
+#endif
+
+
+/*!
+* Returns callable object or boost::shared_ptr<T> that holds the symbol imported
+* from the loaded library. Returned value refcounts usage
+* of the loaded shared library, so that it won't get unload until all copies of return value
+* are not destroyed.
+*
+* This call will succeed if call to \forcedlink{shared_library}`::has(const char* )`
+* function with the same symbol name returned `true`.
+*
+* For importing symbols by \b alias names use \forcedlink{import_alias} method.
+*
+* \b Examples:
+*
+* \code
+* boost::function<int(int)> f = import<int(int)>("test_lib.so", "integer_func_name");
+*
+* auto f_cpp11 = import<int(int)>("test_lib.so", "integer_func_name");
+* \endcode
+*
+* \code
+* boost::shared_ptr<int> i = import<int>("test_lib.so", "integer_name");
+* \endcode
+*
+* \b Template \b parameter \b T: Type of the symbol that we are going to import. Must be explicitly specified.
+*
+* \param lib Path to shared library or shared library to load function from.
+* \param name Null-terminated C or C++ mangled name of the function to import. Can handle std::string, char*, const char*.
+* \param mode An mode that will be used on library load.
+*
+* \return callable object if T is a function type, or boost::shared_ptr<T> if T is an object type.
+*
+* \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded.
+* Overload that accepts path also throws std::bad_alloc in case of insufficient memory.
+*/
+template <class T>
+BOOST_DLL_IMPORT_RESULT_TYPE import(const boost::filesystem::path& lib, const char* name,
+ load_mode::type mode = load_mode::default_mode)
+{
+ typedef typename boost::dll::detail::import_type<T>::base_type type;
+
+ boost::shared_ptr<boost::dll::shared_library> p = boost::make_shared<boost::dll::shared_library>(lib, mode);
+ return type(p, boost::addressof(p->get<T>(name)));
+}
+
+//! \overload boost::dll::import(const boost::filesystem::path& lib, const char* name, load_mode::type mode)
+template <class T>
+BOOST_DLL_IMPORT_RESULT_TYPE import(const boost::filesystem::path& lib, const std::string& name,
+ load_mode::type mode = load_mode::default_mode)
+{
+ return import<T>(lib, name.c_str(), mode);
+}
+
+//! \overload boost::dll::import(const boost::filesystem::path& lib, const char* name, load_mode::type mode)
+template <class T>
+BOOST_DLL_IMPORT_RESULT_TYPE import(const shared_library& lib, const char* name) {
+ typedef typename boost::dll::detail::import_type<T>::base_type type;
+
+ boost::shared_ptr<boost::dll::shared_library> p = boost::make_shared<boost::dll::shared_library>(lib);
+ return type(p, boost::addressof(p->get<T>(name)));
+}
+
+//! \overload boost::dll::import(const boost::filesystem::path& lib, const char* name, load_mode::type mode)
+template <class T>
+BOOST_DLL_IMPORT_RESULT_TYPE import(const shared_library& lib, const std::string& name) {
+ return import<T>(lib, name.c_str());
+}
+
+//! \overload boost::dll::import(const boost::filesystem::path& lib, const char* name, load_mode::type mode)
+template <class T>
+BOOST_DLL_IMPORT_RESULT_TYPE import(BOOST_RV_REF(shared_library) lib, const char* name) {
+ typedef typename boost::dll::detail::import_type<T>::base_type type;
+
+ boost::shared_ptr<boost::dll::shared_library> p = boost::make_shared<boost::dll::shared_library>(
+ boost::move(lib)
+ );
+ return type(p, boost::addressof(p->get<T>(name)));
+}
+
+//! \overload boost::dll::import(const boost::filesystem::path& lib, const char* name, load_mode::type mode)
+template <class T>
+BOOST_DLL_IMPORT_RESULT_TYPE import(BOOST_RV_REF(shared_library) lib, const std::string& name) {
+ return import<T>(boost::move(lib), name.c_str());
+}
+
+
+
+
+/*!
+* Returns callable object or boost::shared_ptr<T> that holds the symbol imported
+* from the loaded library. Returned value refcounts usage
+* of the loaded shared library, so that it won't get unload until all copies of return value
+* are not destroyed.
+*
+* This call will succeed if call to \forcedlink{shared_library}`::has(const char* )`
+* function with the same symbol name returned `true`.
+*
+* For importing symbols by \b non \b alias names use \forcedlink{import} method.
+*
+* \b Examples:
+*
+* \code
+* boost::function<int(int)> f = import_alias<int(int)>("test_lib.so", "integer_func_alias_name");
+*
+* auto f_cpp11 = import_alias<int(int)>("test_lib.so", "integer_func_alias_name");
+* \endcode
+*
+* \code
+* boost::shared_ptr<int> i = import_alias<int>("test_lib.so", "integer_alias_name");
+* \endcode
+*
+* \code
+* \endcode
+*
+* \b Template \b parameter \b T: Type of the symbol alias that we are going to import. Must be explicitly specified.
+*
+* \param lib Path to shared library or shared library to load function from.
+* \param name Null-terminated C or C++ mangled name of the function or variable to import. Can handle std::string, char*, const char*.
+* \param mode An mode that will be used on library load.
+*
+* \return callable object if T is a function type, or boost::shared_ptr<T> if T is an object type.
+*
+* \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded.
+* Overload that accepts path also throws std::bad_alloc in case of insufficient memory.
+*/
+template <class T>
+BOOST_DLL_IMPORT_RESULT_TYPE import_alias(const boost::filesystem::path& lib, const char* name,
+ load_mode::type mode = load_mode::default_mode)
+{
+ typedef typename boost::dll::detail::import_type<T>::base_type type;
+
+ boost::shared_ptr<boost::dll::shared_library> p = boost::make_shared<boost::dll::shared_library>(lib, mode);
+ return type(p, p->get<T*>(name));
+}
+
+//! \overload boost::dll::import_alias(const boost::filesystem::path& lib, const char* name, load_mode::type mode)
+template <class T>
+BOOST_DLL_IMPORT_RESULT_TYPE import_alias(const boost::filesystem::path& lib, const std::string& name,
+ load_mode::type mode = load_mode::default_mode)
+{
+ return import_alias<T>(lib, name.c_str(), mode);
+}
+
+//! \overload boost::dll::import_alias(const boost::filesystem::path& lib, const char* name, load_mode::type mode)
+template <class T>
+BOOST_DLL_IMPORT_RESULT_TYPE import_alias(const shared_library& lib, const char* name) {
+ typedef typename boost::dll::detail::import_type<T>::base_type type;
+
+ boost::shared_ptr<boost::dll::shared_library> p = boost::make_shared<boost::dll::shared_library>(lib);
+ return type(p, p->get<T*>(name));
+}
+
+//! \overload boost::dll::import_alias(const boost::filesystem::path& lib, const char* name, load_mode::type mode)
+template <class T>
+BOOST_DLL_IMPORT_RESULT_TYPE import_alias(const shared_library& lib, const std::string& name) {
+ return import_alias<T>(lib, name.c_str());
+}
+
+//! \overload boost::dll::import_alias(const boost::filesystem::path& lib, const char* name, load_mode::type mode)
+template <class T>
+BOOST_DLL_IMPORT_RESULT_TYPE import_alias(BOOST_RV_REF(shared_library) lib, const char* name) {
+ typedef typename boost::dll::detail::import_type<T>::base_type type;
+
+ boost::shared_ptr<boost::dll::shared_library> p = boost::make_shared<boost::dll::shared_library>(
+ boost::move(lib)
+ );
+ return type(p, p->get<T*>(name));
+}
+
+//! \overload boost::dll::import_alias(const boost::filesystem::path& lib, const char* name, load_mode::type mode)
+template <class T>
+BOOST_DLL_IMPORT_RESULT_TYPE import_alias(BOOST_RV_REF(shared_library) lib, const std::string& name) {
+ return import_alias<T>(boost::move(lib), name.c_str());
+}
+
+#undef BOOST_DLL_IMPORT_RESULT_TYPE
+
+
+}} // boost::dll
+
+#endif // BOOST_DLL_IMPORT_HPP
+
diff --git a/boost/dll/library_info.hpp b/boost/dll/library_info.hpp
new file mode 100644
index 0000000000..4666a16353
--- /dev/null
+++ b/boost/dll/library_info.hpp
@@ -0,0 +1,181 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015 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_DLL_LIBRARY_INFO_HPP
+#define BOOST_DLL_LIBRARY_INFO_HPP
+
+#include <boost/config.hpp>
+#include <boost/mpl/max_element.hpp>
+#include <boost/mpl/vector_c.hpp>
+#include <boost/aligned_storage.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/predef/os.h>
+#include <boost/predef/architecture.h>
+#include <boost/type_traits/integral_constant.hpp>
+
+#include <boost/dll/detail/pe_info.hpp>
+#include <boost/dll/detail/elf_info.hpp>
+#include <boost/dll/detail/macho_info.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+/// \file boost/dll/library_info.hpp
+/// \brief Contains only the boost::dll::library_info class that is capable of
+/// extracting different information from binaries.
+
+namespace boost { namespace dll {
+
+/*!
+* \brief Class that is capable of extracting different information from a library or binary file.
+* Currently understands ELF, MACH-O and PE formats on all the platforms.
+*/
+class library_info: private boost::noncopyable {
+private:
+ boost::filesystem::ifstream f_;
+
+ boost::aligned_storage< // making my own std::aligned_union from scratch. TODO: move to TypeTraits
+ boost::mpl::deref<
+ boost::mpl::max_element<
+ boost::mpl::vector_c<std::size_t,
+ sizeof(boost::dll::detail::elf_info32),
+ sizeof(boost::dll::detail::elf_info64),
+ sizeof(boost::dll::detail::pe_info32),
+ sizeof(boost::dll::detail::pe_info64),
+ sizeof(boost::dll::detail::macho_info32),
+ sizeof(boost::dll::detail::macho_info64)
+ >
+ >::type
+ >::type::value
+ >::type impl_;
+
+ /// @cond
+ boost::dll::detail::x_info_interface& impl() BOOST_NOEXCEPT {
+ return *reinterpret_cast<boost::dll::detail::x_info_interface*>(impl_.address());
+ }
+
+ inline static void throw_if_in_32bit_impl(boost::true_type /* is_32bit_platform */) {
+ boost::throw_exception(std::runtime_error("Not native format: 64bit binary"));
+ }
+
+ inline static void throw_if_in_32bit_impl(boost::false_type /* is_32bit_platform */) BOOST_NOEXCEPT {}
+
+
+ inline static void throw_if_in_32bit() {
+ throw_if_in_32bit_impl( boost::integral_constant<bool, (sizeof(void*) == 4)>() );
+ }
+
+ static void throw_if_in_windows() {
+#if BOOST_OS_WINDOWS
+ boost::throw_exception(std::runtime_error("Not native format: not a PE binary"));
+#endif
+ }
+
+ static void throw_if_in_linux() {
+#if !BOOST_OS_WINDOWS && !BOOST_OS_MACOS && !BOOST_OS_IOS
+ boost::throw_exception(std::runtime_error("Not native format: not an ELF binary"));
+#endif
+ }
+
+ static void throw_if_in_macos() {
+#if BOOST_OS_MACOS || BOOST_OS_IOS
+ boost::throw_exception(std::runtime_error("Not native format: not an Mach-O binary"));
+#endif
+ }
+
+ void init(bool throw_if_not_native) {
+
+ if (boost::dll::detail::elf_info32::parsing_supported(f_)) {
+ if (throw_if_not_native) { throw_if_in_windows(); throw_if_in_macos(); }
+
+ new (impl_.address()) boost::dll::detail::elf_info32(f_);
+ } else if (boost::dll::detail::elf_info64::parsing_supported(f_)) {
+ if (throw_if_not_native) { throw_if_in_windows(); throw_if_in_macos(); throw_if_in_32bit(); }
+
+ new (impl_.address()) boost::dll::detail::elf_info64(f_);
+ } else if (boost::dll::detail::pe_info32::parsing_supported(f_)) {
+ if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_macos(); }
+
+ new (impl_.address()) boost::dll::detail::pe_info32(f_);
+ } else if (boost::dll::detail::pe_info64::parsing_supported(f_)) {
+ if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_macos(); throw_if_in_32bit(); }
+
+ new (impl_.address()) boost::dll::detail::pe_info64(f_);
+ } else if (boost::dll::detail::macho_info32::parsing_supported(f_)) {
+ if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_windows(); }
+
+ new (impl_.address()) boost::dll::detail::macho_info32(f_);
+ } else if (boost::dll::detail::macho_info64::parsing_supported(f_)) {
+ if (throw_if_not_native) { throw_if_in_linux(); throw_if_in_windows(); throw_if_in_32bit(); }
+
+ new (impl_.address()) boost::dll::detail::macho_info64(f_);
+ } else {
+ boost::throw_exception(std::runtime_error("Unsupported binary format"));
+ }
+ }
+ /// @endcond
+
+public:
+ /*!
+ * Opens file with specified path and prepares for information extraction.
+ * \param library_path Path to the binary file from which the info must be extracted.
+ * \param throw_if_not_native_format Throw an exception if this file format is not
+ * supported by OS.
+ */
+ explicit library_info(const boost::filesystem::path& library_path, bool throw_if_not_native_format = true)
+ : f_(library_path, std::ios_base::in | std::ios_base::binary)
+ , impl_()
+ {
+ f_.exceptions(
+ boost::filesystem::ifstream::failbit
+ | boost::filesystem::ifstream::badbit
+ | boost::filesystem::ifstream::eofbit
+ );
+
+ init(throw_if_not_native_format);
+ }
+
+ /*!
+ * \return List of sections that exist in binary file.
+ */
+ std::vector<std::string> sections() {
+ return impl().sections();
+ }
+
+ /*!
+ * \return List of all the exportable symbols from all the sections that exist in binary file.
+ */
+ std::vector<std::string> symbols() {
+ return impl().symbols();
+ }
+
+ /*!
+ * \param section_name Name of the section from which symbol names must be returned.
+ * \return List of symbols from the specified section.
+ */
+ std::vector<std::string> symbols(const char* section_name) {
+ return impl().symbols(section_name);
+ }
+
+
+ //! \overload std::vector<std::string> symbols(const char* section_name)
+ std::vector<std::string> symbols(const std::string& section_name) {
+ return impl().symbols(section_name.c_str());
+ }
+
+ /*!
+ * \throw Nothing.
+ */
+ ~library_info() BOOST_NOEXCEPT {
+ typedef boost::dll::detail::x_info_interface T;
+ impl().~T();
+ }
+};
+
+}} // namespace boost::dll
+#endif // BOOST_DLL_LIBRARY_INFO_HPP
diff --git a/boost/dll/runtime_symbol_info.hpp b/boost/dll/runtime_symbol_info.hpp
new file mode 100644
index 0000000000..80cce510f9
--- /dev/null
+++ b/boost/dll/runtime_symbol_info.hpp
@@ -0,0 +1,194 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015-2016 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_DLL_RUNTIME_SYMBOL_INFO_HPP
+#define BOOST_DLL_RUNTIME_SYMBOL_INFO_HPP
+
+#include <boost/config.hpp>
+#include <boost/predef/os.h>
+#include <boost/predef/compiler/visualc.h>
+#include <boost/dll/detail/aggressive_ptr_cast.hpp>
+#if BOOST_OS_WINDOWS
+# include <boost/detail/winapi/dll.hpp>
+# include <boost/dll/detail/windows/path_from_handle.hpp>
+#else
+# include <dlfcn.h>
+# include <boost/dll/detail/posix/program_location_impl.hpp>
+#endif
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+/// \file boost/dll/runtime_symbol_info.hpp
+/// \brief Provides methods for getting acceptable by boost::dll::shared_library location of symbol, source line or program.
+namespace boost { namespace dll {
+
+namespace detail {
+#if BOOST_OS_WINDOWS
+ inline boost::filesystem::path symbol_location_impl(const void* symbol, boost::system::error_code& ec) {
+ boost::filesystem::path ret;
+
+ boost::detail::winapi::MEMORY_BASIC_INFORMATION_ mbi;
+ if (!boost::detail::winapi::VirtualQuery(symbol, &mbi, sizeof(mbi))) {
+ ec = boost::dll::detail::last_error_code();
+ return ret;
+ }
+
+ return boost::dll::detail::path_from_handle(reinterpret_cast<boost::detail::winapi::HMODULE_>(mbi.AllocationBase), ec);
+ }
+
+ inline boost::filesystem::path program_location_impl(boost::system::error_code& ec) {
+ return boost::dll::detail::path_from_handle(NULL, ec);
+ }
+#else
+ inline boost::filesystem::path symbol_location_impl(const void* symbol, boost::system::error_code& ec) {
+ boost::filesystem::path ret;
+ Dl_info info;
+
+ // Some of the libc headers miss `const` in `dladdr(const void*, Dl_info*)`
+ const int res = dladdr(const_cast<void*>(symbol), &info);
+
+ if (res) {
+ ret = info.dli_fname;
+ } else {
+ boost::dll::detail::reset_dlerror();
+ ec = boost::system::error_code(
+ boost::system::errc::bad_address,
+ boost::system::generic_category()
+ );
+ }
+
+ return ret;
+ }
+#endif
+} // namespace detail
+
+ /*!
+ * On success returns full path and name of the binary object that holds symbol.
+ * \tparam T Type of the symbol, must not be explicitly specified.
+ * \param symbol Symbol which location is to be determined.
+ * \param ec Variable that will be set to the result of the operation.
+ * \return Path to the binary object that holds symbol or empty path in case error.
+ * \throws std::bad_alloc in case of insufficient memory. Overload that does not accept boost::system::error_code also throws boost::system::system_error.
+ *
+ * \b Examples:
+ * \code
+ * int var;
+ * void foo() {}
+ *
+ * int main() {
+ * dll::symbol_location(var); // returns program location
+ * dll::symbol_location(foo); // returns program location
+ * dll::symbol_location(std::cerr); // returns location of libstdc++: "/usr/lib/x86_64-linux-gnu/libstdc++.so.6"
+ * dll::symbol_location(std::placeholders::_1); // returns location of libstdc++: "/usr/lib/x86_64-linux-gnu/libstdc++.so.6"
+ * dll::symbol_location(std::puts); // returns location of libc: "/lib/x86_64-linux-gnu/libc.so.6"
+ * }
+ * \endcode
+ */
+ template <class T>
+ inline boost::filesystem::path symbol_location(const T& symbol, boost::system::error_code& ec) {
+ ec.clear();
+ return boost::dll::detail::symbol_location_impl(
+ boost::dll::detail::aggressive_ptr_cast<const void*>(boost::addressof(symbol)),
+ ec
+ );
+ }
+
+#if BOOST_COMP_MSVC < BOOST_VERSION_NUMBER(14,0,0)
+ // Without this MSVC 7.1 fails with:
+ // ..\boost\dll\runtime_symbol_info.hpp(133) : error C2780: 'filesystem::path dll::symbol_location(const T &)' : expects 1 arguments - 2 provided
+ template <class T>
+ inline boost::filesystem::path symbol_location(const T& symbol, const char* /*workaround*/ = 0)
+#else
+ //! \overload symbol_location(const T& symbol, boost::system::error_code& ec)
+ template <class T>
+ inline boost::filesystem::path symbol_location(const T& symbol)
+#endif
+ {
+ boost::filesystem::path ret;
+ boost::system::error_code ec;
+ ret = boost::dll::detail::symbol_location_impl(
+ boost::dll::detail::aggressive_ptr_cast<const void*>(boost::addressof(symbol)),
+ ec
+ );
+
+ if (ec) {
+ boost::dll::detail::report_error(ec, "boost::dll::symbol_location(const T& symbol) failed");
+ }
+
+ return ret;
+ }
+
+ /// @cond
+ // We have anonymous namespace here to make sure that `this_line_location()` method is instantiated in
+ // current translation module and is not shadowed by instantiations from other modules.
+ namespace {
+ /// @endcond
+
+ /*!
+ * On success returns full path and name of the binary object that holds the current line of code
+ * (the line in which the `this_line_location()` method was called).
+ *
+ * \param ec Variable that will be set to the result of the operation.
+ * \throws std::bad_alloc in case of insufficient memory. Overload that does not accept boost::system::error_code also throws boost::system::system_error.
+ */
+ static inline boost::filesystem::path this_line_location(boost::system::error_code& ec) {
+ typedef boost::filesystem::path(func_t)(boost::system::error_code& );
+ func_t& f = this_line_location;
+ return boost::dll::symbol_location(f, ec);
+ }
+
+ //! \overload this_line_location(boost::system::error_code& ec)
+ static inline boost::filesystem::path this_line_location() {
+ boost::filesystem::path ret;
+ boost::system::error_code ec;
+ ret = this_line_location(ec);
+
+ if (ec) {
+ boost::dll::detail::report_error(ec, "boost::dll::this_line_location() failed");
+ }
+
+ return ret;
+ }
+
+ /// @cond
+ } // anonymous namespace
+ /// @endcond
+
+ /*!
+ * On success returns full path and name of the currently running program (the one which contains the `main()` function).
+ *
+ * Return value can be used as a parameter for shared_library. See Tutorial "Linking plugin into the executable"
+ * for usage example. Flag '-rdynamic' must be used when linking the plugin into the executable
+ * on Linux OS.
+ *
+ * \param ec Variable that will be set to the result of the operation.
+ * \throws std::bad_alloc in case of insufficient memory. Overload that does not accept boost::system::error_code also throws boost::system::system_error.
+ */
+ inline boost::filesystem::path program_location(boost::system::error_code& ec) {
+ ec.clear();
+ return boost::dll::detail::program_location_impl(ec);
+ }
+
+ //! \overload program_location(boost::system::error_code& ec) {
+ inline boost::filesystem::path program_location() {
+ boost::filesystem::path ret;
+ boost::system::error_code ec;
+ ret = boost::dll::detail::program_location_impl(ec);
+
+ if (ec) {
+ boost::dll::detail::report_error(ec, "boost::dll::program_location() failed");
+ }
+
+ return ret;
+ }
+
+}} // namespace boost::dll
+
+#endif // BOOST_DLL_RUNTIME_SYMBOL_INFO_HPP
+
diff --git a/boost/dll/shared_library.hpp b/boost/dll/shared_library.hpp
new file mode 100644
index 0000000000..86aed9433e
--- /dev/null
+++ b/boost/dll/shared_library.hpp
@@ -0,0 +1,550 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015-2016 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_DLL_SHARED_LIBRARY_HPP
+#define BOOST_DLL_SHARED_LIBRARY_HPP
+
+/// \file boost/dll/shared_library.hpp
+/// \brief Contains the boost::dll::shared_library class, core class for all the
+/// DLL/DSO operations.
+
+#include <boost/config.hpp>
+#include <boost/predef/os.h>
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/is_member_pointer.hpp>
+#include <boost/utility/explicit_operator_bool.hpp>
+#include <boost/dll/detail/system_error.hpp>
+#include <boost/dll/detail/aggressive_ptr_cast.hpp>
+
+#if BOOST_OS_WINDOWS
+# include <boost/dll/detail/windows/shared_library_impl.hpp>
+#else
+# include <boost/dll/detail/posix/shared_library_impl.hpp>
+#endif
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+namespace boost { namespace dll {
+
+/*!
+* \brief This class can be used to load a
+* Dynamic link libraries (DLL's) or Shared Libraries, also know
+* as dynamic shared objects (DSO's) and get their exported
+* symbols (functions and variables).
+*
+* shared_library instances share reference count to an actual loaded DLL/DSO, so it
+* is safe and memory efficient to have multiple instances of shared_library referencing the same DLL/DSO
+* even if those instances were loaded using different paths (relative + absolute) referencing the same object.
+*
+* On Linux/POSIX link with library "dl". "-fvisibility=hidden" flag is also recommended for use on Linux/POSIX.
+*/
+class shared_library
+/// @cond
+ : private boost::dll::detail::shared_library_impl
+/// @endcond
+{
+ typedef boost::dll::detail::shared_library_impl base_t;
+ BOOST_COPYABLE_AND_MOVABLE(shared_library)
+
+public:
+#ifdef BOOST_DLL_DOXYGEN
+ typedef platform_specific native_handle_t;
+#else
+ typedef shared_library_impl::native_handle_t native_handle_t;
+#endif
+
+ /*!
+ * Creates in anstance that does not reference any DLL/DSO.
+ *
+ * \post this->is_loaded() returns false.
+ * \throw Nothing.
+ */
+ shared_library() BOOST_NOEXCEPT {}
+
+ /*!
+ * Copy constructor that increments the reference count of an underlying shared library.
+ * Same as calling constructor with `lib.location()` parameter.
+ *
+ * \param lib A library to copy.
+ * \post lib == *this
+ * \throw boost::system::system_error, std::bad_alloc in case of insufficient memory.
+ */
+ shared_library(const shared_library& lib)
+ : base_t()
+ {
+ assign(lib);
+ }
+
+ /*!
+ * Copy constructor that increments the reference count of an underlying shared library.
+ * Same as calling constructor with `lib.location(), ec` parameters.
+ *
+ * \param lib A shared library to copy.
+ * \param ec Variable that will be set to the result of the operation.
+ * \post lib == *this
+ * \throw std::bad_alloc in case of insufficient memory.
+ */
+ shared_library(const shared_library& lib, boost::system::error_code& ec)
+ : base_t()
+ {
+ assign(lib, ec);
+ }
+
+ /*!
+ * Move constructor. Does not invalidate existing symbols and functions loaded from lib.
+ *
+ * \param lib A shared library to move from.
+ * \post lib.is_loaded() returns false, this->is_loaded() return true.
+ * \throw Nothing.
+ */
+ shared_library(BOOST_RV_REF(shared_library) lib) BOOST_NOEXCEPT
+ : base_t(boost::move(static_cast<base_t&>(lib)))
+ {}
+
+ /*!
+ * Loads a library by specified path with a specified mode.
+ *
+ * \param lib_path Library file name. Can handle std::string, const char*, std::wstring,
+ * const wchar_t* or boost::filesystem::path.
+ * \param mode A mode that will be used on library load.
+ * \throw boost::system::system_error, std::bad_alloc in case of insufficient memory.
+ */
+ explicit shared_library(const boost::filesystem::path& lib_path, load_mode::type mode = load_mode::default_mode) {
+ shared_library::load(lib_path, mode);
+ }
+
+ /*!
+ * Loads a library by specified path with a specified mode.
+ *
+ * \param lib_path Library file name. Can handle std::string, const char*, std::wstring,
+ * const wchar_t* or boost::filesystem::path.
+ * \param mode A mode that will be used on library load.
+ * \param ec Variable that will be set to the result of the operation.
+ * \throw std::bad_alloc in case of insufficient memory.
+ */
+ shared_library(const boost::filesystem::path& lib_path, boost::system::error_code& ec, load_mode::type mode = load_mode::default_mode) {
+ shared_library::load(lib_path, mode, ec);
+ }
+
+ //! \overload shared_library(const boost::filesystem::path& lib_path, boost::system::error_code& ec, load_mode::type mode = load_mode::default_mode)
+ shared_library(const boost::filesystem::path& lib_path, load_mode::type mode, boost::system::error_code& ec) {
+ shared_library::load(lib_path, mode, ec);
+ }
+
+ /*!
+ * Assignment operator. If this->is_loaded() then calls this->unload(). Does not invalidate existing symbols and functions loaded from lib.
+ *
+ * \param lib A shared library to assign from.
+ * \post lib == *this
+ * \throw boost::system::system_error, std::bad_alloc in case of insufficient memory.
+ */
+ shared_library& operator=(BOOST_COPY_ASSIGN_REF(shared_library) lib) {
+ boost::system::error_code ec;
+ assign(lib, ec);
+ if (ec) {
+ boost::dll::detail::report_error(ec, "boost::dll::shared_library::operator= failed");
+ }
+
+ return *this;
+ }
+
+ /*!
+ * Move assignment operator. If this->is_loaded() then calls this->unload(). Does not invalidate existing symbols and functions loaded from lib.
+ *
+ * \param lib A library to move from.
+ * \post lib.is_loaded() returns false.
+ * \throw Nothing.
+ */
+ shared_library& operator=(BOOST_RV_REF(shared_library) lib) BOOST_NOEXCEPT {
+ if (lib.native() != native()) {
+ swap(lib);
+ }
+
+ return *this;
+ }
+
+ /*!
+ * Destroys the object by calling `unload()`. If library was loaded multiple times
+ * by different instances, the actual DLL/DSO won't be unloaded until
+ * there is at least one instance that references the DLL/DSO.
+ *
+ * \throw Nothing.
+ */
+ ~shared_library() BOOST_NOEXCEPT {}
+
+ /*!
+ * Makes *this share the same shared object as lib. If *this is loaded, then unloads it.
+ *
+ * \post lib.location() == this->location(), lib == *this
+ * \param lib A library to copy.
+ * \param ec Variable that will be set to the result of the operation.
+ * \throw std::bad_alloc in case of insufficient memory.
+ */
+ shared_library& assign(const shared_library& lib, boost::system::error_code& ec) {
+ ec.clear();
+
+ if (native() == lib.native()) {
+ return *this;
+ }
+
+ if (!lib) {
+ unload();
+ return *this;
+ }
+
+ boost::filesystem::path loc = lib.location(ec);
+ if (ec) {
+ return *this;
+ }
+
+ shared_library copy(loc, ec);
+ if (ec) {
+ return *this;
+ }
+
+ swap(copy);
+ return *this;
+ }
+
+ /*!
+ * Makes *this share the same shared object as lib. If *this is loaded, then unloads it.
+ *
+ * \param lib A library instance to assign from.
+ * \post lib.location() == this->location()
+ * \throw boost::system::system_error, std::bad_alloc in case of insufficient memory.
+ */
+ shared_library& assign(const shared_library& lib) {
+ boost::system::error_code ec;
+ assign(lib, ec);
+ if (ec) {
+ boost::dll::detail::report_error(ec, "boost::dll::shared_library::assign() failed");
+ }
+
+ return *this;
+ }
+
+ /*!
+ * Loads a library by specified path with a specified mode.
+ *
+ * Note that if some library is already loaded in this instance, load will
+ * call unload() and then load the new provided library.
+ *
+ * \param lib_path Library file name. Can handle std::string, const char*, std::wstring,
+ * const wchar_t* or boost::filesystem::path.
+ * \param mode A mode that will be used on library load.
+ * \throw boost::system::system_error, std::bad_alloc in case of insufficient memory.
+ *
+ */
+ void load(const boost::filesystem::path& lib_path, load_mode::type mode = load_mode::default_mode) {
+ boost::system::error_code ec;
+
+ base_t::load(lib_path, mode, ec);
+
+ if (ec) {
+ boost::dll::detail::report_error(ec, "boost::dll::shared_library::load() failed");
+ }
+ }
+
+ /*!
+ * Loads a library by specified path with a specified mode.
+ *
+ * Note that if some library is already loaded in this instance, load will
+ * call unload() and then load the new provided library.
+ *
+ * \param lib_path Library file name. Can handle std::string, const char*, std::wstring,
+ * const wchar_t* or boost::filesystem::path.
+ * \param ec Variable that will be set to the result of the operation.
+ * \param mode A mode that will be used on library load.
+ * \throw std::bad_alloc in case of insufficient memory.
+ */
+ void load(const boost::filesystem::path& lib_path, boost::system::error_code& ec, load_mode::type mode = load_mode::default_mode) {
+ ec.clear();
+ base_t::load(lib_path, mode, ec);
+ }
+
+ //! \overload void load(const boost::filesystem::path& lib_path, boost::system::error_code& ec, load_mode::type mode = load_mode::default_mode)
+ void load(const boost::filesystem::path& lib_path, load_mode::type mode, boost::system::error_code& ec) {
+ ec.clear();
+ base_t::load(lib_path, mode, ec);
+ }
+
+ /*!
+ * Unloads a shared library. If library was loaded multiple times
+ * by different instances, the actual DLL/DSO won't be unloaded until
+ * there is at least one instance that references the DLL/DSO.
+ *
+ * \post this->is_loaded() returns false.
+ * \throw Nothing.
+ */
+ void unload() BOOST_NOEXCEPT {
+ base_t::unload();
+ }
+
+ /*!
+ * Check if an library is loaded.
+ *
+ * \return true if a library has been loaded.
+ * \throw Nothing.
+ */
+ bool is_loaded() const BOOST_NOEXCEPT {
+ return base_t::is_loaded();
+ }
+
+ /*!
+ * Check if an library is not loaded.
+ *
+ * \return true if a library has not been loaded.
+ * \throw Nothing.
+ */
+ bool operator!() const BOOST_NOEXCEPT {
+ return !is_loaded();
+ }
+
+ /*!
+ * Check if an library is loaded.
+ *
+ * \return true if a library has been loaded.
+ * \throw Nothing.
+ */
+ BOOST_EXPLICIT_OPERATOR_BOOL()
+
+ /*!
+ * Search for a given symbol on loaded library. Works for all symbols, including alias names.
+ *
+ * \param symbol_name Null-terminated symbol name. Can handle std::string, char*, const char*.
+ * \return `true` if the loaded library contains a symbol with a given name.
+ * \throw Nothing.
+ */
+ bool has(const char* symbol_name) const BOOST_NOEXCEPT {
+ boost::system::error_code ec;
+ return is_loaded() && !!base_t::symbol_addr(symbol_name, ec) && !ec;
+ }
+
+ //! \overload bool has(const char* symbol_name) const
+ bool has(const std::string& symbol_name) const BOOST_NOEXCEPT {
+ return has(symbol_name.c_str());
+ }
+
+ /*!
+ * Returns reference to the symbol (function or variable) with the given name from the loaded library.
+ * This call will always succeed and throw nothing if call to `has(const char* )`
+ * member function with the same symbol name returned `true`.
+ *
+ * \b Example:
+ * \code
+ * int& i0 = lib.get<int>("integer_name");
+ * int& i1 = *lib.get<int*>("integer_alias_name");
+ * \endcode
+ *
+ * \tparam T Type of the symbol that we are going to import. Must be explicitly specified.
+ * \param symbol_name Null-terminated symbol name. Can handle std::string, char*, const char*.
+ * \return Reference to the symbol.
+ * \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded.
+ */
+ template <typename T>
+ inline typename boost::enable_if_c<boost::is_member_pointer<T>::value || boost::is_reference<T>::value, T>::type get(const std::string& symbol_name) const {
+ return get<T>(symbol_name.c_str());
+ }
+
+ //! \overload T& get(const std::string& symbol_name) const
+ template <typename T>
+ inline typename boost::disable_if_c<boost::is_member_pointer<T>::value || boost::is_reference<T>::value, T&>::type get(const std::string& symbol_name) const {
+ return get<T>(symbol_name.c_str());
+ }
+
+ //! \overload T& get(const std::string& symbol_name) const
+ template <typename T>
+ inline typename boost::enable_if_c<boost::is_member_pointer<T>::value || boost::is_reference<T>::value, T>::type get(const char* symbol_name) const {
+ return boost::dll::detail::aggressive_ptr_cast<T>(
+ get_void(symbol_name)
+ );
+ }
+
+ //! \overload T& get(const std::string& symbol_name) const
+ template <typename T>
+ inline typename boost::disable_if_c<boost::is_member_pointer<T>::value || boost::is_reference<T>::value, T&>::type get(const char* symbol_name) const {
+ return *boost::dll::detail::aggressive_ptr_cast<T*>(
+ get_void(symbol_name)
+ );
+ }
+
+ /*!
+ * Returns a symbol (function or variable) from a shared library by alias name of the symbol.
+ *
+ * \b Example:
+ * \code
+ * int& i = lib.get_alias<int>("integer_alias_name");
+ * \endcode
+ *
+ * \tparam T Type of the symbol that we are going to import. Must be explicitly specified..
+ * \param alias_name Null-terminated alias symbol name. Can handle std::string, char*, const char*.
+ * \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded.
+ */
+ template <typename T>
+ inline T& get_alias(const char* alias_name) const {
+ return *get<T*>(alias_name);
+ }
+
+ //! \overload T& get_alias(const char* alias_name) const
+ template <typename T>
+ inline T& get_alias(const std::string& alias_name) const {
+ return *get<T*>(alias_name.c_str());
+ }
+
+private:
+ /// @cond
+ // get_void is required to reduce binary size: it does not depend on a template
+ // parameter and will be instantiated only once.
+ void* get_void(const char* sb) const {
+ boost::system::error_code ec;
+
+ if (!is_loaded()) {
+ ec = boost::system::error_code(
+ boost::system::errc::bad_file_descriptor,
+ boost::system::generic_category()
+ );
+
+ // report_error() calls dlsym, do not use it here!
+ boost::throw_exception(
+ boost::system::system_error(
+ ec, "boost::dll::shared_library::get() failed: no library was loaded"
+ )
+ );
+ }
+
+ void* const ret = base_t::symbol_addr(sb, ec);
+ if (ec || !ret) {
+ boost::dll::detail::report_error(ec, "boost::dll::shared_library::get() failed");
+ }
+
+ return ret;
+ }
+ /// @endcond
+
+public:
+
+ /*!
+ * Returns the native handler of the loaded library.
+ *
+ * \return Platform-specific handle.
+ */
+ native_handle_t native() const BOOST_NOEXCEPT {
+ return base_t::native();
+ }
+
+ /*!
+ * Returns full path and name of this shared object.
+ *
+ * \b Example:
+ * \code
+ * shared_library lib("test_lib.dll");
+ * filesystem::path full_path = lib.location(); // C:\Windows\System32\test_lib.dll
+ * \endcode
+ *
+ * \return Full path to the shared library.
+ * \throw boost::system::system_error, std::bad_alloc.
+ */
+ boost::filesystem::path location() const {
+ boost::system::error_code ec;
+ if (!is_loaded()) {
+ ec = boost::system::error_code(
+ boost::system::errc::bad_file_descriptor,
+ boost::system::generic_category()
+ );
+
+ boost::throw_exception(
+ boost::system::system_error(
+ ec, "boost::dll::shared_library::location() failed (no library was loaded)"
+ )
+ );
+ }
+
+ boost::filesystem::path full_path = base_t::full_module_path(ec);
+
+ if (ec) {
+ boost::dll::detail::report_error(ec, "boost::dll::shared_library::location() failed");
+ }
+
+ return full_path;
+ }
+
+ /*!
+ * Returns full path and name of shared module.
+ *
+ * \b Example:
+ * \code
+ * shared_library lib("test_lib.dll");
+ * filesystem::path full_path = lib.location(); // C:\Windows\System32\test_lib.dll
+ * \endcode
+ *
+ * \param ec Variable that will be set to the result of the operation.
+ * \return Full path to the shared library.
+ * \throw std::bad_alloc.
+ */
+ boost::filesystem::path location(boost::system::error_code& ec) const {
+ if (!is_loaded()) {
+ ec = boost::system::error_code(
+ boost::system::errc::bad_file_descriptor,
+ boost::system::generic_category()
+ );
+
+ return boost::filesystem::path();
+ }
+
+ ec.clear();
+ return base_t::full_module_path(ec);
+ }
+
+ /*!
+ * Returns suffix of shared module:
+ * in a call to load() or the constructor/load.
+ *
+ * \return The suffix od shared module: ".dll" (Windows), ".so" (Unix/Linux/BSD), ".dylib" (MacOS/IOS)
+ */
+ static boost::filesystem::path suffix() {
+ return base_t::suffix();
+ }
+
+ /*!
+ * Swaps two libraries. Does not invalidate existing symbols and functions loaded from libraries.
+ *
+ * \param rhs Library to swap with.
+ * \throw Nothing.
+ */
+ void swap(shared_library& rhs) BOOST_NOEXCEPT {
+ base_t::swap(rhs);
+ }
+};
+
+
+
+/// Very fast equality check that compares the actual DLL/DSO objects. Throws nothing.
+inline bool operator==(const shared_library& lhs, const shared_library& rhs) BOOST_NOEXCEPT {
+ return lhs.native() == rhs.native();
+}
+
+/// Very fast inequality check that compares the actual DLL/DSO objects. Throws nothing.
+inline bool operator!=(const shared_library& lhs, const shared_library& rhs) BOOST_NOEXCEPT {
+ return lhs.native() != rhs.native();
+}
+
+/// Compare the actual DLL/DSO objects without any guarantee to be stable between runs. Throws nothing.
+inline bool operator<(const shared_library& lhs, const shared_library& rhs) BOOST_NOEXCEPT {
+ return lhs.native() < rhs.native();
+}
+
+/// Swaps two shared libraries. Does not invalidate symbols and functions loaded from libraries. Throws nothing.
+inline void swap(shared_library& lhs, shared_library& rhs) BOOST_NOEXCEPT {
+ lhs.swap(rhs);
+}
+
+}} // boost::dll
+
+#endif // BOOST_DLL_SHARED_LIBRARY_HPP
+
diff --git a/boost/dll/shared_library_load_mode.hpp b/boost/dll/shared_library_load_mode.hpp
new file mode 100644
index 0000000000..5627e42dfd
--- /dev/null
+++ b/boost/dll/shared_library_load_mode.hpp
@@ -0,0 +1,249 @@
+// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
+// Copyright 2015-2016 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_DLL_SHARED_LIBRARY_MODE_HPP
+#define BOOST_DLL_SHARED_LIBRARY_MODE_HPP
+
+#include <boost/config.hpp>
+#include <boost/predef/os.h>
+#include <boost/predef/library/c.h>
+
+#if BOOST_OS_WINDOWS
+//#include <boost/detail/winapi/dll.hpp>
+#include <boost/detail/winapi/dll.hpp>
+#else
+# include <dlfcn.h>
+#endif
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+/// \file boost/dll/shared_library_load_mode.hpp
+/// \brief Contains only the boost::dll::load_mode::type enum and operators related to it.
+
+namespace boost { namespace dll { namespace load_mode {
+
+/*! Library load modes.
+*
+* Each of system family provides own modes. Flags not supported by a particular platform will be silently ignored.
+*
+* For a detailed description of platform specific options see:
+* <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684179(v=vs.85).aspx">Windows specific options</a>,
+* <a href="http://pubs.opengroup.org/onlinepubs/000095399/functions/dlopen.html">POSIX specific options</a>.
+*
+*/
+
+enum type {
+#ifdef BOOST_DLL_DOXYGEN
+ /*!
+ * Default open mode. See the \b Default: comments below to find out the flags that are enabled by default.
+ */
+ default_mode,
+
+ /*!
+ * \b Platforms: Windows
+ *
+ * \b Default: disabled
+ *
+ * If this value is used, and the executable module is a DLL, the system does
+ * not call DllMain for process and thread initialization and termination.
+ * Also, the system does not load additional executable modules that are
+ * referenced by the specified module.
+ *
+ * Note Do not use this value; it is provided only for backward compatibility.
+ * If you are planning to access only data or resources in the DLL, use
+ * LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE or LOAD_LIBRARY_AS_IMAGE_RESOURCE
+ * or both.
+ */
+ dont_resolve_dll_references,
+
+ /*!
+ * \b Platforms: Windows
+ *
+ * \b Default: disabled
+ *
+ * If this value is used, the system does not check AppLocker rules or
+ * apply Software Restriction Policies for the DLL.
+ */
+ load_ignore_code_authz_level,
+
+ /*!
+ * \b Platforms: Windows
+ *
+ * \b Default: disabled
+ *
+ * If this value is used and lpFileName specifies an absolute path,
+ * the system uses the alternate file search strategy.
+ *
+ * This value cannot be combined with any LOAD_LIBRARY_SEARCH flag.
+ */
+ load_with_altered_search_path,
+
+ /*!
+ * \b Platforms: POSIX
+ *
+ * \b Default: enabled
+ *
+ * Relocations shall be performed at an implementation-defined time, ranging
+ * from the time of the dlopen() call until the first reference to a given
+ * symbol occurs.
+ *
+ * Specifying RTLD_LAZY should improve performance on implementations
+ * supporting dynamic symbol binding as a process may not reference all of
+ * the functions in any given object. And, for systems supporting dynamic
+ * symbol resolution for normal process execution, this behavior mimics
+ * the normal handling of process execution.
+ */
+ rtld_lazy,
+
+ /*!
+ * \b Platforms: POSIX
+ *
+ * \b Default: disabled
+ *
+ * All necessary relocations shall be performed when the object is first
+ * loaded. This may waste some processing if relocations are performed for
+ * functions that are never referenced. This behavior may be useful for
+ * plugins that need to know as soon as an object is loaded that all
+ * symbols referenced during execution are available.
+ */
+ rtld_now,
+
+ /*!
+ * \b Platforms: POSIX
+ *
+ * \b Default: disabled
+ *
+ * The object's symbols shall be made available for the relocation
+ * processing of any other object. In addition, symbol lookup using
+ * dlopen(0, mode) and an associated dlsym() allows objects loaded
+ * with this mode to be searched.
+ */
+ rtld_global,
+
+ /*!
+ * \b Platforms: POSIX
+ *
+ * \b Default: enabled
+ *
+ * The object's symbols shall not be made available for the relocation
+ * processing of any other object.
+ *
+ * This is a default Windows behavior that can not be changed.
+ */
+ rtld_local,
+
+ /*!
+ * \b Platforms: POSIX (requires glibc >= 2.3.4)
+ *
+ * \b Default: disabled
+ *
+ * The object will use its own symbols in preference to global symbols
+ * with the same name contained in libraries that have already been loaded.
+ * This flag is not specified in POSIX.1-2001.
+ */
+ rtld_deepbind,
+
+ /*!
+ * \b Platforms: Windows, POSIX
+ *
+ * \b Default: disabled
+ *
+ * Append a platform specific extension and prefix to shared library filename before trying to load it.
+ * If load attempt fails, try to load with exactly specified name.
+ *
+ * \b Example:
+ * \code
+ * // Opens `./my_plugins/plugin1.dll` on Windows, `./my_plugins/libplugin1.so` on Linux, `./my_plugins/libplugin1.dylib` on MacOS.
+ * // If that fails, loads `./my_plugins/plugin1`
+ * boost::dll::shared_library lib("./my_plugins/plugin1", load_mode::append_decorations);
+ * \endcode
+ */
+ append_decorations,
+ /*!
+ * \b Platforms: Windows, POSIX
+ *
+ * \b Default: disabled
+ *
+ * Allow loading from system folders if path to library contains no parent path.
+ */
+ search_system_folders
+#elif BOOST_OS_WINDOWS
+ default_mode = 0,
+ dont_resolve_dll_references = boost::detail::winapi::DONT_RESOLVE_DLL_REFERENCES_,
+ load_ignore_code_authz_level = boost::detail::winapi::LOAD_IGNORE_CODE_AUTHZ_LEVEL_,
+ load_with_altered_search_path = boost::detail::winapi::LOAD_WITH_ALTERED_SEARCH_PATH_,
+ rtld_lazy = 0,
+ rtld_now = 0,
+ rtld_global = 0,
+ rtld_local = 0,
+ rtld_deepbind = 0,
+ append_decorations = 0x00800000,
+ search_system_folders = (append_decorations << 1)
+#else
+ default_mode = 0,
+ dont_resolve_dll_references = 0,
+ load_ignore_code_authz_level = 0,
+ load_with_altered_search_path = 0,
+ rtld_lazy = RTLD_LAZY,
+ rtld_now = RTLD_NOW,
+ rtld_global = RTLD_GLOBAL,
+ rtld_local = RTLD_LOCAL,
+
+#if BOOST_LIB_C_GNU < BOOST_VERSION_NUMBER(2,3,4)
+ rtld_deepbind = 0,
+#else
+ rtld_deepbind = RTLD_DEEPBIND,
+#endif
+
+ append_decorations = 0x00800000,
+ search_system_folders = (append_decorations << 1)
+#endif
+};
+
+
+/// Free operators for load_mode::type flag manipulation.
+BOOST_CONSTEXPR inline type operator|(type left, type right) BOOST_NOEXCEPT {
+ return static_cast<type>(
+ static_cast<unsigned int>(left) | static_cast<unsigned int>(right)
+ );
+}
+BOOST_CXX14_CONSTEXPR inline type& operator|=(type& left, type right) BOOST_NOEXCEPT {
+ left = left | right;
+ return left;
+}
+
+BOOST_CONSTEXPR inline type operator&(type left, type right) BOOST_NOEXCEPT {
+ return static_cast<type>(
+ static_cast<unsigned int>(left) & static_cast<unsigned int>(right)
+ );
+}
+BOOST_CXX14_CONSTEXPR inline type& operator&=(type& left, type right) BOOST_NOEXCEPT {
+ left = left & right;
+ return left;
+}
+
+BOOST_CONSTEXPR inline type operator^(type left, type right) BOOST_NOEXCEPT {
+ return static_cast<type>(
+ static_cast<unsigned int>(left) ^ static_cast<unsigned int>(right)
+ );
+}
+BOOST_CXX14_CONSTEXPR inline type& operator^=(type& left, type right) BOOST_NOEXCEPT {
+ left = left ^ right;
+ return left;
+}
+
+BOOST_CONSTEXPR inline type operator~(type left) BOOST_NOEXCEPT {
+ return static_cast<type>(
+ ~static_cast<unsigned int>(left)
+ );
+}
+
+}}} // boost::dll::load_mode
+
+#endif // BOOST_DLL_SHARED_LIBRARY_MODE_HPP
diff --git a/boost/dll/smart_library.hpp b/boost/dll/smart_library.hpp
new file mode 100644
index 0000000000..718820b2fb
--- /dev/null
+++ b/boost/dll/smart_library.hpp
@@ -0,0 +1,347 @@
+// Copyright 2016 Klemens 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 INCLUDE_BOOST_DLL_SMART_LIBRARY_HPP_
+#define INCLUDE_BOOST_DLL_SMART_LIBRARY_HPP_
+
+/// \file boost/dll/smart_library.hpp
+/// \warning Extremely experimental! Requires C++14! Will change in next version of Boost! boost/dll/smart_library.hpp is not included in boost/dll.hpp
+/// \brief Contains the boost::dll::experimental::smart_library class for loading mangled symbols.
+
+#include <boost/dll/shared_library.hpp>
+#include <boost/dll/detail/get_mem_fn_type.hpp>
+#include <boost/dll/detail/ctor_dtor.hpp>
+
+#include <boost/predef/compiler.h>
+
+
+#if BOOST_COMP_GNUC || BOOST_COMP_CLANG || BOOST_COMP_HPACC || BOOST_COMP_IBM
+#include <boost/dll/detail/demangling/itanium.hpp>
+#elif BOOST_COMP_MSVC
+#include <boost/dll/detail/demangling/msvc.hpp>
+#else
+#error "Compiler not supported"
+#endif
+
+namespace boost {
+namespace dll {
+namespace experimental {
+
+using boost::dll::detail::constructor;
+using boost::dll::detail::destructor;
+
+/*!
+* \brief This class is an extension of \ref shared_library, which allows to load C++ symbols.
+*
+* This class allows type safe loading of overloaded functions, member-functions, constructors and variables.
+* It also allows to overwrite classes so they can be loaded, while being declared with different names.
+*
+* \warning Is still very experimental.
+*
+* Currently known limitations:
+*
+* Member functions must be defined outside of the class to be exported. That is:
+* \code
+* //not exported:
+* struct BOOST_SYMBOL_EXPORT my_class { void func() {}};
+* //exported
+* struct BOOST_SYMBOL_EXPORT my_class { void func();};
+* void my_class::func() {};
+* \endcode
+*
+* With the current analysis, the first version does get exported in MSVC.
+* MinGW also does export it, BOOST_SYMBOL_EXPORT is written before it. To allow this on windows one can use
+* BOOST_DLL_MEMBER_EXPORT for this, so that MinGW and MSVC can provide those functions. This does however not work with gcc on linux.
+*
+* Direct initialization of members.
+* On linux the following member variable i will not be initialized when using the allocating contructor:
+* \code
+* struct BOOST_SYMBOL_EXPORT my_class { int i; my_class() : i(42) {} };
+* \endcode
+*
+* This does however not happen when the value is set inside the constructor function.
+*/
+class smart_library {
+ shared_library _lib;
+ detail::mangled_storage_impl _storage;
+
+public:
+ /*!
+ * Get the underlying shared_library
+ */
+ const shared_library &shared_lib() const {return _lib;}
+
+ using mangled_storage = detail::mangled_storage_impl;
+ /*!
+ * Acces to the mangled storage, which is created on construction.
+ *
+ * \throw Nothing.
+ */
+ const mangled_storage &symbol_storage() const {return _storage;}
+
+ //! \copydoc shared_library::shared_library()
+ smart_library() BOOST_NOEXCEPT {};
+
+ //! \copydoc shared_library::shared_library(const boost::filesystem::path& lib_path, load_mode::type mode = load_mode::default_mode)
+ smart_library(const boost::filesystem::path& lib_path, load_mode::type mode = load_mode::default_mode) {
+ _lib.load(lib_path, mode);
+ _storage.load(lib_path, mode);
+ }
+
+ //! \copydoc shared_library::shared_library(const boost::filesystem::path& lib_path, boost::system::error_code& ec, load_mode::type mode = load_mode::default_mode)
+ smart_library(const boost::filesystem::path& lib_path, boost::system::error_code& ec, load_mode::type mode = load_mode::default_mode) {
+ load(lib_path, mode, ec);
+ }
+
+ //! \copydoc shared_library::shared_library(const boost::filesystem::path& lib_path, load_mode::type mode, boost::system::error_code& ec)
+ smart_library(const boost::filesystem::path& lib_path, load_mode::type mode, boost::system::error_code& ec) {
+ load(lib_path, mode, ec);
+ }
+
+ //! \copydoc shared_library::shared_library(BOOST_RV_REF(smart_library) lib)
+ smart_library(BOOST_RV_REF(smart_library) lib) BOOST_NOEXCEPT // Move ctor
+ : _lib(boost::move(static_cast<shared_library&>(lib._lib))), _storage(boost::move(lib._storage))
+ {}
+
+ //! \copydoc shared_library::~shared_library()
+ ~smart_library() BOOST_NOEXCEPT {};
+
+ //! \copydoc shared_library::load(const boost::filesystem::path& lib_path, load_mode::type mode = load_mode::default_mode)
+ void load(const boost::filesystem::path& lib_path, load_mode::type mode = load_mode::default_mode) {
+ boost::system::error_code ec;
+ _storage.load(lib_path);
+ _lib.load(lib_path, mode, ec);
+
+ if (ec) {
+ boost::dll::detail::report_error(ec, "load() failed");
+ }
+ }
+
+ //! \copydoc shared_library::load(const boost::filesystem::path& lib_path, boost::system::error_code& ec, load_mode::type mode = load_mode::default_mode)
+ void load(const boost::filesystem::path& lib_path, boost::system::error_code& ec, load_mode::type mode = load_mode::default_mode) {
+ ec.clear();
+ _storage.load(lib_path);
+ _lib.load(lib_path, mode, ec);
+ }
+
+ //! \copydoc shared_library::load(const boost::filesystem::path& lib_path, load_mode::type mode, boost::system::error_code& ec)
+ void load(const boost::filesystem::path& lib_path, load_mode::type mode, boost::system::error_code& ec) {
+ ec.clear();
+ _storage.load(lib_path);
+ _lib.load(lib_path, mode, ec);
+ }
+
+ /*!
+ * Load a variable from the referenced library.
+ *
+ * Unlinke shared_library::get this function will also load scoped variables, which also includes static class members.
+ *
+ * \note When mangled, MSVC will also check the type.
+ *
+ * \param name Name of the variable
+ * \tparam T Type of the variable
+ * \return A reference to the variable of type T.
+ *
+ * \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded.
+ */
+ template<typename T>
+ T& get_variable(const std::string &name) {
+ return _lib.get<T>(_storage.get_variable<T>(name));
+ }
+
+ /*!
+ * Load a function from the referenced library.
+ *
+ * \b Example:
+ *
+ * \code
+ * smart_library lib("test_lib.so");
+ * typedef int (&add_ints)(int, int);
+ * typedef double (&add_doubles)(double, double);
+ * add_ints f1 = lib.get_function<int(int, int)> ("func_name");
+ * add_doubles f2 = lib.get_function<double(double, double)>("func_name");
+ * \endcode
+ *
+ * \note When mangled, MSVC will also check the return type.
+ *
+ * \param name Name of the function.
+ * \tparam Func Type of the function, required for determining the overload
+ * \return A reference to the function of type F.
+ *
+ * \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded.
+ */
+ template<typename Func>
+ Func& get_function(const std::string &name) {
+ return _lib.get<Func>(_storage.get_function<Func>(name));
+ }
+
+ /*!
+ * Load a member-function from the referenced library.
+ *
+ * \b Example (import class is MyClass, which is available inside the library and the host):
+ *
+ * \code
+ * smart_library lib("test_lib.so");
+ *
+ * typedef int MyClass(*func)(int);
+ * typedef int MyClass(*func_const)(int) const;
+ *
+ * add_ints f1 = lib.get_mem_fn<MyClass, int(int)> ("MyClass::function");
+ * add_doubles f2 = lib.get_mem_fn<const MyClass, double(double)>("MyClass::function");
+ * \endcode
+ *
+ * \note When mangled, MSVC will also check the return type.
+ *
+ * \param name Name of the function.
+ * \tparam Class The class the function is a member of. If Class is const, the function will be assumed as taking a const this-pointer. The same applies for volatile.
+ * \tparam Func Signature of the function, required for determining the overload
+ * \return A pointer to the member-function with the signature provided
+ *
+ * \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded.
+ */
+ template<typename Class, typename Func>
+ typename detail::get_mem_fn_type<Class, Func>::mem_fn get_mem_fn(const std::string& name) {
+ return _lib.get<typename detail::get_mem_fn_type<Class, Func>::mem_fn>(
+ _storage.get_mem_fn<Class, Func>(name)
+ );
+ }
+
+ /*!
+ * Load a constructor from the referenced library.
+ *
+ * \b Example (import class is MyClass, which is available inside the library and the host):
+ *
+ * \code
+ * smart_library lib("test_lib.so");
+ *
+ * constructor<MyClass(int) f1 = lib.get_mem_fn<MyClass(int)>();
+ * \endcode
+ *
+ * \tparam Signature Signature of the function, required for determining the overload. The return type is the class which this is the constructor of.
+ * \return A constructor object.
+ *
+ * \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded.
+ */
+ template<typename Signature>
+ constructor<Signature> get_constructor() {
+ return detail::load_ctor<Signature>(_lib, _storage.get_constructor<Signature>());
+ }
+
+ /*!
+ * Load a destructor from the referenced library.
+ *
+ * \b Example (import class is MyClass, which is available inside the library and the host):
+ *
+ * \code
+ * smart_library lib("test_lib.so");
+ *
+ * destructor<MyClass> f1 = lib.get_mem_fn<MyClass>();
+ * \endcode
+ *
+ * \tparam Class The class whichs destructor shall be loaded
+ * \return A destructor object.
+ *
+ * \throw boost::system::system_error if symbol does not exist or if the DLL/DSO was not loaded.
+ *
+ */
+ template<typename Class>
+ destructor<Class> get_destructor() {
+ return detail::load_dtor<Class>(_lib, _storage.get_destructor<Class>());
+ }
+ /**
+ * This function can be used to add a type alias.
+ *
+ * This is to be used, when a class shall be imported, which is not declared on the host side.
+ *
+ * Example:
+ * \code
+ * smart_library lib("test_lib.so");
+ *
+ * lib.add_type_alias<MyAlias>("MyClass"); //when using MyAlias, the library will look for MyClass
+ *
+ * //get the destructor of MyClass
+ * destructor<MyAlias> dtor = lib.get_destructor<MyAlias>();
+ * \endcode
+ *
+ *
+ * \param name Name of the class the alias is for.
+ *
+ * \attention If the alias-type is not large enough for the imported class, it will result in undefined behaviour.
+ * \warning The alias will only be applied for the type signature, it will not replace the token in the scoped name.
+ */
+ template<typename Alias> void add_type_alias(const std::string& name) {
+ this->_storage.add_alias<Alias>(name);
+ }
+
+ //! \copydoc shared_library::unload()
+ void unload() BOOST_NOEXCEPT {
+ _storage.clear();
+ _lib.unload();
+ }
+
+ //! \copydoc shared_library::is_loaded() const
+ bool is_loaded() const BOOST_NOEXCEPT {
+ return _lib.is_loaded();
+ }
+
+ //! \copydoc shared_library::operator!() const
+ bool operator!() const BOOST_NOEXCEPT {
+ return !is_loaded();
+ }
+
+ //! \copydoc shared_library::operator bool() const
+ BOOST_EXPLICIT_OPERATOR_BOOL()
+
+ //! \copydoc shared_library::has(const char* symbol_name) const
+ bool has(const char* symbol_name) const BOOST_NOEXCEPT {
+ return _lib.has(symbol_name);
+ }
+
+ //! \copydoc shared_library::has(const std::string& symbol_name) const
+ bool has(const std::string& symbol_name) const BOOST_NOEXCEPT {
+ return _lib.has(symbol_name);
+ }
+
+ //! \copydoc shared_library::assign(const shared_library& lib)
+ smart_library& assign(const smart_library& lib) {
+ _lib.assign(lib._lib);
+ _storage.assign(lib._storage);
+ return *this;
+ }
+
+ //! \copydoc shared_library::swap(shared_library& rhs)
+ void swap(smart_library& rhs) BOOST_NOEXCEPT {
+ _lib.swap(rhs._lib);
+ _storage.swap(rhs._storage);
+ }
+};
+
+/// Very fast equality check that compares the actual DLL/DSO objects. Throws nothing.
+inline bool operator==(const smart_library& lhs, const smart_library& rhs) BOOST_NOEXCEPT {
+ return lhs.shared_lib().native() == rhs.shared_lib().native();
+}
+
+/// Very fast inequality check that compares the actual DLL/DSO objects. Throws nothing.
+inline bool operator!=(const smart_library& lhs, const smart_library& rhs) BOOST_NOEXCEPT {
+ return lhs.shared_lib().native() != rhs.shared_lib().native();
+}
+
+/// Compare the actual DLL/DSO objects without any guarantee to be stable between runs. Throws nothing.
+inline bool operator<(const smart_library& lhs, const smart_library& rhs) BOOST_NOEXCEPT {
+ return lhs.shared_lib().native() < rhs.shared_lib().native();
+}
+
+/// Swaps two shared libraries. Does not invalidate symbols and functions loaded from libraries. Throws nothing.
+inline void swap(smart_library& lhs, smart_library& rhs) BOOST_NOEXCEPT {
+ lhs.swap(rhs);
+}
+
+
+} /* namespace experimental */
+} /* namespace dll */
+} /* namespace boost */
+
+#endif /* INCLUDE_BOOST_DLL_SMART_LIBRARY_HPP_ */
diff --git a/boost/endian/conversion.hpp b/boost/endian/conversion.hpp
index 7c145d9506..fc0e1a2360 100644
--- a/boost/endian/conversion.hpp
+++ b/boost/endian/conversion.hpp
@@ -50,7 +50,7 @@ namespace endian
//--------------------------------------------------------------------------------------//
// customization for exact-length arithmetic types. See doc/conversion.html/#FAQ.
- // Note: The omission of an overloads for the arithmetic type (typically long, or
+ // 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.
@@ -98,7 +98,7 @@ namespace endian
//------------------------------------------------------------------------------------//
- // Q: What happended to bswap, htobe, and the other synonym functions based on names
+ // Q: What happened to bswap, htobe, and the other synonym functions based on names
// popularized by BSD, OS X, and Linux?
// A: Turned out these may be implemented as macros on some systems. Ditto POSIX names
// for such functionality. Since macros would cause endless problems with functions
diff --git a/boost/endian/detail/intrinsic.hpp b/boost/endian/detail/intrinsic.hpp
index 6ead6813a2..0abd0ad435 100644
--- a/boost/endian/detail/intrinsic.hpp
+++ b/boost/endian/detail/intrinsic.hpp
@@ -18,8 +18,19 @@
#define __has_builtin(x) 0 // Compatibility with non-clang compilers
#endif
+#if defined(_MSC_VER)
+// Microsoft documents these as being compatible since Windows 95 and specifically
+// lists runtime library support since Visual Studio 2003 (aka 7.1).
+// Clang/c2 uses the Microsoft rather than GCC intrinsics, so we check for
+// defined(_MSC_VER) before defined(__clang__)
+# define BOOST_ENDIAN_INTRINSIC_MSG "cstdlib _byteswap_ushort, etc."
+# include <cstdlib>
+# define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(x) _byteswap_ushort(x)
+# define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(x) _byteswap_ulong(x)
+# define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(x) _byteswap_uint64(x)
+
// GCC and Clang recent versions provide intrinsic byte swaps via builtins
-#if (defined(__clang__) && __has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64)) \
+#elif (defined(__clang__) && __has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64)) \
|| (defined(__GNUC__ ) && \
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
# define BOOST_ENDIAN_INTRINSIC_MSG "__builtin_bswap16, etc."
@@ -45,14 +56,6 @@
# define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(x) bswap_32(x)
# define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(x) bswap_64(x)
-#elif defined(_MSC_VER)
-// Microsoft documents these as being compatible since Windows 95 and specificly
-// lists runtime library support since Visual Studio 2003 (aka 7.1).
-# define BOOST_ENDIAN_INTRINSIC_MSG "cstdlib _byteswap_ushort, etc."
-# include <cstdlib>
-# define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(x) _byteswap_ushort(x)
-# define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(x) _byteswap_ulong(x)
-# define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(x) _byteswap_uint64(x)
#else
# define BOOST_ENDIAN_NO_INTRINSICS
# define BOOST_ENDIAN_INTRINSIC_MSG "no byte swap intrinsics"
diff --git a/boost/fusion/adapted/adt/adapt_adt.hpp b/boost/fusion/adapted/adt/adapt_adt.hpp
index 7ff6f4eee2..2ebc76c36b 100644
--- a/boost/fusion/adapted/adt/adapt_adt.hpp
+++ b/boost/fusion/adapted/adt/adapt_adt.hpp
@@ -15,7 +15,6 @@
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/empty.hpp>
#include <boost/preprocessor/control/if.hpp>
-#include <boost/preprocessor/comparison/equal.hpp>
#include <boost/preprocessor/comparison/less.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/is_const.hpp>
@@ -45,13 +44,11 @@
TEMPLATE_PARAMS_SEQ, \
NAME_SEQ, \
I, \
- BOOST_PP_IF(IS_VIEW, BOOST_FUSION_PROXY_PREFIX, BOOST_PP_EMPTY), \
+ BOOST_PP_IIF(IS_VIEW, BOOST_FUSION_PROXY_PREFIX, BOOST_PP_EMPTY), \
BOOST_FUSION_ADAPT_ADT_WRAPPEDATTR(ATTRIBUTE), \
BOOST_FUSION_ADAPT_ADT_WRAPPEDATTR_SIZE(ATTRIBUTE), \
- BOOST_PP_IF( \
- BOOST_PP_LESS( \
- BOOST_FUSION_ADAPT_ADT_WRAPPEDATTR_SIZE(ATTRIBUTE), 4) \
- , 1, 0))
+ BOOST_PP_LESS( \
+ BOOST_FUSION_ADAPT_ADT_WRAPPEDATTR_SIZE(ATTRIBUTE), 4)) \
#define BOOST_FUSION_ADAPT_TPL_ADT(TEMPLATE_PARAMS_SEQ, NAME_SEQ , ATTRIBUTES) \
BOOST_FUSION_ADAPT_STRUCT_BASE( \
diff --git a/boost/fusion/adapted/adt/adapt_assoc_adt.hpp b/boost/fusion/adapted/adt/adapt_assoc_adt.hpp
index 49a8805d8a..bd451a32eb 100644
--- a/boost/fusion/adapted/adt/adapt_assoc_adt.hpp
+++ b/boost/fusion/adapted/adt/adapt_assoc_adt.hpp
@@ -14,7 +14,7 @@
#include <boost/fusion/support/config.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/empty.hpp>
-#include <boost/preprocessor/tuple/elem.hpp>
+#include <boost/preprocessor/control/if.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/remove_const.hpp>
@@ -46,13 +46,11 @@
TEMPLATE_PARAMS_SEQ, \
NAME_SEQ, \
I, \
- BOOST_PP_IF(IS_VIEW, BOOST_FUSION_PROXY_PREFIX, BOOST_PP_EMPTY), \
+ BOOST_PP_IIF(IS_VIEW, BOOST_FUSION_PROXY_PREFIX, BOOST_PP_EMPTY), \
BOOST_FUSION_ADAPT_ADT_WRAPPEDATTR(ATTRIBUTE), \
BOOST_FUSION_ADAPT_ADT_WRAPPEDATTR_SIZE(ATTRIBUTE), \
- BOOST_PP_IF( \
- BOOST_PP_LESS( \
- BOOST_FUSION_ADAPT_ADT_WRAPPEDATTR_SIZE(ATTRIBUTE), 5) \
- , 1, 0)) \
+ BOOST_PP_LESS( \
+ BOOST_FUSION_ADAPT_ADT_WRAPPEDATTR_SIZE(ATTRIBUTE), 5)) \
\
template< \
BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \
diff --git a/boost/fusion/adapted/adt/detail/adapt_base.hpp b/boost/fusion/adapted/adt/detail/adapt_base.hpp
index dec17251df..0ef6fcd92b 100644
--- a/boost/fusion/adapted/adt/detail/adapt_base.hpp
+++ b/boost/fusion/adapted/adt/detail/adapt_base.hpp
@@ -15,8 +15,10 @@
#include <boost/fusion/adapted/struct/detail/adapt_is_tpl.hpp>
#include <boost/preprocessor/control/if.hpp>
+#include <boost/preprocessor/control/expr_if.hpp>
#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/seq/elem.hpp>
+#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/add_const.hpp>
@@ -36,18 +38,18 @@
boost::remove_const<boost::remove_reference<lvalue>::type>::type
#define BOOST_FUSION_ADAPT_ADT_ATTRIBUTE_GETEXPR(ATTRIBUTE, \
- ATTRIBUTE_TUPEL_SIZE, DEDUCE_TYPE) \
- BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE, \
+ ATTRIBUTE_TUPLE_SIZE, DEDUCE_TYPE) \
+ BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE, \
BOOST_PP_IF(DEDUCE_TYPE, 0, 2), ATTRIBUTE)
#define BOOST_FUSION_ADAPT_ADT_ATTRIBUTE_SETEXPR(ATTRIBUTE, \
- ATTRIBUTE_TUPEL_SIZE, DEDUCE_TYPE) \
- BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE, \
+ ATTRIBUTE_TUPLE_SIZE, DEDUCE_TYPE) \
+ BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE, \
BOOST_PP_IF(DEDUCE_TYPE, 1, 3), ATTRIBUTE)
#ifdef BOOST_MSVC
# define BOOST_FUSION_DEDUCED_ATTR_TYPE(NAME_SEQ, ATTRIBUTE, \
- ATTRIBUTE_TUPEL_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \
+ ATTRIBUTE_TUPLE_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \
\
BOOST_FUSION_ADAPT_STRUCT_MSVC_REDEFINE_TEMPLATE_PARAMS( \
TEMPLATE_PARAMS_SEQ) \
@@ -55,52 +57,57 @@
struct deduced_attr_type { \
static const BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ)& obj; \
typedef \
- BOOST_PP_IF(BOOST_FUSION_ADAPT_IS_TPL(TEMPLATE_PARAMS_SEQ),typename,) \
+ BOOST_PP_EXPR_IF(BOOST_FUSION_ADAPT_IS_TPL(TEMPLATE_PARAMS_SEQ), \
+ typename) \
BOOST_TYPEOF( PREFIX() BOOST_FUSION_ADAPT_ADT_ATTRIBUTE_GETEXPR( \
- ATTRIBUTE, ATTRIBUTE_TUPEL_SIZE, 1)) type; \
+ ATTRIBUTE, ATTRIBUTE_TUPLE_SIZE, 1)) type; \
};
#else
# define BOOST_FUSION_DEDUCED_ATTR_TYPE(NAME_SEQ, ATTRIBUTE, \
- ATTRIBUTE_TUPEL_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \
+ ATTRIBUTE_TUPLE_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \
struct deduced_attr_type { \
static const BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ)& obj; \
typedef BOOST_TYPEOF( PREFIX() BOOST_FUSION_ADAPT_ADT_ATTRIBUTE_GETEXPR( \
- ATTRIBUTE, ATTRIBUTE_TUPEL_SIZE, 1)) type; \
+ ATTRIBUTE, ATTRIBUTE_TUPLE_SIZE, 1)) type; \
};
#endif
#define BOOST_FUSION_ADT_ATTRIBUTE_TYPEOF( \
- NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPEL_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \
+ NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPLE_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \
\
BOOST_FUSION_DEDUCED_ATTR_TYPE( \
- NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPEL_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \
+ NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPLE_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \
\
typedef \
- BOOST_PP_IF(BOOST_FUSION_ADAPT_IS_TPL(TEMPLATE_PARAMS_SEQ),typename,) \
+ BOOST_PP_EXPR_IF(BOOST_FUSION_ADAPT_IS_TPL(TEMPLATE_PARAMS_SEQ), \
+ typename) \
boost::remove_const< \
- BOOST_PP_IF(BOOST_FUSION_ADAPT_IS_TPL(TEMPLATE_PARAMS_SEQ),typename,) \
+ BOOST_PP_EXPR_IF(BOOST_FUSION_ADAPT_IS_TPL(TEMPLATE_PARAMS_SEQ), \
+ typename) \
deduced_attr_type::type \
>::type type; \
\
typedef \
- BOOST_PP_IF(BOOST_FUSION_ADAPT_IS_TPL(TEMPLATE_PARAMS_SEQ),typename,) \
+ BOOST_PP_EXPR_IF(BOOST_FUSION_ADAPT_IS_TPL(TEMPLATE_PARAMS_SEQ), \
+ typename) \
boost::add_const< \
- BOOST_PP_IF(BOOST_FUSION_ADAPT_IS_TPL(TEMPLATE_PARAMS_SEQ),typename,) \
+ BOOST_PP_EXPR_IF(BOOST_FUSION_ADAPT_IS_TPL(TEMPLATE_PARAMS_SEQ), \
+ typename) \
deduced_attr_type::type \
>::type const_type;
#define BOOST_FUSION_ADT_ATTRIBUTE_GIVENTYPE( \
- NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPEL_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \
+ NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPLE_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \
\
- typedef BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE, 0, ATTRIBUTE) type; \
- typedef BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE, 1, ATTRIBUTE) const_type;
+ typedef BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE, 0, ATTRIBUTE) type; \
+ typedef BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE, 1, ATTRIBUTE) const_type;
#define BOOST_FUSION_ADAPT_ADT_C_BASE( \
TEMPLATE_PARAMS_SEQ,NAME_SEQ,I,PREFIX, \
- ATTRIBUTE,ATTRIBUTE_TUPEL_SIZE, DEDUCE_TYPE) \
+ ATTRIBUTE,ATTRIBUTE_TUPLE_SIZE, DEDUCE_TYPE) \
\
template< \
BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \
@@ -116,7 +123,7 @@
BOOST_FUSION_ADT_ATTRIBUTE_GIVENTYPE)( \
NAME_SEQ, \
ATTRIBUTE, \
- ATTRIBUTE_TUPEL_SIZE, \
+ ATTRIBUTE_TUPLE_SIZE, \
PREFIX, \
TEMPLATE_PARAMS_SEQ) \
\
@@ -128,7 +135,7 @@
Val const& val) \
{ \
PREFIX() BOOST_FUSION_ADAPT_ADT_ATTRIBUTE_SETEXPR(ATTRIBUTE, \
- ATTRIBUTE_TUPEL_SIZE, DEDUCE_TYPE); \
+ ATTRIBUTE_TUPLE_SIZE, DEDUCE_TYPE); \
} \
\
BOOST_FUSION_GPU_ENABLED \
@@ -137,7 +144,7 @@
BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ)& obj) \
{ \
return PREFIX() BOOST_FUSION_ADAPT_ADT_ATTRIBUTE_GETEXPR(ATTRIBUTE, \
- ATTRIBUTE_TUPEL_SIZE, DEDUCE_TYPE); \
+ ATTRIBUTE_TUPLE_SIZE, DEDUCE_TYPE); \
} \
\
BOOST_FUSION_GPU_ENABLED \
@@ -146,7 +153,7 @@
BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) const& obj) \
{ \
return PREFIX() BOOST_FUSION_ADAPT_ADT_ATTRIBUTE_GETEXPR(ATTRIBUTE, \
- ATTRIBUTE_TUPEL_SIZE, DEDUCE_TYPE); \
+ ATTRIBUTE_TUPLE_SIZE, DEDUCE_TYPE); \
} \
}; \
\
@@ -160,7 +167,7 @@
> \
{ \
typedef \
- BOOST_PP_IF(BOOST_PP_SEQ_HEAD(TEMPLATE_PARAMS_SEQ), typename, ) \
+ BOOST_PP_EXPR_IF(BOOST_PP_SEQ_HEAD(TEMPLATE_PARAMS_SEQ), typename) \
access::adt_attribute_access< \
BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \
, I \
@@ -201,7 +208,7 @@
> \
{ \
typedef \
- BOOST_PP_IF(BOOST_PP_SEQ_HEAD(TEMPLATE_PARAMS_SEQ), typename, ) \
+ BOOST_PP_EXPR_IF(BOOST_PP_SEQ_HEAD(TEMPLATE_PARAMS_SEQ), typename) \
access::adt_attribute_access< \
BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \
, I \
@@ -252,7 +259,8 @@
, I \
> \
{ \
- typedef BOOST_PP_IF(BOOST_PP_SEQ_HEAD(TEMPLATE_PARAMS_SEQ), typename, ) \
+ typedef BOOST_PP_EXPR_IF(BOOST_PP_SEQ_HEAD(TEMPLATE_PARAMS_SEQ), \
+ typename) \
adt_attribute_proxy< \
BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \
, I \
diff --git a/boost/fusion/adapted/adt/detail/adapt_base_assoc_attr_filler.hpp b/boost/fusion/adapted/adt/detail/adapt_base_assoc_attr_filler.hpp
index b9c93b7d59..daa73063a0 100644
--- a/boost/fusion/adapted/adt/detail/adapt_base_assoc_attr_filler.hpp
+++ b/boost/fusion/adapted/adt/detail/adapt_base_assoc_attr_filler.hpp
@@ -10,12 +10,15 @@
#include <boost/config.hpp>
+#include <boost/fusion/adapted/struct/detail/adapt_auto.hpp>
#include <boost/fusion/adapted/adt/detail/adapt_base_attr_filler.hpp>
-#include <boost/preprocessor/control/if.hpp>
+#include <boost/mpl/aux_/preprocessor/token_equal.hpp>
+
+#include <boost/preprocessor/config/config.hpp>
+#include <boost/preprocessor/control/iif.hpp>
#include <boost/preprocessor/variadic/size.hpp>
-#include <boost/preprocessor/empty.hpp>
-#include <boost/preprocessor/facilities/is_empty.hpp>
+#include <boost/preprocessor/arithmetic/dec.hpp>
#if BOOST_PP_VARIADICS
@@ -41,7 +44,7 @@
BOOST_FUSION_ADAPT_ASSOC_ADT_FILLER_0
#define BOOST_FUSION_ADAPT_ASSOC_ADT_WRAP_ATTR(A, B, C, D, E) \
- BOOST_PP_IF(BOOST_PP_IS_EMPTY(A), \
+ BOOST_PP_IIF(BOOST_MPL_PP_TOKEN_EQUAL(auto, A), \
((3, (C,D,E))), \
((5, (A,B,C,D,E))) \
)
@@ -55,7 +58,7 @@
#define BOOST_FUSION_ADAPT_ASSOC_ADT_WRAPPEDATTR_GET_KEY(ATTRIBUTE) \
BOOST_PP_TUPLE_ELEM( \
BOOST_FUSION_ADAPT_ADT_WRAPPEDATTR_SIZE(ATTRIBUTE), \
- BOOST_PP_SUB(BOOST_FUSION_ADAPT_ADT_WRAPPEDATTR_SIZE(ATTRIBUTE), 1), \
+ BOOST_PP_DEC(BOOST_FUSION_ADAPT_ADT_WRAPPEDATTR_SIZE(ATTRIBUTE)), \
BOOST_FUSION_ADAPT_ADT_WRAPPEDATTR(ATTRIBUTE))
#endif
diff --git a/boost/fusion/adapted/adt/detail/adapt_base_attr_filler.hpp b/boost/fusion/adapted/adt/detail/adapt_base_attr_filler.hpp
index 09bd4014ed..dc9e2c3b13 100644
--- a/boost/fusion/adapted/adt/detail/adapt_base_attr_filler.hpp
+++ b/boost/fusion/adapted/adt/detail/adapt_base_attr_filler.hpp
@@ -9,24 +9,22 @@
#define BOOST_FUSION_ADAPTED_ADT_DETAIL_ADAPT_BASE_ATTR_FILLER_HPP
#include <boost/config.hpp>
+
+#include <boost/fusion/adapted/struct/detail/adapt_auto.hpp>
#include <boost/fusion/adapted/struct/detail/preprocessor/is_seq.hpp>
-#include <boost/preprocessor/arithmetic/sub.hpp>
-#include <boost/preprocessor/control/if.hpp>
+#include <boost/mpl/aux_/preprocessor/token_equal.hpp>
+
+#include <boost/preprocessor/arithmetic/dec.hpp>
+#include <boost/preprocessor/control/iif.hpp>
#include <boost/preprocessor/logical/or.hpp>
-#include <boost/preprocessor/empty.hpp>
-#include <boost/preprocessor/tuple/size.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
-#include <boost/preprocessor/facilities/is_empty.hpp>
#include <boost/preprocessor/variadic/to_seq.hpp>
-#include <boost/preprocessor/variadic/to_tuple.hpp>
+#include <boost/preprocessor/variadic/size.hpp>
#include <boost/preprocessor/variadic/elem.hpp>
-#include <boost/preprocessor/seq/for_each.hpp>
-#include <boost/preprocessor/seq/push_front.hpp>
+#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/seq/rest_n.hpp>
-#include <boost/preprocessor/tuple/reverse.hpp>
-
#define BOOST_FUSION_ADAPT_ADT_WRAPPEDATTR_SIZE(ATTRIBUTE) \
BOOST_PP_TUPLE_ELEM(2, 0, ATTRIBUTE)
@@ -47,11 +45,15 @@
# define BOOST_FUSION_ADAPT_ADT_FILLER_0_END
# define BOOST_FUSION_ADAPT_ADT_FILLER_1_END
+// MSVC don't compile when using BOOST_PP_BITOR instead of BOOST_PP_OR.
# define BOOST_FUSION_ADAPT_ADT_FILLER(...) \
- BOOST_PP_IF( \
+ BOOST_PP_IIF( \
BOOST_PP_OR( \
- BOOST_PP_IS_EMPTY(BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__)), \
- BOOST_PP_IS_EMPTY(BOOST_PP_VARIADIC_ELEM(1, __VA_ARGS__))), \
+ BOOST_MPL_PP_TOKEN_EQUAL(auto, \
+ BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__)), \
+ BOOST_MPL_PP_TOKEN_EQUAL(auto, \
+ BOOST_PP_VARIADIC_ELEM(1, __VA_ARGS__))), \
+ \
BOOST_FUSION_ADAPT_ADT_WRAP_ATTR( \
BOOST_PP_VARIADIC_ELEM(2, __VA_ARGS__), \
BOOST_FUSION_WORKAROUND_VARIADIC_EMPTINESS_LAST_ELEM(__VA_ARGS__) \
@@ -63,7 +65,7 @@
# define BOOST_FUSION_WORKAROUND_VARIADIC_EMPTINESS_LAST_ELEM(...) \
BOOST_PP_SEQ_HEAD(BOOST_PP_SEQ_REST_N( \
- BOOST_PP_SUB(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), 1), \
+ BOOST_PP_DEC(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__)), \
BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)))
#else // BOOST_PP_VARIADICS
@@ -80,7 +82,7 @@
# define BOOST_FUSION_ADAPT_ADT_FILLER_1_END
# define BOOST_FUSION_ADAPT_ADT_WRAP_ATTR(A, B, C, D) \
- BOOST_PP_IF(BOOST_PP_IS_EMPTY(A), \
+ BOOST_PP_IIF(BOOST_MPL_PP_TOKEN_EQUAL(auto, A), \
((2, (C,D))), \
((4, (A,B,C,D))) \
)
diff --git a/boost/fusion/adapted/struct/adapt_assoc_struct.hpp b/boost/fusion/adapted/struct/adapt_assoc_struct.hpp
index eab4e1bb6d..c8659fdfe1 100644
--- a/boost/fusion/adapted/struct/adapt_assoc_struct.hpp
+++ b/boost/fusion/adapted/struct/adapt_assoc_struct.hpp
@@ -13,7 +13,8 @@
#include <boost/fusion/support/config.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/empty.hpp>
-#include <boost/preprocessor/tuple/elem.hpp>
+#include <boost/preprocessor/control/iif.hpp>
+#include <boost/preprocessor/comparison/less.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/add_const.hpp>
@@ -44,11 +45,11 @@
NAME_SEQ, \
IS_VIEW, \
I, \
- PREFIX, \
+ BOOST_PP_IIF(IS_VIEW, BOOST_FUSION_PROXY_PREFIX, BOOST_PP_EMPTY), \
BOOST_FUSION_ADAPT_STRUCT_WRAPPEDATTR(ATTRIBUTE), \
BOOST_FUSION_ADAPT_STRUCT_WRAPPEDATTR_SIZE(ATTRIBUTE), \
- BOOST_PP_IF(BOOST_PP_LESS( \
- BOOST_FUSION_ADAPT_STRUCT_WRAPPEDATTR_SIZE(ATTRIBUTE),3), 1, 0)) \
+ BOOST_PP_LESS( \
+ BOOST_FUSION_ADAPT_STRUCT_WRAPPEDATTR_SIZE(ATTRIBUTE),3)) \
\
template< \
BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \
diff --git a/boost/fusion/adapted/struct/adapt_assoc_struct_named.hpp b/boost/fusion/adapted/struct/adapt_assoc_struct_named.hpp
index 2f1a9a3037..0d97db5c6a 100644
--- a/boost/fusion/adapted/struct/adapt_assoc_struct_named.hpp
+++ b/boost/fusion/adapted/struct/adapt_assoc_struct_named.hpp
@@ -12,13 +12,6 @@
#include <boost/fusion/adapted/struct/adapt_assoc_struct.hpp>
#include <boost/fusion/adapted/struct/detail/proxy_type.hpp>
-#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_NAMED_FILLER_0(X, Y, Z) \
- (X, obj.Y, Z) BOOST_FUSION_ADAPT_ASSOC_STRUCT_NAMED_FILLER_1
-#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_NAMED_FILLER_1(X, Y, Z) \
- (X, obj.Y, Z) BOOST_FUSION_ADAPT_ASSOC_STRUCT_NAMED_FILLER_0
-#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_NAMED_FILLER_0_END
-#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_NAMED_FILLER_1_END
-
#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_NAMED_NS( \
WRAPPED_TYPE, NAMESPACE_SEQ, NAME, ATTRIBUTES) \
\
@@ -27,9 +20,7 @@
\
BOOST_FUSION_ADAPT_ASSOC_STRUCT_AS_VIEW( \
BOOST_FUSION_ADAPT_STRUCT_NAMESPACE_DECLARATION((0)NAMESPACE_SEQ)NAME, \
- BOOST_PP_CAT( \
- BOOST_FUSION_ADAPT_ASSOC_STRUCT_NAMED_FILLER_0 ATTRIBUTES, \
- _END))
+ ATTRIBUTES)
#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_NAMED(WRAPPED_TYPE, NAME, ATTRIBUTES) \
BOOST_FUSION_ADAPT_ASSOC_STRUCT_NAMED_NS( \
diff --git a/boost/fusion/adapted/struct/adapt_struct.hpp b/boost/fusion/adapted/struct/adapt_struct.hpp
index 2744f5b218..66710b47ff 100644
--- a/boost/fusion/adapted/struct/adapt_struct.hpp
+++ b/boost/fusion/adapted/struct/adapt_struct.hpp
@@ -14,9 +14,8 @@
#include <boost/preprocessor/config/config.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/empty.hpp>
-#include <boost/preprocessor/control/if.hpp>
+#include <boost/preprocessor/control/iif.hpp>
#include <boost/preprocessor/comparison/less.hpp>
-#include <boost/preprocessor/comparison/equal.hpp>
#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/variadic/to_seq.hpp>
#include <boost/type_traits/add_reference.hpp>
@@ -45,13 +44,11 @@
NAME_SEQ, \
IS_VIEW, \
I, \
- BOOST_PP_IF(IS_VIEW, BOOST_FUSION_PROXY_PREFIX, BOOST_PP_EMPTY), \
+ BOOST_PP_IIF(IS_VIEW, BOOST_FUSION_PROXY_PREFIX, BOOST_PP_EMPTY), \
BOOST_FUSION_ADAPT_STRUCT_WRAPPEDATTR(ATTRIBUTE), \
BOOST_FUSION_ADAPT_STRUCT_WRAPPEDATTR_SIZE(ATTRIBUTE), \
- BOOST_PP_IF( \
- BOOST_PP_LESS( \
- BOOST_FUSION_ADAPT_STRUCT_WRAPPEDATTR_SIZE(ATTRIBUTE), 2) \
- , 1, 0))
+ BOOST_PP_LESS( \
+ BOOST_FUSION_ADAPT_STRUCT_WRAPPEDATTR_SIZE(ATTRIBUTE), 2))
@@ -86,7 +83,7 @@
BOOST_FUSION_ADAPT_STRUCT_ATTRIBUTES_FILLER( \
BOOST_PP_SEQ_TAIL(BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))), \
BOOST_FUSION_ADAPT_STRUCT_C)
-
+
#else // BOOST_PP_VARIADICS
# define BOOST_FUSION_ADAPT_TPL_STRUCT( \
diff --git a/boost/fusion/adapted/struct/adapt_struct_named.hpp b/boost/fusion/adapted/struct/adapt_struct_named.hpp
index 791fb5b0d0..0c61b42a97 100644
--- a/boost/fusion/adapted/struct/adapt_struct_named.hpp
+++ b/boost/fusion/adapted/struct/adapt_struct_named.hpp
@@ -13,7 +13,7 @@
#include <boost/fusion/support/config.hpp>
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/adapted/struct/detail/proxy_type.hpp>
-#include <boost/preprocessor/empty.hpp>
+#include <boost/preprocessor/config/config.hpp>
#ifdef BOOST_PP_VARIADICS
diff --git a/boost/fusion/adapted/struct/define_assoc_struct.hpp b/boost/fusion/adapted/struct/define_assoc_struct.hpp
index f4a3679d73..faea077fb7 100644
--- a/boost/fusion/adapted/struct/define_assoc_struct.hpp
+++ b/boost/fusion/adapted/struct/define_assoc_struct.hpp
@@ -11,6 +11,7 @@
#include <boost/fusion/support/config.hpp>
#include <boost/fusion/adapted/struct/adapt_assoc_struct.hpp>
#include <boost/fusion/adapted/struct/detail/define_struct.hpp>
+#include <boost/preprocessor/cat.hpp>
#define BOOST_FUSION_DEFINE_ASSOC_STRUCT_FILLER_0(X, Y, Z) \
((X, Y, Z)) BOOST_FUSION_DEFINE_ASSOC_STRUCT_FILLER_1
diff --git a/boost/fusion/adapted/struct/define_struct.hpp b/boost/fusion/adapted/struct/define_struct.hpp
index 2978543672..c9ae422976 100644
--- a/boost/fusion/adapted/struct/define_struct.hpp
+++ b/boost/fusion/adapted/struct/define_struct.hpp
@@ -11,6 +11,7 @@
#include <boost/fusion/support/config.hpp>
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/adapted/struct/detail/define_struct.hpp>
+#include <boost/preprocessor/cat.hpp>
#define BOOST_FUSION_DEFINE_TPL_STRUCT( \
TEMPLATE_PARAMS_SEQ, NAMESPACE_SEQ, NAME, ATTRIBUTES) \
diff --git a/boost/fusion/adapted/struct/detail/adapt_auto.hpp b/boost/fusion/adapted/struct/detail/adapt_auto.hpp
index 5178150b4b..71a542c7a4 100644
--- a/boost/fusion/adapted/struct/detail/adapt_auto.hpp
+++ b/boost/fusion/adapted/struct/detail/adapt_auto.hpp
@@ -8,8 +8,7 @@
#ifndef BOOST_FUSION_ADAPTED_STRUCT_DETAIL_ADAPT_AUTO_HPP
#define BOOST_FUSION_ADAPTED_STRUCT_DETAIL_ADAPT_AUTO_HPP
-#include <boost/preprocessor/empty.hpp>
-
-#define BOOST_FUSION_ADAPT_AUTO BOOST_PP_EMPTY()
+#define BOOST_FUSION_ADAPT_AUTO auto
+#define BOOST_MPL_PP_TOKEN_EQUAL_auto(x) x
#endif
diff --git a/boost/fusion/adapted/struct/detail/adapt_base.hpp b/boost/fusion/adapted/struct/detail/adapt_base.hpp
index 8ec467aed9..84b9302c44 100644
--- a/boost/fusion/adapted/struct/detail/adapt_base.hpp
+++ b/boost/fusion/adapted/struct/detail/adapt_base.hpp
@@ -29,6 +29,7 @@
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/arithmetic/dec.hpp>
#include <boost/preprocessor/comparison/less.hpp>
+#include <boost/preprocessor/logical/not.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/tag.hpp>
#include <boost/mpl/eval_if.hpp>
@@ -64,7 +65,7 @@
#ifdef BOOST_MSVC
# define BOOST_FUSION_ATTRIBUTE_TYPEOF( \
- NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPEL_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \
+ NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPLE_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \
\
BOOST_FUSION_ADAPT_STRUCT_MSVC_REDEFINE_TEMPLATE_PARAMS( \
TEMPLATE_PARAMS_SEQ) \
@@ -73,7 +74,7 @@
static const BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ)& obj; \
typedef \
BOOST_PP_IF(BOOST_FUSION_ADAPT_IS_TPL(TEMPLATE_PARAMS_SEQ), typename, ) \
- BOOST_TYPEOF( PREFIX() obj.BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE, \
+ BOOST_TYPEOF( PREFIX() obj.BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE, \
0, ATTRIBUTE)) \
type; \
}; \
@@ -84,12 +85,12 @@
#else
# define BOOST_FUSION_ATTRIBUTE_TYPEOF( \
- NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPEL_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \
+ NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPLE_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \
\
struct deduced_attr_type { \
static const BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ)& obj; \
typedef BOOST_TYPEOF( \
- PREFIX() obj.BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE, 0, ATTRIBUTE)) \
+ PREFIX() obj.BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE, 0, ATTRIBUTE)) \
type; \
}; \
\
@@ -100,9 +101,9 @@
#endif
#define BOOST_FUSION_ATTRIBUTE_GIVENTYPE( \
- NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPEL_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \
+ NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPLE_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \
typedef \
- BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE, 0, ATTRIBUTE) attribute_type;
+ BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE, 0, ATTRIBUTE) attribute_type;
#ifdef BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS
@@ -159,7 +160,7 @@
#define BOOST_FUSION_ADAPT_STRUCT_C_BASE( \
TEMPLATE_PARAMS_SEQ,NAME_SEQ,IS_VIEW, \
- I,PREFIX,ATTRIBUTE,ATTRIBUTE_TUPEL_SIZE, \
+ I,PREFIX,ATTRIBUTE,ATTRIBUTE_TUPLE_SIZE, \
DEDUCE_TYPE) \
\
template< \
@@ -174,7 +175,7 @@
BOOST_FUSION_ATTRIBUTE_TYPEOF, BOOST_FUSION_ATTRIBUTE_GIVENTYPE)( \
NAME_SEQ, \
ATTRIBUTE, \
- ATTRIBUTE_TUPEL_SIZE, \
+ ATTRIBUTE_TUPLE_SIZE, \
PREFIX, \
TEMPLATE_PARAMS_SEQ) \
\
@@ -201,8 +202,8 @@
call(Seq& seq) \
{ \
return seq.PREFIX() \
- BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE, \
- BOOST_PP_IF(DEDUCE_TYPE, 0, 1), ATTRIBUTE); \
+ BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE, \
+ BOOST_PP_NOT(DEDUCE_TYPE), ATTRIBUTE); \
} \
}; \
}; \
@@ -222,9 +223,8 @@
call() \
{ \
return BOOST_PP_STRINGIZE( \
- BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE, \
- BOOST_PP_IF(DEDUCE_TYPE, 0, 1), \
- ATTRIBUTE)); \
+ BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE, \
+ BOOST_PP_NOT(DEDUCE_TYPE), ATTRIBUTE)); \
} \
};
@@ -274,7 +274,7 @@ namespace boost
struct struct_is_view< \
BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \
> \
- : mpl::BOOST_PP_IF(IS_VIEW,true_,false_) \
+ : mpl::BOOST_PP_IIF(IS_VIEW,true_,false_) \
{}; \
} \
} \
diff --git a/boost/fusion/adapted/struct/detail/adapt_base_assoc_attr_filler.hpp b/boost/fusion/adapted/struct/detail/adapt_base_assoc_attr_filler.hpp
index c75e83c397..8c4801111e 100644
--- a/boost/fusion/adapted/struct/detail/adapt_base_assoc_attr_filler.hpp
+++ b/boost/fusion/adapted/struct/detail/adapt_base_assoc_attr_filler.hpp
@@ -10,13 +10,16 @@
#include <boost/config.hpp>
+#include <boost/fusion/adapted/struct/detail/adapt_auto.hpp>
#include <boost/fusion/adapted/struct/detail/adapt_base_attr_filler.hpp>
-#include <boost/preprocessor/control/if.hpp>
-#include <boost/preprocessor/arithmetic/sub.hpp>
+#include <boost/mpl/aux_/preprocessor/token_equal.hpp>
+
+#include <boost/preprocessor/config/config.hpp>
+#include <boost/preprocessor/control/iif.hpp>
+#include <boost/preprocessor/arithmetic/dec.hpp>
#include <boost/preprocessor/variadic/size.hpp>
-#include <boost/preprocessor/empty.hpp>
-#include <boost/preprocessor/facilities/is_empty.hpp>
+#include <boost/preprocessor/variadic/elem.hpp>
#if BOOST_PP_VARIADICS
@@ -29,7 +32,14 @@
BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLER_0
#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_WRAP_ATTR(...) \
- ((BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), (__VA_ARGS__)))
+ BOOST_PP_IIF( \
+ BOOST_MPL_PP_TOKEN_EQUAL(auto, BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__)), \
+ ((2, \
+ (BOOST_PP_VARIADIC_ELEM(1, __VA_ARGS__), \
+ BOOST_PP_VARIADIC_ELEM(2, __VA_ARGS__)))), \
+ ((BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), \
+ (__VA_ARGS__))) \
+ )
#else // BOOST_PP_VARIADICS
@@ -43,7 +53,7 @@
BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLER_0
#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_WRAP_ATTR(X, Y, Z) \
- BOOST_PP_IF(BOOST_PP_IS_EMPTY(X), \
+ BOOST_PP_IIF(BOOST_MPL_PP_TOKEN_EQUAL(auto, X), \
((2, (Y,Z))), \
((3, (X,Y,Z))) \
)
@@ -57,7 +67,7 @@
#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_WRAPPEDATTR_GET_KEY(ATTRIBUTE) \
BOOST_PP_TUPLE_ELEM( \
BOOST_FUSION_ADAPT_STRUCT_WRAPPEDATTR_SIZE(ATTRIBUTE), \
- BOOST_PP_SUB(BOOST_FUSION_ADAPT_STRUCT_WRAPPEDATTR_SIZE(ATTRIBUTE), 1), \
+ BOOST_PP_DEC(BOOST_FUSION_ADAPT_STRUCT_WRAPPEDATTR_SIZE(ATTRIBUTE)), \
BOOST_FUSION_ADAPT_STRUCT_WRAPPEDATTR(ATTRIBUTE))
#endif
diff --git a/boost/fusion/adapted/struct/detail/adapt_base_attr_filler.hpp b/boost/fusion/adapted/struct/detail/adapt_base_attr_filler.hpp
index 7a83bb347c..3755bc3679 100644
--- a/boost/fusion/adapted/struct/detail/adapt_base_attr_filler.hpp
+++ b/boost/fusion/adapted/struct/detail/adapt_base_attr_filler.hpp
@@ -9,15 +9,21 @@
#define BOOST_FUSION_ADAPTED_STRUCT_DETAIL_ADAPT_BASE_ATTR_FILLER_HPP
#include <boost/config.hpp>
+
+#include <boost/fusion/adapted/struct/detail/adapt_auto.hpp>
#include <boost/fusion/adapted/struct/detail/preprocessor/is_seq.hpp>
-#include <boost/preprocessor/empty.hpp>
-#include <boost/preprocessor/tuple/size.hpp>
+#include <boost/mpl/aux_/preprocessor/token_equal.hpp>
+
+#include <boost/preprocessor/config/config.hpp>
+#include <boost/preprocessor/control/iif.hpp>
+#include <boost/preprocessor/control/expr_iif.hpp>
+#include <boost/preprocessor/logical/compl.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
-#include <boost/preprocessor/facilities/is_empty.hpp>
-#include <boost/preprocessor/variadic/to_seq.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/push_front.hpp>
+#include <boost/preprocessor/facilities/expand.hpp>
+#include <boost/preprocessor/facilities/is_empty.hpp>
#define BOOST_FUSION_ADAPT_STRUCT_FILLER_0(X, Y) \
@@ -32,7 +38,7 @@
#define BOOST_FUSION_ADAPT_STRUCT_FILLER_1_END
#define BOOST_FUSION_ADAPT_STRUCT_WRAP_ATTR(X, Y) \
- BOOST_PP_IF(BOOST_PP_IS_EMPTY(X), \
+ BOOST_PP_IIF(BOOST_MPL_PP_TOKEN_EQUAL(auto, BOOST_PP_EXPAND(X)), \
((1, (Y))), \
((2, (X,Y))) \
)
@@ -47,12 +53,10 @@
#if BOOST_PP_VARIADICS
# define BOOST_FUSION_ADAPT_STRUCT_ATTRIBUTES_FILLER_OP(r, unused, elem) \
- BOOST_PP_IF(BOOST_FUSION_PP_IS_SEQ(elem), \
- BOOST_PP_CAT( BOOST_FUSION_ADAPT_STRUCT_FILLER_0 elem ,_END), \
- BOOST_PP_IF(BOOST_PP_IS_EMPTY(elem), \
- BOOST_PP_EMPTY(), \
- BOOST_FUSION_ADAPT_STRUCT_WRAP_ATTR(BOOST_FUSION_ADAPT_AUTO,elem))\
- )
+ BOOST_PP_IIF(BOOST_FUSION_PP_IS_SEQ(elem), \
+ BOOST_PP_CAT(BOOST_FUSION_ADAPT_STRUCT_FILLER_0 elem ,_END), \
+ BOOST_PP_EXPR_IIF(BOOST_PP_COMPL(BOOST_PP_IS_EMPTY(elem)), \
+ BOOST_FUSION_ADAPT_STRUCT_WRAP_ATTR(auto, elem)))
# define BOOST_FUSION_ADAPT_STRUCT_ATTRIBUTES_FILLER(VA_ARGS_SEQ) \
BOOST_PP_SEQ_PUSH_FRONT( \
diff --git a/boost/fusion/adapted/struct/detail/adapt_is_tpl.hpp b/boost/fusion/adapted/struct/detail/adapt_is_tpl.hpp
index 2b54a2c0c7..8430262f8c 100644
--- a/boost/fusion/adapted/struct/detail/adapt_is_tpl.hpp
+++ b/boost/fusion/adapted/struct/detail/adapt_is_tpl.hpp
@@ -8,6 +8,8 @@
#ifndef BOOST_FUSION_ADAPTED_STRUCT_DETAIL_ADAPT_IS_TPL_HPP
#define BOOST_FUSION_ADAPTED_STRUCT_DETAIL_ADAPT_IS_TPL_HPP
+#include <boost/preprocessor/seq/seq.hpp>
+
#define BOOST_FUSION_ADAPT_IS_TPL(TEMPLATE_PARAMS_SEQ) \
BOOST_PP_SEQ_HEAD(TEMPLATE_PARAMS_SEQ)
diff --git a/boost/fusion/adapted/struct/detail/define_struct.hpp b/boost/fusion/adapted/struct/detail/define_struct.hpp
index ce3737ea97..ab483f0252 100644
--- a/boost/fusion/adapted/struct/detail/define_struct.hpp
+++ b/boost/fusion/adapted/struct/detail/define_struct.hpp
@@ -16,13 +16,11 @@
#include <boost/fusion/iterator/advance.hpp>
#include <boost/fusion/adapted/struct/detail/adapt_base.hpp>
#include <boost/fusion/adapted/struct/detail/namespace.hpp>
-#include <boost/preprocessor/inc.hpp>
#include <boost/preprocessor/if.hpp>
#include <boost/preprocessor/expr_if.hpp>
#include <boost/preprocessor/dec.hpp>
#include <boost/preprocessor/logical/not.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
-#include <boost/preprocessor/comparison/equal.hpp>
#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/for_each_i.hpp>
@@ -42,14 +40,14 @@
#define BOOST_FUSION_DEFINE_STRUCT_FILLER_1_END
#define BOOST_FUSION_DEFINE_STRUCT_COPY_CTOR_FILLER_I( \
- R, ATTRIBUTE_TUPEL_SIZE, I, ATTRIBUTE) \
+ R, ATTRIBUTE_TUPLE_SIZE, I, ATTRIBUTE) \
\
BOOST_PP_COMMA_IF(I) \
- BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE,1,ATTRIBUTE)( \
- other_self.BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE,1,ATTRIBUTE))
+ BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,1,ATTRIBUTE)( \
+ other_self.BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,1,ATTRIBUTE))
#define BOOST_FUSION_DEFINE_STRUCT_ASSIGN_FILLER_I( \
- R, ATTRIBUTE_TUPEL_SIZE, I_, ATTRIBUTE) \
+ R, ATTRIBUTE_TUPLE_SIZE, I_, ATTRIBUTE) \
\
BOOST_PP_EXPR_IF( \
I_, \
@@ -62,11 +60,11 @@
boost::fusion::next(BOOST_PP_CAT(i,BOOST_PP_DEC(I_))); \
) \
\
- BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE,1,ATTRIBUTE)= \
+ BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,1,ATTRIBUTE)= \
boost::fusion::deref(BOOST_PP_CAT(i,I_));
#define BOOST_FUSION_DEFINE_STRUCT_ASSIGN_OP( \
- ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE) \
+ ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
\
template<typename Seq> \
BOOST_FUSION_GPU_ENABLED \
@@ -81,51 +79,51 @@
BOOST_PP_SEQ_FOR_EACH_I_R( \
1, \
BOOST_FUSION_DEFINE_STRUCT_ASSIGN_FILLER_I, \
- ATTRIBUTE_TUPEL_SIZE, \
+ ATTRIBUTE_TUPLE_SIZE, \
ATTRIBUTES_SEQ) \
\
return *this; \
}
-#define BOOST_FUSION_DEFINE_STRUCT_ATTR_I(R, ATTRIBUTE_TUPEL_SIZE, ATTRIBUTE) \
+#define BOOST_FUSION_DEFINE_STRUCT_ATTR_I(R, ATTRIBUTE_TUPLE_SIZE, ATTRIBUTE) \
\
- BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE,0,ATTRIBUTE) \
- BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE,1,ATTRIBUTE);
+ BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,0,ATTRIBUTE) \
+ BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,1,ATTRIBUTE);
#define BOOST_FUSION_DEFINE_STRUCT_SEQ_CTOR_FILLER_I( \
- R, ATTRIBUTE_TUPEL_SIZE, I, ATTRIBUTE) \
+ R, ATTRIBUTE_TUPLE_SIZE, I, ATTRIBUTE) \
\
BOOST_PP_COMMA_IF(I) \
- BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE,1,ATTRIBUTE)( \
+ BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,1,ATTRIBUTE)( \
boost::fusion::deref(boost::fusion::advance_c<I>(boost::fusion::begin( \
seq))))
#define BOOST_FUSION_DEFINE_STRUCT_SEQ_CTOR_DISABLER( \
- ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE) \
+ ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
\
, typename boost::disable_if< \
boost::is_convertible< \
Seq const& \
, BOOST_PP_TUPLE_ELEM( \
- ATTRIBUTE_TUPEL_SIZE, \
+ ATTRIBUTE_TUPLE_SIZE, \
0, \
BOOST_PP_SEQ_HEAD(ATTRIBUTES_SEQ)) \
> \
>::type* =0
#define BOOST_FUSION_DEFINE_STRUCT_SEQ_DEFAULT_CTOR_FILLER_I( \
- R, ATTRIBUTE_TUPEL_SIZE, I, ATTRIBUTE) \
+ R, ATTRIBUTE_TUPLE_SIZE, I, ATTRIBUTE) \
\
BOOST_PP_COMMA_IF(I) \
- BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE,1,ATTRIBUTE)()
+ BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,1,ATTRIBUTE)()
#define BOOST_FUSION_DEFINE_STRUCT_IMPL_IMPL( \
- NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE) \
+ NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
\
BOOST_PP_SEQ_FOR_EACH_R( \
1, \
BOOST_FUSION_DEFINE_STRUCT_ATTR_I, \
- ATTRIBUTE_TUPEL_SIZE, \
+ ATTRIBUTE_TUPLE_SIZE, \
ATTRIBUTES_SEQ) \
\
BOOST_FUSION_GPU_ENABLED \
@@ -133,7 +131,7 @@
: BOOST_PP_SEQ_FOR_EACH_I_R( \
1, \
BOOST_FUSION_DEFINE_STRUCT_SEQ_DEFAULT_CTOR_FILLER_I, \
- ATTRIBUTE_TUPEL_SIZE, \
+ ATTRIBUTE_TUPLE_SIZE, \
ATTRIBUTES_SEQ) \
{} \
\
@@ -142,7 +140,7 @@
: BOOST_PP_SEQ_FOR_EACH_I_R( \
1, \
BOOST_FUSION_DEFINE_STRUCT_COPY_CTOR_FILLER_I, \
- ATTRIBUTE_TUPEL_SIZE, \
+ ATTRIBUTE_TUPLE_SIZE, \
ATTRIBUTES_SEQ) \
{} \
\
@@ -153,53 +151,53 @@
BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(ATTRIBUTES_SEQ)), \
BOOST_PP_TUPLE_EAT(2), \
BOOST_FUSION_DEFINE_STRUCT_SEQ_CTOR_DISABLER)( \
- ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE) \
+ ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
) \
: BOOST_PP_SEQ_FOR_EACH_I_R( \
1, \
BOOST_FUSION_DEFINE_STRUCT_SEQ_CTOR_FILLER_I, \
- ATTRIBUTE_TUPEL_SIZE, \
+ ATTRIBUTE_TUPLE_SIZE, \
ATTRIBUTES_SEQ) \
{} \
\
- BOOST_FUSION_DEFINE_STRUCT_ASSIGN_OP(ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE)
+ BOOST_FUSION_DEFINE_STRUCT_ASSIGN_OP(ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE)
#define BOOST_FUSION_DEFINE_STRUCT_CTOR_1( \
- NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE) \
+ NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
\
BOOST_FUSION_GPU_ENABLED \
explicit \
NAME(boost::call_traits< \
BOOST_PP_TUPLE_ELEM( \
- ATTRIBUTE_TUPEL_SIZE,0,BOOST_PP_SEQ_HEAD(ATTRIBUTES_SEQ)) \
+ ATTRIBUTE_TUPLE_SIZE,0,BOOST_PP_SEQ_HEAD(ATTRIBUTES_SEQ)) \
>::param_type arg) \
: BOOST_PP_TUPLE_ELEM( \
- ATTRIBUTE_TUPEL_SIZE,1,BOOST_PP_SEQ_HEAD(ATTRIBUTES_SEQ))(arg) \
+ ATTRIBUTE_TUPLE_SIZE,1,BOOST_PP_SEQ_HEAD(ATTRIBUTES_SEQ))(arg) \
{}
#define BOOST_FUSION_DEFINE_TPL_STRUCT_CTOR_1( \
- TEMPLATE_PARAMS_SEQ, NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE) \
+ TEMPLATE_PARAMS_SEQ, NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
\
BOOST_FUSION_GPU_ENABLED \
explicit \
NAME(typename boost::call_traits< \
typename boost::fusion::detail::get_first_arg< \
BOOST_PP_TUPLE_ELEM( \
- ATTRIBUTE_TUPEL_SIZE, \
+ ATTRIBUTE_TUPLE_SIZE, \
0, \
BOOST_PP_SEQ_HEAD(ATTRIBUTES_SEQ)) \
, BOOST_PP_SEQ_HEAD(TEMPLATE_PARAMS_SEQ) \
>::type \
>::param_type arg) \
: BOOST_PP_TUPLE_ELEM( \
- ATTRIBUTE_TUPEL_SIZE,1,BOOST_PP_SEQ_HEAD(ATTRIBUTES_SEQ))(arg) \
+ ATTRIBUTE_TUPLE_SIZE,1,BOOST_PP_SEQ_HEAD(ATTRIBUTES_SEQ))(arg) \
{}
#define BOOST_FUSION_DEFINE_STRUCT_CTOR_FILLER_I( \
- R, ATTRIBUTE_TUPEL_SIZE, I, ATTRIBUTE) \
+ R, ATTRIBUTE_TUPLE_SIZE, I, ATTRIBUTE) \
\
BOOST_PP_COMMA_IF(I) \
- BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE,1,ATTRIBUTE)(BOOST_PP_CAT(_,I))
+ BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,1,ATTRIBUTE)(BOOST_PP_CAT(_,I))
#define BOOST_FUSION_DEFINE_TPL_STRUCT_CTOR_ARG_I(R, DATA, I, ATTRIBUTE) \
\
@@ -215,14 +213,14 @@
>::param_type BOOST_PP_CAT(_,I)
#define BOOST_FUSION_DEFINE_TPL_STRUCT_CTOR_N( \
- TEMPLATE_PARAMS_SEQ, NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE) \
+ TEMPLATE_PARAMS_SEQ, NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
\
BOOST_FUSION_GPU_ENABLED \
NAME(BOOST_PP_SEQ_FOR_EACH_I_R( \
1, \
BOOST_FUSION_DEFINE_TPL_STRUCT_CTOR_ARG_I, \
( \
- ATTRIBUTE_TUPEL_SIZE, \
+ ATTRIBUTE_TUPLE_SIZE, \
BOOST_PP_SEQ_SIZE(ATTRIBUTES_SEQ), \
BOOST_PP_SEQ_HEAD(TEMPLATE_PARAMS_SEQ) \
), \
@@ -230,61 +228,61 @@
: BOOST_PP_SEQ_FOR_EACH_I_R( \
1, \
BOOST_FUSION_DEFINE_STRUCT_CTOR_FILLER_I, \
- ATTRIBUTE_TUPEL_SIZE, \
+ ATTRIBUTE_TUPLE_SIZE, \
ATTRIBUTES_SEQ) \
{}
#define BOOST_FUSION_DEFINE_STRUCT_CTOR_ARG_I( \
- R, ATTRIBUTE_TUPEL_SIZE, I, ATTRIBUTE) \
+ R, ATTRIBUTE_TUPLE_SIZE, I, ATTRIBUTE) \
\
BOOST_PP_COMMA_IF(I) \
boost::call_traits< \
- BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE,0,ATTRIBUTE) \
+ BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,0,ATTRIBUTE) \
>::param_type BOOST_PP_CAT(_,I)
#define BOOST_FUSION_DEFINE_STRUCT_CTOR_N( \
- NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE) \
+ NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
\
BOOST_FUSION_GPU_ENABLED \
NAME(BOOST_PP_SEQ_FOR_EACH_I_R( \
1, \
BOOST_FUSION_DEFINE_STRUCT_CTOR_ARG_I, \
- ATTRIBUTE_TUPEL_SIZE, \
+ ATTRIBUTE_TUPLE_SIZE, \
ATTRIBUTES_SEQ)) \
: BOOST_PP_SEQ_FOR_EACH_I_R( \
1, \
BOOST_FUSION_DEFINE_STRUCT_CTOR_FILLER_I, \
- ATTRIBUTE_TUPEL_SIZE, \
+ ATTRIBUTE_TUPLE_SIZE, \
ATTRIBUTES_SEQ) \
{}
#define BOOST_FUSION_DEFINE_STRUCT_CTOR( \
- NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE) \
+ NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
\
BOOST_PP_IF(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(ATTRIBUTES_SEQ)), \
BOOST_FUSION_DEFINE_STRUCT_CTOR_N, \
BOOST_FUSION_DEFINE_STRUCT_CTOR_1)( \
- NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE)
+ NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE)
#define BOOST_FUSION_DEFINE_TPL_STRUCT_CTOR( \
- TEMPLATE_PARAMS_SEQ, NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE) \
+ TEMPLATE_PARAMS_SEQ, NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
\
BOOST_PP_IF(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(ATTRIBUTES_SEQ)), \
BOOST_FUSION_DEFINE_TPL_STRUCT_CTOR_N, \
BOOST_FUSION_DEFINE_TPL_STRUCT_CTOR_1)( \
- TEMPLATE_PARAMS_SEQ, NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE)
+ TEMPLATE_PARAMS_SEQ, NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE)
#define BOOST_FUSION_DEFINE_NONEMPTY_STRUCT_IMPL( \
- NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE) \
+ NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
\
BOOST_FUSION_DEFINE_STRUCT_IMPL_IMPL( \
- NAME, BOOST_PP_SEQ_TAIL(ATTRIBUTES_SEQ), ATTRIBUTE_TUPEL_SIZE) \
+ NAME, BOOST_PP_SEQ_TAIL(ATTRIBUTES_SEQ), ATTRIBUTE_TUPLE_SIZE) \
\
BOOST_FUSION_DEFINE_STRUCT_CTOR( \
- NAME, BOOST_PP_SEQ_TAIL(ATTRIBUTES_SEQ), ATTRIBUTE_TUPEL_SIZE)
+ NAME, BOOST_PP_SEQ_TAIL(ATTRIBUTES_SEQ), ATTRIBUTE_TUPLE_SIZE)
#define BOOST_FUSION_DEFINE_EMPTY_STRUCT_IMPL( \
- NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE) \
+ NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
\
template<typename Seq> \
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED \
@@ -300,7 +298,7 @@
}
#define BOOST_FUSION_DEFINE_STRUCT_IMPL( \
- NAMESPACE_SEQ, NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE) \
+ NAMESPACE_SEQ, NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
\
BOOST_FUSION_ADAPT_STRUCT_NAMESPACE_DEFINITION_BEGIN(NAMESPACE_SEQ) \
\
@@ -311,35 +309,35 @@
BOOST_PP_IF(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(ATTRIBUTES_SEQ)), \
BOOST_FUSION_DEFINE_NONEMPTY_STRUCT_IMPL, \
BOOST_FUSION_DEFINE_EMPTY_STRUCT_IMPL)( \
- NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE) \
+ NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
}; \
\
BOOST_FUSION_ADAPT_STRUCT_NAMESPACE_DEFINITION_END(NAMESPACE_SEQ)
#define BOOST_FUSION_DEFINE_NONEMPTY_TPL_STRUCT_IMPL( \
- TEMPLATE_PARAMS_SEQ, NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE) \
+ TEMPLATE_PARAMS_SEQ, NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
\
BOOST_FUSION_DEFINE_STRUCT_IMPL_IMPL( \
- NAME, BOOST_PP_SEQ_TAIL(ATTRIBUTES_SEQ), ATTRIBUTE_TUPEL_SIZE) \
+ NAME, BOOST_PP_SEQ_TAIL(ATTRIBUTES_SEQ), ATTRIBUTE_TUPLE_SIZE) \
\
BOOST_FUSION_DEFINE_TPL_STRUCT_CTOR( \
TEMPLATE_PARAMS_SEQ, \
NAME, \
BOOST_PP_SEQ_TAIL(ATTRIBUTES_SEQ), \
- ATTRIBUTE_TUPEL_SIZE)
+ ATTRIBUTE_TUPLE_SIZE)
#define BOOST_FUSION_DEFINE_EMPTY_TPL_STRUCT_IMPL( \
- TEMPLATE_PARAMS_SEQ, NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE) \
+ TEMPLATE_PARAMS_SEQ, NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \
\
BOOST_FUSION_DEFINE_EMPTY_STRUCT_IMPL( \
- NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE)
+ NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE)
#define BOOST_FUSION_DEFINE_TPL_STRUCT_IMPL( \
TEMPLATE_PARAMS_SEQ, \
NAMESPACE_SEQ, \
NAME, \
ATTRIBUTES_SEQ, \
- ATTRIBUTE_TUPEL_SIZE) \
+ ATTRIBUTE_TUPLE_SIZE) \
\
BOOST_FUSION_ADAPT_STRUCT_NAMESPACE_DEFINITION_BEGIN(NAMESPACE_SEQ) \
\
@@ -354,7 +352,7 @@
BOOST_PP_IF(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(ATTRIBUTES_SEQ)), \
BOOST_FUSION_DEFINE_NONEMPTY_TPL_STRUCT_IMPL, \
BOOST_FUSION_DEFINE_EMPTY_TPL_STRUCT_IMPL)( \
- TEMPLATE_PARAMS_SEQ, NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPEL_SIZE)\
+ TEMPLATE_PARAMS_SEQ, NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE)\
}; \
\
BOOST_FUSION_ADAPT_STRUCT_NAMESPACE_DEFINITION_END(NAMESPACE_SEQ)
diff --git a/boost/fusion/adapted/struct/detail/define_struct_inline.hpp b/boost/fusion/adapted/struct/detail/define_struct_inline.hpp
index a037ffe549..1db1a2efe4 100644
--- a/boost/fusion/adapted/struct/detail/define_struct_inline.hpp
+++ b/boost/fusion/adapted/struct/detail/define_struct_inline.hpp
@@ -22,7 +22,7 @@
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/preprocessor/comma_if.hpp>
-#include <boost/preprocessor/facilities/is_empty.hpp>
+#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/seq/size.hpp>
@@ -62,7 +62,6 @@
~, \
ATTRIBUTES_SEQ) \
-#define BOOST_FUSION_IGNORE_1(ARG1)
#define BOOST_FUSION_IGNORE_2(ARG1, ARG2)
#define BOOST_FUSION_MAKE_COPY_CONSTRUCTOR(NAME, ATTRIBUTES_SEQ) \
@@ -425,17 +424,10 @@
#define BOOST_FUSION_DEFINE_STRUCT_INLINE_MEMBERS_IMPL_IMPL( \
NAME, ATTRIBUTES_SEQ, ATTRIBUTES_SEQ_SIZE) \
\
- /* Note: second BOOST_PP_IF is necessary to avoid MSVC warning when */ \
- /* calling BOOST_FUSION_IGNORE_1 with no arguments. */ \
NAME() \
- BOOST_PP_IF( \
- ATTRIBUTES_SEQ_SIZE, \
+ BOOST_PP_IF(ATTRIBUTES_SEQ_SIZE, \
BOOST_FUSION_MAKE_DEFAULT_INIT_LIST, \
- BOOST_FUSION_IGNORE_1) \
- (BOOST_PP_IF( \
- ATTRIBUTES_SEQ_SIZE, \
- ATTRIBUTES_SEQ, \
- 0)) \
+ BOOST_PP_EMPTY)(ATTRIBUTES_SEQ) \
{ \
} \
\
diff --git a/boost/fusion/adapted/struct/detail/preprocessor/is_seq.hpp b/boost/fusion/adapted/struct/detail/preprocessor/is_seq.hpp
index 95f110509b..00371ca5b8 100644
--- a/boost/fusion/adapted/struct/detail/preprocessor/is_seq.hpp
+++ b/boost/fusion/adapted/struct/detail/preprocessor/is_seq.hpp
@@ -13,8 +13,6 @@
#ifndef BOOST_FUSION_ADAPTED_STRUCT_DETAIL_PREPROCESSOR_IS_SEQ_HPP
#define BOOST_FUSION_ADAPTED_STRUCT_DETAIL_PREPROCESSOR_IS_SEQ_HPP
-#include <boost/preprocessor/seq/size.hpp>
-#include <boost/preprocessor/arithmetic/dec.hpp>
#include <boost/preprocessor/punctuation/paren.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/config/config.hpp>
diff --git a/boost/fusion/algorithm/transformation/zip.hpp b/boost/fusion/algorithm/transformation/zip.hpp
index e94efc8183..0775a42944 100644
--- a/boost/fusion/algorithm/transformation/zip.hpp
+++ b/boost/fusion/algorithm/transformation/zip.hpp
@@ -17,6 +17,7 @@
#include <boost/type_traits/add_reference.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/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
diff --git a/boost/fusion/container/deque/deque.hpp b/boost/fusion/container/deque/deque.hpp
index dee51befcd..a282a70129 100644
--- a/boost/fusion/container/deque/deque.hpp
+++ b/boost/fusion/container/deque/deque.hpp
@@ -21,6 +21,8 @@
// C++11 interface
///////////////////////////////////////////////////////////////////////////////
#include <boost/fusion/support/sequence_base.hpp>
+#include <boost/fusion/support/void.hpp>
+#include <boost/fusion/support/detail/enabler.hpp>
#include <boost/fusion/support/detail/access.hpp>
#include <boost/fusion/support/is_sequence.hpp>
#include <boost/fusion/container/deque/detail/keyed_element.hpp>
@@ -59,7 +61,7 @@ namespace boost { namespace fusion
typename enable_if<
mpl::and_<
traits::is_sequence<Sequence>
- , result_of::empty<Sequence>>>::type* /*dummy*/ = 0) BOOST_NOEXCEPT
+ , result_of::empty<Sequence>>, detail::enabler_>::type = detail::enabler) BOOST_NOEXCEPT
{}
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
@@ -149,8 +151,8 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
explicit deque(Sequence const& seq
- , typename disable_if<is_convertible<Sequence, Head> >::type* /*dummy*/ = 0
- , typename enable_if<traits::is_sequence<Sequence> >::type* /*dummy*/ = 0)
+ , typename disable_if<is_convertible<Sequence, Head>, detail::enabler_>::type = detail::enabler
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: base(base::from_iterator(fusion::begin(seq)))
{}
diff --git a/boost/fusion/container/deque/detail/cpp03/deque.hpp b/boost/fusion/container/deque/detail/cpp03/deque.hpp
index a65fa4acbd..8cffe6b960 100644
--- a/boost/fusion/container/deque/detail/cpp03/deque.hpp
+++ b/boost/fusion/container/deque/detail/cpp03/deque.hpp
@@ -35,6 +35,7 @@
#include <boost/mpl/bool.hpp>
#include <boost/fusion/support/void.hpp>
+#include <boost/fusion/support/detail/enabler.hpp>
#include <boost/utility/enable_if.hpp>
#if !defined(BOOST_FUSION_DONT_USE_PREPROCESSED_FILES)
@@ -102,8 +103,8 @@ namespace boost { namespace fusion {
template<typename Sequence>
BOOST_FUSION_GPU_ENABLED
deque(Sequence const& seq
- , typename disable_if<is_convertible<Sequence, T0> >::type* /*dummy*/ = 0
- , typename enable_if<traits::is_sequence<Sequence> >::type* /*dummy*/ = 0)
+ , typename disable_if<is_convertible<Sequence, T0>, detail::enabler_>::type = detail::enabler
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: base(base::from_iterator(fusion::begin(seq)))
{}
@@ -133,7 +134,7 @@ FUSION_HASH if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename T0_>
BOOST_FUSION_GPU_ENABLED
explicit deque(T0_&& t0
- , typename enable_if<is_convertible<T0_, T0> >::type* /*dummy*/ = 0
+ , typename enable_if<is_convertible<T0_, T0>, detail::enabler_>::type = detail::enabler
)
: base(BOOST_FUSION_FWD_ELEM(T0_, t0), detail::nil_keyed_element())
{}
@@ -146,7 +147,8 @@ FUSION_HASH if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
deque(deque<BOOST_PP_ENUM_PARAMS(FUSION_MAX_DEQUE_SIZE, U)>&& seq
, typename disable_if<
is_convertible<deque<BOOST_PP_ENUM_PARAMS(FUSION_MAX_DEQUE_SIZE, U)>, T0>
- >::type* /*dummy*/ = 0)
+ , detail::enabler_
+ >::type = detail::enabler)
: base(std::forward<deque<BOOST_PP_ENUM_PARAMS(FUSION_MAX_DEQUE_SIZE, U)>>(seq))
{}
template <typename T>
@@ -180,7 +182,7 @@ FUSION_HASH endif
typename enable_if<
mpl::and_<
traits::is_sequence<Sequence>
- , result_of::empty<Sequence> > >::type* /*dummy*/ = 0) BOOST_NOEXCEPT
+ , result_of::empty<Sequence> >, detail::enabler_>::type = detail::enabler) BOOST_NOEXCEPT
{}
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
diff --git a/boost/fusion/container/deque/detail/cpp03/preprocessed/deque10.hpp b/boost/fusion/container/deque/detail/cpp03/preprocessed/deque10.hpp
index 95cd8c1cba..8267496c6d 100644
--- a/boost/fusion/container/deque/detail/cpp03/preprocessed/deque10.hpp
+++ b/boost/fusion/container/deque/detail/cpp03/preprocessed/deque10.hpp
@@ -202,8 +202,8 @@ deque(T_0 && t0 , T_1 && t1 , T_2 && t2 , T_3 && t3 , T_4 && t4 , T_5 && t5 , T_
template<typename Sequence>
BOOST_FUSION_GPU_ENABLED
deque(Sequence const& seq
- , typename disable_if<is_convertible<Sequence, T0> >::type* = 0
- , typename enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ , typename disable_if<is_convertible<Sequence, T0>, detail::enabler_>::type = detail::enabler
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: base(base::from_iterator(fusion::begin(seq)))
{}
template <typename U0 , typename U1 , typename U2 , typename U3 , typename U4 , typename U5 , typename U6 , typename U7 , typename U8 , typename U9>
@@ -226,7 +226,7 @@ deque(T_0 && t0 , T_1 && t1 , T_2 && t2 , T_3 && t3 , T_4 && t4 , T_5 && t5 , T_
template <typename T0_>
BOOST_FUSION_GPU_ENABLED
explicit deque(T0_&& t0
- , typename enable_if<is_convertible<T0_, T0> >::type* = 0
+ , typename enable_if<is_convertible<T0_, T0>, detail::enabler_>::type = detail::enabler
)
: base(std::forward<T0_>( t0), detail::nil_keyed_element())
{}
@@ -239,7 +239,8 @@ deque(T_0 && t0 , T_1 && t1 , T_2 && t2 , T_3 && t3 , T_4 && t4 , T_5 && t5 , T_
deque(deque<U0 , U1 , U2 , U3 , U4 , U5 , U6 , U7 , U8 , U9>&& seq
, typename disable_if<
is_convertible<deque<U0 , U1 , U2 , U3 , U4 , U5 , U6 , U7 , U8 , U9>, T0>
- >::type* = 0)
+ , detail::enabler_
+ >::type = detail::enabler)
: base(std::forward<deque<U0 , U1 , U2 , U3 , U4 , U5 , U6 , U7 , U8 , U9>>(seq))
{}
template <typename T>
@@ -267,7 +268,7 @@ deque(T_0 && t0 , T_1 && t1 , T_2 && t2 , T_3 && t3 , T_4 && t4 , T_5 && t5 , T_
typename enable_if<
mpl::and_<
traits::is_sequence<Sequence>
- , result_of::empty<Sequence> > >::type* = 0) BOOST_NOEXCEPT
+ , result_of::empty<Sequence> >, detail::enabler_>::type = detail::enabler) BOOST_NOEXCEPT
{}
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
deque() BOOST_NOEXCEPT {}
diff --git a/boost/fusion/container/deque/detail/cpp03/preprocessed/deque20.hpp b/boost/fusion/container/deque/detail/cpp03/preprocessed/deque20.hpp
index ad06945135..a3adee14d1 100644
--- a/boost/fusion/container/deque/detail/cpp03/preprocessed/deque20.hpp
+++ b/boost/fusion/container/deque/detail/cpp03/preprocessed/deque20.hpp
@@ -382,8 +382,8 @@ deque(T_0 && t0 , T_1 && t1 , T_2 && t2 , T_3 && t3 , T_4 && t4 , T_5 && t5 , T_
template<typename Sequence>
BOOST_FUSION_GPU_ENABLED
deque(Sequence const& seq
- , typename disable_if<is_convertible<Sequence, T0> >::type* = 0
- , typename enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ , typename disable_if<is_convertible<Sequence, T0>, detail::enabler_>::type = detail::enabler
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: base(base::from_iterator(fusion::begin(seq)))
{}
template <typename U0 , typename U1 , typename U2 , typename U3 , typename U4 , typename U5 , typename U6 , typename U7 , typename U8 , typename U9 , typename U10 , typename U11 , typename U12 , typename U13 , typename U14 , typename U15 , typename U16 , typename U17 , typename U18 , typename U19>
@@ -406,7 +406,7 @@ deque(T_0 && t0 , T_1 && t1 , T_2 && t2 , T_3 && t3 , T_4 && t4 , T_5 && t5 , T_
template <typename T0_>
BOOST_FUSION_GPU_ENABLED
explicit deque(T0_&& t0
- , typename enable_if<is_convertible<T0_, T0> >::type* = 0
+ , typename enable_if<is_convertible<T0_, T0>, detail::enabler_>::type = detail::enabler
)
: base(std::forward<T0_>( t0), detail::nil_keyed_element())
{}
@@ -419,7 +419,8 @@ deque(T_0 && t0 , T_1 && t1 , T_2 && t2 , T_3 && t3 , T_4 && t4 , T_5 && t5 , T_
deque(deque<U0 , U1 , U2 , U3 , U4 , U5 , U6 , U7 , U8 , U9 , U10 , U11 , U12 , U13 , U14 , U15 , U16 , U17 , U18 , U19>&& seq
, typename disable_if<
is_convertible<deque<U0 , U1 , U2 , U3 , U4 , U5 , U6 , U7 , U8 , U9 , U10 , U11 , U12 , U13 , U14 , U15 , U16 , U17 , U18 , U19>, T0>
- >::type* = 0)
+ , detail::enabler_
+ >::type = detail::enabler)
: base(std::forward<deque<U0 , U1 , U2 , U3 , U4 , U5 , U6 , U7 , U8 , U9 , U10 , U11 , U12 , U13 , U14 , U15 , U16 , U17 , U18 , U19>>(seq))
{}
template <typename T>
@@ -447,7 +448,7 @@ deque(T_0 && t0 , T_1 && t1 , T_2 && t2 , T_3 && t3 , T_4 && t4 , T_5 && t5 , T_
typename enable_if<
mpl::and_<
traits::is_sequence<Sequence>
- , result_of::empty<Sequence> > >::type* = 0) BOOST_NOEXCEPT
+ , result_of::empty<Sequence> >, detail::enabler_>::type = detail::enabler) BOOST_NOEXCEPT
{}
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
deque() BOOST_NOEXCEPT {}
diff --git a/boost/fusion/container/deque/detail/cpp03/preprocessed/deque30.hpp b/boost/fusion/container/deque/detail/cpp03/preprocessed/deque30.hpp
index 44a5b2b103..4c56d9ffc8 100644
--- a/boost/fusion/container/deque/detail/cpp03/preprocessed/deque30.hpp
+++ b/boost/fusion/container/deque/detail/cpp03/preprocessed/deque30.hpp
@@ -562,8 +562,8 @@ deque(T_0 && t0 , T_1 && t1 , T_2 && t2 , T_3 && t3 , T_4 && t4 , T_5 && t5 , T_
template<typename Sequence>
BOOST_FUSION_GPU_ENABLED
deque(Sequence const& seq
- , typename disable_if<is_convertible<Sequence, T0> >::type* = 0
- , typename enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ , typename disable_if<is_convertible<Sequence, T0>, detail::enabler_>::type = detail::enabler
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: base(base::from_iterator(fusion::begin(seq)))
{}
template <typename U0 , typename U1 , typename U2 , typename U3 , typename U4 , typename U5 , typename U6 , typename U7 , typename U8 , typename U9 , typename U10 , typename U11 , typename U12 , typename U13 , typename U14 , typename U15 , typename U16 , typename U17 , typename U18 , typename U19 , typename U20 , typename U21 , typename U22 , typename U23 , typename U24 , typename U25 , typename U26 , typename U27 , typename U28 , typename U29>
@@ -586,7 +586,7 @@ deque(T_0 && t0 , T_1 && t1 , T_2 && t2 , T_3 && t3 , T_4 && t4 , T_5 && t5 , T_
template <typename T0_>
BOOST_FUSION_GPU_ENABLED
explicit deque(T0_&& t0
- , typename enable_if<is_convertible<T0_, T0> >::type* = 0
+ , typename enable_if<is_convertible<T0_, T0>, detail::enabler_>::type = detail::enabler
)
: base(std::forward<T0_>( t0), detail::nil_keyed_element())
{}
@@ -599,7 +599,8 @@ deque(T_0 && t0 , T_1 && t1 , T_2 && t2 , T_3 && t3 , T_4 && t4 , T_5 && t5 , T_
deque(deque<U0 , U1 , U2 , U3 , U4 , U5 , U6 , U7 , U8 , U9 , U10 , U11 , U12 , U13 , U14 , U15 , U16 , U17 , U18 , U19 , U20 , U21 , U22 , U23 , U24 , U25 , U26 , U27 , U28 , U29>&& seq
, typename disable_if<
is_convertible<deque<U0 , U1 , U2 , U3 , U4 , U5 , U6 , U7 , U8 , U9 , U10 , U11 , U12 , U13 , U14 , U15 , U16 , U17 , U18 , U19 , U20 , U21 , U22 , U23 , U24 , U25 , U26 , U27 , U28 , U29>, T0>
- >::type* = 0)
+ , detail::enabler_
+ >::type = detail::enabler)
: base(std::forward<deque<U0 , U1 , U2 , U3 , U4 , U5 , U6 , U7 , U8 , U9 , U10 , U11 , U12 , U13 , U14 , U15 , U16 , U17 , U18 , U19 , U20 , U21 , U22 , U23 , U24 , U25 , U26 , U27 , U28 , U29>>(seq))
{}
template <typename T>
@@ -627,7 +628,7 @@ deque(T_0 && t0 , T_1 && t1 , T_2 && t2 , T_3 && t3 , T_4 && t4 , T_5 && t5 , T_
typename enable_if<
mpl::and_<
traits::is_sequence<Sequence>
- , result_of::empty<Sequence> > >::type* = 0) BOOST_NOEXCEPT
+ , result_of::empty<Sequence> >, detail::enabler_>::type = detail::enabler) BOOST_NOEXCEPT
{}
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
deque() BOOST_NOEXCEPT {}
diff --git a/boost/fusion/container/deque/detail/cpp03/preprocessed/deque40.hpp b/boost/fusion/container/deque/detail/cpp03/preprocessed/deque40.hpp
index e642288eb7..bb827e935e 100644
--- a/boost/fusion/container/deque/detail/cpp03/preprocessed/deque40.hpp
+++ b/boost/fusion/container/deque/detail/cpp03/preprocessed/deque40.hpp
@@ -742,8 +742,8 @@ deque(T_0 && t0 , T_1 && t1 , T_2 && t2 , T_3 && t3 , T_4 && t4 , T_5 && t5 , T_
template<typename Sequence>
BOOST_FUSION_GPU_ENABLED
deque(Sequence const& seq
- , typename disable_if<is_convertible<Sequence, T0> >::type* = 0
- , typename enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ , typename disable_if<is_convertible<Sequence, T0>, detail::enabler_>::type = detail::enabler
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: base(base::from_iterator(fusion::begin(seq)))
{}
template <typename U0 , typename U1 , typename U2 , typename U3 , typename U4 , typename U5 , typename U6 , typename U7 , typename U8 , typename U9 , typename U10 , typename U11 , typename U12 , typename U13 , typename U14 , typename U15 , typename U16 , typename U17 , typename U18 , typename U19 , typename U20 , typename U21 , typename U22 , typename U23 , typename U24 , typename U25 , typename U26 , typename U27 , typename U28 , typename U29 , typename U30 , typename U31 , typename U32 , typename U33 , typename U34 , typename U35 , typename U36 , typename U37 , typename U38 , typename U39>
@@ -766,7 +766,7 @@ deque(T_0 && t0 , T_1 && t1 , T_2 && t2 , T_3 && t3 , T_4 && t4 , T_5 && t5 , T_
template <typename T0_>
BOOST_FUSION_GPU_ENABLED
explicit deque(T0_&& t0
- , typename enable_if<is_convertible<T0_, T0> >::type* = 0
+ , typename enable_if<is_convertible<T0_, T0>, detail::enabler_>::type = detail::enabler
)
: base(std::forward<T0_>( t0), detail::nil_keyed_element())
{}
@@ -779,7 +779,8 @@ deque(T_0 && t0 , T_1 && t1 , T_2 && t2 , T_3 && t3 , T_4 && t4 , T_5 && t5 , T_
deque(deque<U0 , U1 , U2 , U3 , U4 , U5 , U6 , U7 , U8 , U9 , U10 , U11 , U12 , U13 , U14 , U15 , U16 , U17 , U18 , U19 , U20 , U21 , U22 , U23 , U24 , U25 , U26 , U27 , U28 , U29 , U30 , U31 , U32 , U33 , U34 , U35 , U36 , U37 , U38 , U39>&& seq
, typename disable_if<
is_convertible<deque<U0 , U1 , U2 , U3 , U4 , U5 , U6 , U7 , U8 , U9 , U10 , U11 , U12 , U13 , U14 , U15 , U16 , U17 , U18 , U19 , U20 , U21 , U22 , U23 , U24 , U25 , U26 , U27 , U28 , U29 , U30 , U31 , U32 , U33 , U34 , U35 , U36 , U37 , U38 , U39>, T0>
- >::type* = 0)
+ , detail::enabler_
+ >::type = detail::enabler)
: base(std::forward<deque<U0 , U1 , U2 , U3 , U4 , U5 , U6 , U7 , U8 , U9 , U10 , U11 , U12 , U13 , U14 , U15 , U16 , U17 , U18 , U19 , U20 , U21 , U22 , U23 , U24 , U25 , U26 , U27 , U28 , U29 , U30 , U31 , U32 , U33 , U34 , U35 , U36 , U37 , U38 , U39>>(seq))
{}
template <typename T>
@@ -807,7 +808,7 @@ deque(T_0 && t0 , T_1 && t1 , T_2 && t2 , T_3 && t3 , T_4 && t4 , T_5 && t5 , T_
typename enable_if<
mpl::and_<
traits::is_sequence<Sequence>
- , result_of::empty<Sequence> > >::type* = 0) BOOST_NOEXCEPT
+ , result_of::empty<Sequence> >, detail::enabler_>::type = detail::enabler) BOOST_NOEXCEPT
{}
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
deque() BOOST_NOEXCEPT {}
diff --git a/boost/fusion/container/deque/detail/cpp03/preprocessed/deque50.hpp b/boost/fusion/container/deque/detail/cpp03/preprocessed/deque50.hpp
index a387708bca..af40651fea 100644
--- a/boost/fusion/container/deque/detail/cpp03/preprocessed/deque50.hpp
+++ b/boost/fusion/container/deque/detail/cpp03/preprocessed/deque50.hpp
@@ -922,8 +922,8 @@ deque(T_0 && t0 , T_1 && t1 , T_2 && t2 , T_3 && t3 , T_4 && t4 , T_5 && t5 , T_
template<typename Sequence>
BOOST_FUSION_GPU_ENABLED
deque(Sequence const& seq
- , typename disable_if<is_convertible<Sequence, T0> >::type* = 0
- , typename enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ , typename disable_if<is_convertible<Sequence, T0>, detail::enabler_>::type = detail::enabler
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: base(base::from_iterator(fusion::begin(seq)))
{}
template <typename U0 , typename U1 , typename U2 , typename U3 , typename U4 , typename U5 , typename U6 , typename U7 , typename U8 , typename U9 , typename U10 , typename U11 , typename U12 , typename U13 , typename U14 , typename U15 , typename U16 , typename U17 , typename U18 , typename U19 , typename U20 , typename U21 , typename U22 , typename U23 , typename U24 , typename U25 , typename U26 , typename U27 , typename U28 , typename U29 , typename U30 , typename U31 , typename U32 , typename U33 , typename U34 , typename U35 , typename U36 , typename U37 , typename U38 , typename U39 , typename U40 , typename U41 , typename U42 , typename U43 , typename U44 , typename U45 , typename U46 , typename U47 , typename U48 , typename U49>
@@ -946,7 +946,7 @@ deque(T_0 && t0 , T_1 && t1 , T_2 && t2 , T_3 && t3 , T_4 && t4 , T_5 && t5 , T_
template <typename T0_>
BOOST_FUSION_GPU_ENABLED
explicit deque(T0_&& t0
- , typename enable_if<is_convertible<T0_, T0> >::type* = 0
+ , typename enable_if<is_convertible<T0_, T0>, detail::enabler_>::type = detail::enabler
)
: base(std::forward<T0_>( t0), detail::nil_keyed_element())
{}
@@ -959,7 +959,8 @@ deque(T_0 && t0 , T_1 && t1 , T_2 && t2 , T_3 && t3 , T_4 && t4 , T_5 && t5 , T_
deque(deque<U0 , U1 , U2 , U3 , U4 , U5 , U6 , U7 , U8 , U9 , U10 , U11 , U12 , U13 , U14 , U15 , U16 , U17 , U18 , U19 , U20 , U21 , U22 , U23 , U24 , U25 , U26 , U27 , U28 , U29 , U30 , U31 , U32 , U33 , U34 , U35 , U36 , U37 , U38 , U39 , U40 , U41 , U42 , U43 , U44 , U45 , U46 , U47 , U48 , U49>&& seq
, typename disable_if<
is_convertible<deque<U0 , U1 , U2 , U3 , U4 , U5 , U6 , U7 , U8 , U9 , U10 , U11 , U12 , U13 , U14 , U15 , U16 , U17 , U18 , U19 , U20 , U21 , U22 , U23 , U24 , U25 , U26 , U27 , U28 , U29 , U30 , U31 , U32 , U33 , U34 , U35 , U36 , U37 , U38 , U39 , U40 , U41 , U42 , U43 , U44 , U45 , U46 , U47 , U48 , U49>, T0>
- >::type* = 0)
+ , detail::enabler_
+ >::type = detail::enabler)
: base(std::forward<deque<U0 , U1 , U2 , U3 , U4 , U5 , U6 , U7 , U8 , U9 , U10 , U11 , U12 , U13 , U14 , U15 , U16 , U17 , U18 , U19 , U20 , U21 , U22 , U23 , U24 , U25 , U26 , U27 , U28 , U29 , U30 , U31 , U32 , U33 , U34 , U35 , U36 , U37 , U38 , U39 , U40 , U41 , U42 , U43 , U44 , U45 , U46 , U47 , U48 , U49>>(seq))
{}
template <typename T>
@@ -987,7 +988,7 @@ deque(T_0 && t0 , T_1 && t1 , T_2 && t2 , T_3 && t3 , T_4 && t4 , T_5 && t5 , T_
typename enable_if<
mpl::and_<
traits::is_sequence<Sequence>
- , result_of::empty<Sequence> > >::type* = 0) BOOST_NOEXCEPT
+ , result_of::empty<Sequence> >, detail::enabler_>::type = detail::enabler) BOOST_NOEXCEPT
{}
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
deque() BOOST_NOEXCEPT {}
diff --git a/boost/fusion/container/generation/make_vector.hpp b/boost/fusion/container/generation/make_vector.hpp
index cd3b992bb5..4e4bcb2dec 100644
--- a/boost/fusion/container/generation/make_vector.hpp
+++ b/boost/fusion/container/generation/make_vector.hpp
@@ -30,33 +30,13 @@ namespace boost { namespace fusion
template <typename ...T>
struct make_vector
{
- // make `make_vector<T..., void_...>' into `make_vector<T...>'
- template <typename, typename...> struct trim_void;
-
- template <typename... U>
- struct trim_void<vector<U...> >
- {
- typedef vector<U...> type;
- };
-
- template <typename... U, typename... Tail>
- struct trim_void<vector<U...>, void_, Tail...>
- : trim_void<vector<U...> > { };
-
- template <typename... U, typename Head, typename... Tail>
- struct trim_void<vector<U...>, Head, Tail...>
- : trim_void<vector<U..., Head>, Tail...> { };
-
- typedef
- typename trim_void<
- vector<>
- , typename detail::as_fusion_element<
- typename remove_const<
- typename remove_reference<T>::type
- >::type
- >::type...
- >::type
- type;
+ typedef vector<
+ typename detail::as_fusion_element<
+ typename remove_const<
+ typename remove_reference<T>::type
+ >::type
+ >::type...
+ > type;
};
}
diff --git a/boost/fusion/container/list/cons.hpp b/boost/fusion/container/list/cons.hpp
index e05b62eb48..0dd91b0c32 100644
--- a/boost/fusion/container/list/cons.hpp
+++ b/boost/fusion/container/list/cons.hpp
@@ -9,6 +9,8 @@
#define FUSION_CONS_07172005_0843
#include <boost/fusion/support/config.hpp>
+#include <boost/fusion/support/void.hpp>
+#include <boost/fusion/support/detail/enabler.hpp>
#include <boost/fusion/container/list/cons_fwd.hpp>
#include <boost/fusion/support/detail/access.hpp>
#include <boost/fusion/sequence/intrinsic/begin.hpp>
@@ -34,7 +36,6 @@
namespace boost { namespace fusion
{
- struct void_;
struct cons_tag;
struct forward_traversal_tag;
struct fusion_sequence_tag;
@@ -82,7 +83,8 @@ namespace boost { namespace fusion
traits::is_sequence<Sequence>
, mpl::not_<is_base_of<cons, Sequence> >
, mpl::not_<is_convertible<Sequence, Car> > > // use copy to car instead
- >::type* /*dummy*/ = 0
+ , detail::enabler_
+ >::type = detail::enabler
)
: car(*fusion::begin(seq))
, cdr(fusion::next(fusion::begin(seq)), mpl::true_()) {}
diff --git a/boost/fusion/container/list/detail/cpp03/list.hpp b/boost/fusion/container/list/detail/cpp03/list.hpp
index b39489b0b7..048d59b6b7 100644
--- a/boost/fusion/container/list/detail/cpp03/list.hpp
+++ b/boost/fusion/container/list/detail/cpp03/list.hpp
@@ -8,6 +8,8 @@
#define FUSION_LIST_07172005_1153
#include <boost/fusion/support/config.hpp>
+#include <boost/fusion/support/void.hpp>
+#include <boost/fusion/support/detail/enabler.hpp>
#include <boost/fusion/container/list/detail/cpp03/list_fwd.hpp>
#include <boost/fusion/container/list/detail/cpp03/list_to_cons.hpp>
#include <boost/fusion/support/is_sequence.hpp>
@@ -61,7 +63,7 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_FUSION_GPU_ENABLED
list(Sequence const& rhs
- , typename boost::enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: inherited_type(rhs) {}
// Expand a couple of forwarding constructors for arguments
diff --git a/boost/fusion/container/list/detail/cpp03/preprocessed/list10.hpp b/boost/fusion/container/list/detail/cpp03/preprocessed/list10.hpp
index 47db8f588c..818dc52868 100644
--- a/boost/fusion/container/list/detail/cpp03/preprocessed/list10.hpp
+++ b/boost/fusion/container/list/detail/cpp03/preprocessed/list10.hpp
@@ -30,7 +30,7 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_FUSION_GPU_ENABLED
list(Sequence const& rhs
- , typename boost::enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: inherited_type(rhs) {}
diff --git a/boost/fusion/container/list/detail/cpp03/preprocessed/list20.hpp b/boost/fusion/container/list/detail/cpp03/preprocessed/list20.hpp
index 8eb7d2d2df..3c3c3f6c5f 100644
--- a/boost/fusion/container/list/detail/cpp03/preprocessed/list20.hpp
+++ b/boost/fusion/container/list/detail/cpp03/preprocessed/list20.hpp
@@ -30,7 +30,7 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_FUSION_GPU_ENABLED
list(Sequence const& rhs
- , typename boost::enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: inherited_type(rhs) {}
diff --git a/boost/fusion/container/list/detail/cpp03/preprocessed/list30.hpp b/boost/fusion/container/list/detail/cpp03/preprocessed/list30.hpp
index fb24e8d47b..143dce676f 100644
--- a/boost/fusion/container/list/detail/cpp03/preprocessed/list30.hpp
+++ b/boost/fusion/container/list/detail/cpp03/preprocessed/list30.hpp
@@ -30,7 +30,7 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_FUSION_GPU_ENABLED
list(Sequence const& rhs
- , typename boost::enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: inherited_type(rhs) {}
diff --git a/boost/fusion/container/list/detail/cpp03/preprocessed/list40.hpp b/boost/fusion/container/list/detail/cpp03/preprocessed/list40.hpp
index 49437dee5e..00e16041de 100644
--- a/boost/fusion/container/list/detail/cpp03/preprocessed/list40.hpp
+++ b/boost/fusion/container/list/detail/cpp03/preprocessed/list40.hpp
@@ -30,7 +30,7 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_FUSION_GPU_ENABLED
list(Sequence const& rhs
- , typename boost::enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: inherited_type(rhs) {}
diff --git a/boost/fusion/container/list/detail/cpp03/preprocessed/list50.hpp b/boost/fusion/container/list/detail/cpp03/preprocessed/list50.hpp
index 3ebbf19586..b948f40a67 100644
--- a/boost/fusion/container/list/detail/cpp03/preprocessed/list50.hpp
+++ b/boost/fusion/container/list/detail/cpp03/preprocessed/list50.hpp
@@ -30,7 +30,7 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_FUSION_GPU_ENABLED
list(Sequence const& rhs
- , typename boost::enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: inherited_type(rhs) {}
diff --git a/boost/fusion/container/map/map.hpp b/boost/fusion/container/map/map.hpp
index e90d28a939..ec9e58d32d 100644
--- a/boost/fusion/container/map/map.hpp
+++ b/boost/fusion/container/map/map.hpp
@@ -35,6 +35,8 @@
#include <boost/fusion/support/is_sequence.hpp>
#include <boost/fusion/support/sequence_base.hpp>
#include <boost/fusion/support/category_of.hpp>
+#include <boost/fusion/support/void.hpp>
+#include <boost/fusion/support/detail/enabler.hpp>
#include <boost/utility/enable_if.hpp>
@@ -68,21 +70,21 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_FUSION_GPU_ENABLED
map(Sequence const& seq
- , typename enable_if<traits::is_sequence<Sequence>>::type* /*dummy*/ = 0)
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: base_type(begin(seq), detail::map_impl_from_iterator())
{}
template <typename Sequence>
BOOST_FUSION_GPU_ENABLED
map(Sequence& seq
- , typename enable_if<traits::is_sequence<Sequence>>::type* /*dummy*/ = 0)
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: base_type(begin(seq), detail::map_impl_from_iterator())
{}
template <typename Sequence>
BOOST_FUSION_GPU_ENABLED
map(Sequence&& seq
- , typename enable_if<traits::is_sequence<Sequence>>::type* /*dummy*/ = 0)
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: base_type(begin(seq), detail::map_impl_from_iterator())
{}
diff --git a/boost/fusion/container/set/detail/cpp03/preprocessed/set10.hpp b/boost/fusion/container/set/detail/cpp03/preprocessed/set10.hpp
index d2eba4c8f5..74e847176e 100644
--- a/boost/fusion/container/set/detail/cpp03/preprocessed/set10.hpp
+++ b/boost/fusion/container/set/detail/cpp03/preprocessed/set10.hpp
@@ -8,7 +8,6 @@
==============================================================================*/
namespace boost { namespace fusion
{
- struct void_;
struct fusion_sequence_tag;
template <typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9>
struct set : sequence_base<set<T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9> >
@@ -27,7 +26,7 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
set(Sequence const& rhs
- , typename boost::enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: data(rhs) {}
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
explicit
diff --git a/boost/fusion/container/set/detail/cpp03/preprocessed/set20.hpp b/boost/fusion/container/set/detail/cpp03/preprocessed/set20.hpp
index 500e726e80..cab210484a 100644
--- a/boost/fusion/container/set/detail/cpp03/preprocessed/set20.hpp
+++ b/boost/fusion/container/set/detail/cpp03/preprocessed/set20.hpp
@@ -8,7 +8,6 @@
==============================================================================*/
namespace boost { namespace fusion
{
- struct void_;
struct fusion_sequence_tag;
template <typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19>
struct set : sequence_base<set<T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19> >
@@ -27,7 +26,7 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
set(Sequence const& rhs
- , typename boost::enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: data(rhs) {}
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
explicit
diff --git a/boost/fusion/container/set/detail/cpp03/preprocessed/set30.hpp b/boost/fusion/container/set/detail/cpp03/preprocessed/set30.hpp
index 6c92bead0e..2ac448be68 100644
--- a/boost/fusion/container/set/detail/cpp03/preprocessed/set30.hpp
+++ b/boost/fusion/container/set/detail/cpp03/preprocessed/set30.hpp
@@ -8,7 +8,6 @@
==============================================================================*/
namespace boost { namespace fusion
{
- struct void_;
struct fusion_sequence_tag;
template <typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29>
struct set : sequence_base<set<T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29> >
@@ -27,7 +26,7 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
set(Sequence const& rhs
- , typename boost::enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: data(rhs) {}
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
explicit
diff --git a/boost/fusion/container/set/detail/cpp03/preprocessed/set40.hpp b/boost/fusion/container/set/detail/cpp03/preprocessed/set40.hpp
index d3c3e5eb58..76112505ea 100644
--- a/boost/fusion/container/set/detail/cpp03/preprocessed/set40.hpp
+++ b/boost/fusion/container/set/detail/cpp03/preprocessed/set40.hpp
@@ -8,7 +8,6 @@
==============================================================================*/
namespace boost { namespace fusion
{
- struct void_;
struct fusion_sequence_tag;
template <typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39>
struct set : sequence_base<set<T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39> >
@@ -27,7 +26,7 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
set(Sequence const& rhs
- , typename boost::enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: data(rhs) {}
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
explicit
diff --git a/boost/fusion/container/set/detail/cpp03/preprocessed/set50.hpp b/boost/fusion/container/set/detail/cpp03/preprocessed/set50.hpp
index 1d2dfd446d..32954f42ee 100644
--- a/boost/fusion/container/set/detail/cpp03/preprocessed/set50.hpp
+++ b/boost/fusion/container/set/detail/cpp03/preprocessed/set50.hpp
@@ -8,7 +8,6 @@
==============================================================================*/
namespace boost { namespace fusion
{
- struct void_;
struct fusion_sequence_tag;
template <typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 , typename T47 , typename T48 , typename T49>
struct set : sequence_base<set<T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 , T47 , T48 , T49> >
@@ -27,7 +26,7 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
set(Sequence const& rhs
- , typename boost::enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: data(rhs) {}
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
explicit
diff --git a/boost/fusion/container/set/detail/cpp03/set.hpp b/boost/fusion/container/set/detail/cpp03/set.hpp
index 46191c5c63..274a36eb42 100644
--- a/boost/fusion/container/set/detail/cpp03/set.hpp
+++ b/boost/fusion/container/set/detail/cpp03/set.hpp
@@ -8,6 +8,8 @@
#define FUSION_SET_09162005_1104
#include <boost/fusion/support/config.hpp>
+#include <boost/fusion/support/void.hpp>
+#include <boost/fusion/support/detail/enabler.hpp>
#include <boost/fusion/support/is_sequence.hpp>
#include <boost/fusion/support/sequence_base.hpp>
#include <boost/fusion/support/category_of.hpp>
@@ -47,7 +49,6 @@
namespace boost { namespace fusion
{
- struct void_;
struct fusion_sequence_tag;
template <BOOST_PP_ENUM_PARAMS(FUSION_MAX_SET_SIZE, typename T)>
@@ -72,7 +73,7 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
set(Sequence const& rhs
- , typename boost::enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ , typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: data(rhs) {}
#include <boost/fusion/container/set/detail/cpp03/set_forward_ctor.hpp>
diff --git a/boost/fusion/container/set/set.hpp b/boost/fusion/container/set/set.hpp
index 12fd8115d6..f03488b183 100644
--- a/boost/fusion/container/set/set.hpp
+++ b/boost/fusion/container/set/set.hpp
@@ -21,6 +21,8 @@
// C++11 interface
///////////////////////////////////////////////////////////////////////////////
#include <boost/fusion/support/detail/access.hpp>
+#include <boost/fusion/support/void.hpp>
+#include <boost/fusion/support/detail/enabler.hpp>
#include <boost/fusion/support/sequence_base.hpp>
#include <boost/fusion/support/category_of.hpp>
#include <boost/fusion/support/is_sequence.hpp>
@@ -60,8 +62,8 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_FUSION_GPU_ENABLED
set(Sequence const& rhs,
- typename enable_if<traits::is_sequence<Sequence> >::type* = 0,
- typename enable_if<detail::is_same_size<Sequence, storage_type> >::type* = 0)
+ typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler,
+ typename enable_if<detail::is_same_size<Sequence, storage_type>, detail::enabler_>::type = detail::enabler)
: data(rhs) {}
template <typename T>
@@ -102,8 +104,8 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_FUSION_GPU_ENABLED
set(Sequence&& rhs,
- typename enable_if<traits::is_sequence<Sequence> >::type* = 0,
- typename enable_if<detail::is_same_size<Sequence, storage_type> >::type* = 0)
+ typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler,
+ typename enable_if<detail::is_same_size<Sequence, storage_type>, detail::enabler_>::type = detail::enabler)
: data(std::forward<Sequence>(rhs)) {}
template <typename ...U>
diff --git a/boost/fusion/container/vector/detail/cpp03/preprocessed/vvector10.hpp b/boost/fusion/container/vector/detail/cpp03/preprocessed/vvector10.hpp
index cd2bd58b31..0b4e2574c0 100644
--- a/boost/fusion/container/vector/detail/cpp03/preprocessed/vvector10.hpp
+++ b/boost/fusion/container/vector/detail/cpp03/preprocessed/vvector10.hpp
@@ -40,7 +40,7 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_FUSION_GPU_ENABLED
vector(Sequence const& rhs,
- typename boost::enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: vec(BOOST_FUSION_VECTOR_COPY_INIT()) {}
diff --git a/boost/fusion/container/vector/detail/cpp03/preprocessed/vvector20.hpp b/boost/fusion/container/vector/detail/cpp03/preprocessed/vvector20.hpp
index 809485fe25..44e8832f22 100644
--- a/boost/fusion/container/vector/detail/cpp03/preprocessed/vvector20.hpp
+++ b/boost/fusion/container/vector/detail/cpp03/preprocessed/vvector20.hpp
@@ -40,7 +40,7 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_FUSION_GPU_ENABLED
vector(Sequence const& rhs,
- typename boost::enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: vec(BOOST_FUSION_VECTOR_COPY_INIT()) {}
diff --git a/boost/fusion/container/vector/detail/cpp03/preprocessed/vvector30.hpp b/boost/fusion/container/vector/detail/cpp03/preprocessed/vvector30.hpp
index 3f75a05f35..13f7a6261a 100644
--- a/boost/fusion/container/vector/detail/cpp03/preprocessed/vvector30.hpp
+++ b/boost/fusion/container/vector/detail/cpp03/preprocessed/vvector30.hpp
@@ -40,7 +40,7 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_FUSION_GPU_ENABLED
vector(Sequence const& rhs,
- typename boost::enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: vec(BOOST_FUSION_VECTOR_COPY_INIT()) {}
diff --git a/boost/fusion/container/vector/detail/cpp03/preprocessed/vvector40.hpp b/boost/fusion/container/vector/detail/cpp03/preprocessed/vvector40.hpp
index 6c7654ccc5..1730d988b0 100644
--- a/boost/fusion/container/vector/detail/cpp03/preprocessed/vvector40.hpp
+++ b/boost/fusion/container/vector/detail/cpp03/preprocessed/vvector40.hpp
@@ -40,7 +40,7 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_FUSION_GPU_ENABLED
vector(Sequence const& rhs,
- typename boost::enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: vec(BOOST_FUSION_VECTOR_COPY_INIT()) {}
diff --git a/boost/fusion/container/vector/detail/cpp03/preprocessed/vvector50.hpp b/boost/fusion/container/vector/detail/cpp03/preprocessed/vvector50.hpp
index 47fce0e19d..fb334d1a69 100644
--- a/boost/fusion/container/vector/detail/cpp03/preprocessed/vvector50.hpp
+++ b/boost/fusion/container/vector/detail/cpp03/preprocessed/vvector50.hpp
@@ -40,7 +40,7 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_FUSION_GPU_ENABLED
vector(Sequence const& rhs,
- typename boost::enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: vec(BOOST_FUSION_VECTOR_COPY_INIT()) {}
diff --git a/boost/fusion/container/vector/detail/cpp03/vector.hpp b/boost/fusion/container/vector/detail/cpp03/vector.hpp
index 5dcd688650..8a7a4e5d69 100644
--- a/boost/fusion/container/vector/detail/cpp03/vector.hpp
+++ b/boost/fusion/container/vector/detail/cpp03/vector.hpp
@@ -11,6 +11,8 @@
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/fusion/support/config.hpp>
+#include <boost/fusion/support/void.hpp>
+#include <boost/fusion/support/detail/enabler.hpp>
#include <boost/fusion/support/is_sequence.hpp>
#include <boost/fusion/container/vector/vector_fwd.hpp>
#include <boost/fusion/container/vector/detail/cpp03/vector_n_chooser.hpp>
@@ -118,7 +120,7 @@ namespace boost { namespace fusion
template <typename Sequence>
BOOST_FUSION_GPU_ENABLED
vector(Sequence const& rhs,
- typename boost::enable_if<traits::is_sequence<Sequence> >::type* = 0)
+ typename enable_if<traits::is_sequence<Sequence>, detail::enabler_>::type = detail::enabler)
: vec(BOOST_FUSION_VECTOR_COPY_INIT()) {}
// Expand a couple of forwarding constructors for arguments
diff --git a/boost/fusion/container/vector/vector.hpp b/boost/fusion/container/vector/vector.hpp
index 845a019e6b..65bffd0b69 100644
--- a/boost/fusion/container/vector/vector.hpp
+++ b/boost/fusion/container/vector/vector.hpp
@@ -24,6 +24,8 @@
///////////////////////////////////////////////////////////////////////////////
#include <boost/fusion/support/sequence_base.hpp>
#include <boost/fusion/support/is_sequence.hpp>
+#include <boost/fusion/support/void.hpp>
+#include <boost/fusion/support/detail/enabler.hpp>
#include <boost/fusion/support/detail/index_sequence.hpp>
#include <boost/fusion/container/vector/detail/at_impl.hpp>
#include <boost/fusion/container/vector/detail/value_at_impl.hpp>
@@ -164,7 +166,7 @@ namespace boost { namespace fusion
template <typename U>
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
store(U&& rhs
- , typename disable_if<is_same<typename pure<U>::type, store> >::type* = 0)
+ , typename disable_if<is_same<typename pure<U>::type, store>, detail::enabler_>::type = detail::enabler)
: elem(std::forward<U>(rhs))
{}
@@ -274,37 +276,19 @@ namespace boost { namespace fusion
static BOOST_FUSION_GPU_ENABLED
mpl::identity<U> value_at_impl(store<N, U>*);
};
-
- template <typename V, typename... T>
- struct trim_void_;
-
- template <typename... T>
- struct trim_void_<vector<T...> >
- {
- typedef vector_data<
- typename detail::make_index_sequence<sizeof...(T)>::type
- , T...
- > type;
- };
-
- template <typename... T, typename... Tail>
- struct trim_void_<vector<T...>, void_, Tail...>
- : trim_void_<vector<T...> > {};
-
- template <typename... T, typename Head, typename... Tail>
- struct trim_void_<vector<T...>, Head, Tail...>
- : trim_void_<vector<T..., Head>, Tail...> {};
-
- template <typename... T>
- struct trim_void : trim_void_<vector<>, T...> {};
} // namespace boost::fusion::vector_detail
- // This class provides backward compatibility: vector<T, ..., void_, void_, ...>.
template <typename... T>
struct vector
- : vector_detail::trim_void<T...>::type
+ : vector_detail::vector_data<
+ typename detail::make_index_sequence<sizeof...(T)>::type
+ , T...
+ >
{
- typedef typename vector_detail::trim_void<T...>::type base;
+ typedef vector_detail::vector_data<
+ typename detail::make_index_sequence<sizeof...(T)>::type
+ , T...
+ > base;
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
vector()
diff --git a/boost/fusion/sequence/convert.hpp b/boost/fusion/sequence/convert.hpp
index b367714ca2..534d991a28 100644
--- a/boost/fusion/sequence/convert.hpp
+++ b/boost/fusion/sequence/convert.hpp
@@ -8,6 +8,14 @@
#define FUSION_CONVERT_10022005_1442
#include <boost/fusion/support/config.hpp>
+#if BOOST_WORKAROUND(BOOST_GCC, < 30500)
+#include <boost/core/enable_if.hpp>
+#include <boost/type_traits/is_const.hpp>
+#define BOOST_FUSION_WA_GCC34(type1, type2) \
+ boost::lazy_disable_if<boost::is_const<Sequence>, type1, type2>
+#else
+#define BOOST_FUSION_WA_GCC34(type1, type2) type1, type2
+#endif
namespace boost { namespace fusion
{
@@ -32,7 +40,7 @@ namespace boost { namespace fusion
template <typename Tag, typename Sequence>
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
- inline typename result_of::convert<Tag, Sequence>::type
+ inline typename BOOST_FUSION_WA_GCC34(result_of::convert<Tag, Sequence>)::type
convert(Sequence& seq)
{
typedef typename result_of::convert<Tag, Sequence>::gen gen;
@@ -49,4 +57,5 @@ namespace boost { namespace fusion
}
}}
+#undef BOOST_FUSION_WA_GCC34
#endif
diff --git a/boost/fusion/support/detail/enabler.hpp b/boost/fusion/support/detail/enabler.hpp
new file mode 100644
index 0000000000..ea263a41d3
--- /dev/null
+++ b/boost/fusion/support/detail/enabler.hpp
@@ -0,0 +1,22 @@
+/*=============================================================================
+ Copyright (c) 2015 Kohei Takahashi
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+
+#ifndef BOOST_FUSION_SUPPORT_DETAIL_ENABLER_12102015_0346
+#define BOOST_FUSION_SUPPORT_DETAIL_ENABLER_12102015_0346
+
+#include <boost/config.hpp>
+
+namespace boost { namespace fusion { namespace detail
+{
+
+struct enabler_ {};
+BOOST_STATIC_CONSTEXPR enabler_ enabler = {};
+
+}}}
+
+#endif
+
diff --git a/boost/fusion/support/detail/index_sequence.hpp b/boost/fusion/support/detail/index_sequence.hpp
index 1b596e7239..e86def005e 100644
--- a/boost/fusion/support/detail/index_sequence.hpp
+++ b/boost/fusion/support/detail/index_sequence.hpp
@@ -12,8 +12,27 @@
#include <boost/fusion/support/config.hpp>
#include <cstddef>
+// GCC5 has O(logN) implementation, see https://gcc.gnu.org/PR66059 .
+#if (defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence >= 201304) \
+ || (defined(BOOST_LIBSTDCXX_VERSION) \
+ && BOOST_LIBSTDCXX_VERSION >= 500000 && __cplusplus >= 201402)
+#include <utility>
+#define BOOST_FUSION_STDLIB_HAS_INTEGER_SEQUENCE
+#endif
+
namespace boost { namespace fusion { namespace detail
{
+#ifdef BOOST_FUSION_STDLIB_HAS_INTEGER_SEQUENCE
+ // Use aliasing templates without checking availability, the compiler should work.
+ template <std::size_t ...Ints>
+ using index_sequence = std::index_sequence<Ints...>;
+
+ template <std::size_t N>
+ struct make_index_sequence
+ {
+ using type = std::make_index_sequence<N>;
+ };
+#else
template <std::size_t ...Ints>
struct index_sequence
{
@@ -53,6 +72,7 @@ namespace boost { namespace fusion { namespace detail
struct make_index_sequence<0>
: index_sequence<>
{};
+#endif
}}}
#endif
diff --git a/boost/fusion/view/iterator_range/detail/segmented_iterator_range.hpp b/boost/fusion/view/iterator_range/detail/segmented_iterator_range.hpp
index d35e580f8e..4b2c11ebe2 100644
--- a/boost/fusion/view/iterator_range/detail/segmented_iterator_range.hpp
+++ b/boost/fusion/view/iterator_range/detail/segmented_iterator_range.hpp
@@ -8,6 +8,7 @@
#define BOOST_FUSION_SEGMENTED_ITERATOR_RANGE_HPP_INCLUDED
#include <boost/fusion/support/config.hpp>
+#include <boost/detail/workaround.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
@@ -409,11 +410,14 @@ namespace boost { namespace fusion { namespace detail
template <
typename StackBegin
, typename StackEnd
- , bool SameSegment =
- result_of::equal_to<
+ , bool SameSegment
+#if !(BOOST_WORKAROUND(BOOST_GCC, >= 40000) && BOOST_WORKAROUND(BOOST_GCC, < 40200))
+ = result_of::equal_to<
typename StackBegin::car_type::begin_type
, typename StackEnd::car_type::begin_type
- >::type::value>
+ >::type::value
+#endif
+ >
struct make_segmented_range_reduce2
{
typedef
@@ -480,7 +484,14 @@ namespace boost { namespace fusion { namespace detail
template <typename StackBegin, typename StackEnd, int StackBeginSize, int StackEndSize>
struct make_segmented_range_reduce
- : make_segmented_range_reduce2<StackBegin, StackEnd>
+ : make_segmented_range_reduce2<StackBegin, StackEnd
+#if BOOST_WORKAROUND(BOOST_GCC, >= 40000) && BOOST_WORKAROUND(BOOST_GCC, < 40200)
+ , result_of::equal_to<
+ typename StackBegin::car_type::begin_type
+ , typename StackEnd::car_type::begin_type
+ >::type::value
+#endif
+ >
{};
template <typename StackBegin, typename StackEnd>
diff --git a/boost/fusion/view/single_view/detail/next_impl.hpp b/boost/fusion/view/single_view/detail/next_impl.hpp
index 41c658f322..55a4ff11b4 100644
--- a/boost/fusion/view/single_view/detail/next_impl.hpp
+++ b/boost/fusion/view/single_view/detail/next_impl.hpp
@@ -39,7 +39,10 @@ namespace boost { namespace fusion
static type
call(Iterator const& i)
{
- BOOST_STATIC_ASSERT((type::position::value < 2));
+ // Workaround for ICE on GCC 4.0.0.
+ // see https://svn.boost.org/trac/boost/ticket/5808
+ typedef typename type::position position;
+ BOOST_STATIC_ASSERT((position::value < 2));
return type(i.view);
}
};
diff --git a/boost/geometry/algorithms/assign.hpp b/boost/geometry/algorithms/assign.hpp
index b17e305f2a..e3d664de38 100644
--- a/boost/geometry/algorithms/assign.hpp
+++ b/boost/geometry/algorithms/assign.hpp
@@ -24,7 +24,6 @@
#include <boost/mpl/if.hpp>
#include <boost/numeric/conversion/bounds.hpp>
#include <boost/numeric/conversion/cast.hpp>
-#include <boost/type_traits.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
diff --git a/boost/geometry/algorithms/buffer.hpp b/boost/geometry/algorithms/buffer.hpp
index e776072a2f..5dfe9d8846 100644
--- a/boost/geometry/algorithms/buffer.hpp
+++ b/boost/geometry/algorithms/buffer.hpp
@@ -277,7 +277,7 @@ inline void buffer(GeometryIn const& geometry_in,
rescale_policy_type rescale_policy
= boost::geometry::get_rescale_policy<rescale_policy_type>(box);
- detail::buffer::buffer_inserter<polygon_type>(geometry_in, std::back_inserter(geometry_out),
+ detail::buffer::buffer_inserter<polygon_type>(geometry_in, range::back_inserter(geometry_out),
distance_strategy,
side_strategy,
join_strategy,
diff --git a/boost/geometry/algorithms/convex_hull.hpp b/boost/geometry/algorithms/convex_hull.hpp
index 71c18bb5f3..19d28bc7b5 100644
--- a/boost/geometry/algorithms/convex_hull.hpp
+++ b/boost/geometry/algorithms/convex_hull.hpp
@@ -83,7 +83,7 @@ struct hull_to_geometry
geometry::point_order<OutputGeometry>::value,
geometry::closure<OutputGeometry>::value
>::apply(geometry,
- std::back_inserter(
+ range::back_inserter(
// Handle linestring, ring and polygon the same:
detail::as_range
<
diff --git a/boost/geometry/algorithms/detail/andoyer_inverse.hpp b/boost/geometry/algorithms/detail/andoyer_inverse.hpp
index eb8485b8e1..66ad6446e9 100644
--- a/boost/geometry/algorithms/detail/andoyer_inverse.hpp
+++ b/boost/geometry/algorithms/detail/andoyer_inverse.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2015 Oracle and/or its affiliates.
+// Copyright (c) 2015-2016 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -49,23 +49,17 @@ struct andoyer_inverse
T2 const& lat2,
Spheroid const& spheroid)
{
+ CT const c0 = CT(0);
+ CT const c1 = CT(1);
+ CT const pi = math::pi<CT>();
+
result_type result;
// coordinates in radians
- if ( math::equals(lon1, lon2)
- && math::equals(lat1, lat2) )
+ if ( math::equals(lon1, lon2) && math::equals(lat1, lat2) )
{
- result.set(CT(0), CT(0));
- return result;
- }
-
- CT const pi_half = math::pi<CT>() / CT(2);
-
- if ( math::equals(math::abs(lat1), pi_half)
- && math::equals(math::abs(lat2), pi_half) )
- {
- result.set(CT(0), CT(0));
+ result.set(c0, c0);
return result;
}
@@ -80,22 +74,16 @@ struct andoyer_inverse
// H,G,T = infinity if cos_d = 1 or cos_d = -1
// lat1 == +-90 && lat2 == +-90
// lat1 == lat2 && lon1 == lon2
- CT const cos_d = sin_lat1*sin_lat2 + cos_lat1*cos_lat2*cos_dlon;
- CT const d = acos(cos_d);
- CT const sin_d = sin(d);
-
- // just in case since above lat1 and lat2 is checked
- // the check below is equal to cos_d == 1 || cos_d == -1 || d == 0
- if ( math::equals(sin_d, CT(0)) )
- {
- result.set(CT(0), CT(0));
- return result;
- }
-
- // if the function returned before this place
- // and endpoints were on the poles +-90 deg
- // in this case the azimuth could either be 0 or +-pi
-
+ CT cos_d = sin_lat1*sin_lat2 + cos_lat1*cos_lat2*cos_dlon;
+ // on some platforms cos_d may be outside valid range
+ if (cos_d < -c1)
+ cos_d = -c1;
+ else if (cos_d > c1)
+ cos_d = c1;
+
+ CT const d = acos(cos_d); // [0, pi]
+ CT const sin_d = sin(d); // [-1, 1]
+
CT const f = detail::flattening<CT>(spheroid);
if ( BOOST_GEOMETRY_CONDITION(EnableDistance) )
@@ -103,11 +91,18 @@ struct andoyer_inverse
CT const K = math::sqr(sin_lat1-sin_lat2);
CT const L = math::sqr(sin_lat1+sin_lat2);
CT const three_sin_d = CT(3) * sin_d;
- // H or G = infinity if cos_d = 1 or cos_d = -1
- CT const H = (d+three_sin_d)/(CT(1)-cos_d);
- CT const G = (d-three_sin_d)/(CT(1)+cos_d);
- // for e.g. lat1=-90 && lat2=90 here we have G*L=INF*0
+ CT const one_minus_cos_d = c1 - cos_d;
+ CT const one_plus_cos_d = c1 + cos_d;
+ // cos_d = 1 or cos_d = -1 means that the points are antipodal
+
+ CT const H = math::equals(one_minus_cos_d, c0) ?
+ c0 :
+ (d + three_sin_d) / one_minus_cos_d;
+ CT const G = math::equals(one_plus_cos_d, c0) ?
+ c0 :
+ (d - three_sin_d) / one_plus_cos_d;
+
CT const dd = -(f/CT(4))*(H*K+G*L);
CT const a = get_radius<0>(spheroid);
@@ -116,41 +111,88 @@ struct andoyer_inverse
}
else
{
- result.distance = CT(0);
+ result.distance = c0;
}
if ( BOOST_GEOMETRY_CONDITION(EnableAzimuth) )
{
- CT A = CT(0);
- CT U = CT(0);
- if ( ! math::equals(cos_lat2, CT(0)) )
+ // sin_d = 0 <=> antipodal points
+ if (math::equals(sin_d, c0))
{
- CT const tan_lat2 = sin_lat2/cos_lat2;
- CT const M = cos_lat1*tan_lat2-sin_lat1*cos_dlon;
- A = atan2(sin_dlon, M);
- CT const sin_2A = sin(CT(2)*A);
- U = (f/CT(2))*math::sqr(cos_lat1)*sin_2A;
+ // T = inf
+ // dA = inf
+ // azimuth = -inf
+ if (lat1 <= lat2)
+ result.azimuth = c0;
+ else
+ result.azimuth = pi;
}
-
- CT V = CT(0);
- if ( ! math::equals(cos_lat1, CT(0)) )
+ else
{
- CT const tan_lat1 = sin_lat1/cos_lat1;
- CT const N = cos_lat2*tan_lat1-sin_lat2*cos_dlon;
- CT const B = atan2(sin_dlon, N);
- CT const sin_2B = sin(CT(2)*B);
- V = (f/CT(2))*math::sqr(cos_lat2)*sin_2B;
+ CT const c2 = CT(2);
+
+ CT A = c0;
+ CT U = c0;
+ if ( ! math::equals(cos_lat2, c0) )
+ {
+ CT const tan_lat2 = sin_lat2/cos_lat2;
+ CT const M = cos_lat1*tan_lat2-sin_lat1*cos_dlon;
+ A = atan2(sin_dlon, M);
+ CT const sin_2A = sin(c2*A);
+ U = (f/ c2)*math::sqr(cos_lat1)*sin_2A;
+ }
+
+ CT V = c0;
+ if ( ! math::equals(cos_lat1, c0) )
+ {
+ CT const tan_lat1 = sin_lat1/cos_lat1;
+ CT const N = cos_lat2*tan_lat1-sin_lat2*cos_dlon;
+ CT const B = atan2(sin_dlon, N);
+ CT const sin_2B = sin(c2*B);
+ V = (f/ c2)*math::sqr(cos_lat2)*sin_2B;
+ }
+
+ CT const T = d / sin_d;
+ CT const dA = V*T-U;
+
+ result.azimuth = A - dA;
+
+ // even with sin_d == 0 checked above if the second point
+ // is somewhere in the antipodal area T may still be great
+ // therefore dA may be great and the resulting azimuth
+ // may be some more or less arbitrary angle
+ if (A >= c0) // A indicates Eastern hemisphere
+ {
+ if (dA >= c0) // A altered towards 0
+ {
+ if ((result.azimuth) < c0)
+ result.azimuth = c0;
+ }
+ else // dA < 0, A altered towards pi
+ {
+ if (result.azimuth > pi)
+ result.azimuth = pi;
+ }
+ }
+ else // A indicates Western hemisphere
+ {
+ if (dA <= c0) // A altered towards 0
+ {
+ if (result.azimuth > c0)
+ result.azimuth = c0;
+ }
+ else // dA > 0, A altered towards -pi
+ {
+ CT const minus_pi = -pi;
+ if ((result.azimuth) < minus_pi)
+ result.azimuth = minus_pi;
+ }
+ }
}
-
- // infinity if sin_d = 0, so cos_d = 1 or cos_d = -1
- CT const T = d / sin_d;
- CT const dA = V*T-U;
-
- result.azimuth = A - dA;
}
else
{
- result.azimuth = CT(0);
+ result.azimuth = c0;
}
return result;
diff --git a/boost/geometry/algorithms/detail/as_range.hpp b/boost/geometry/algorithms/detail/as_range.hpp
index d0dfb07e43..fef5156eef 100644
--- a/boost/geometry/algorithms/detail/as_range.hpp
+++ b/boost/geometry/algorithms/detail/as_range.hpp
@@ -15,8 +15,6 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_HPP
-#include <boost/type_traits.hpp>
-
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
diff --git a/boost/geometry/algorithms/detail/assign_values.hpp b/boost/geometry/algorithms/detail/assign_values.hpp
index 5e4a1795b5..ef5691e97c 100644
--- a/boost/geometry/algorithms/detail/assign_values.hpp
+++ b/boost/geometry/algorithms/detail/assign_values.hpp
@@ -23,7 +23,6 @@
#include <boost/mpl/if.hpp>
#include <boost/numeric/conversion/bounds.hpp>
#include <boost/numeric/conversion/cast.hpp>
-#include <boost/type_traits.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/algorithms/append.hpp>
diff --git a/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
index 606726f338..8447532a6c 100644
--- a/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
@@ -918,6 +918,10 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
collection.discard_rings();
collection.block_turns();
collection.enrich();
+
+ // phase 1: turns (after enrichment/clustering)
+ visit_pieces_policy.apply(const_collection, 1);
+
collection.traverse();
// Reverse all offsetted rings / traversed rings if:
@@ -943,8 +947,8 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
collection.template assign<GeometryOutput>(out);
// Visit collection again
- // phase 1: rings (after discarding and traversing)
- visit_pieces_policy.apply(const_collection, 1);
+ // phase 2: rings (after traversing)
+ visit_pieces_policy.apply(const_collection, 2);
}
template
diff --git a/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp b/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
index 255ac797dc..c0fa7b0e33 100644
--- a/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
@@ -46,15 +46,26 @@ class backtrack_for_buffer
public :
typedef detail::overlay::backtrack_state state_type;
- template <typename Operation, typename Rings, typename Turns, typename Geometry, typename RobustPolicy>
+ template
+ <
+ typename Operation,
+ typename Rings,
+ typename Turns,
+ typename Geometry,
+ typename RobustPolicy,
+ typename Visitor
+ >
static inline void apply(std::size_t size_at_start,
Rings& rings, typename boost::range_value<Rings>::type& ring,
- Turns& turns, Operation& operation,
- std::string const& /*reason*/,
+ Turns& turns,
+ typename boost::range_value<Turns>::type const& turn,
+ Operation& operation,
+ detail::overlay::traverse_error_type traverse_error,
Geometry const& ,
Geometry const& ,
RobustPolicy const& ,
- state_type& state
+ state_type& state,
+ Visitor& visitor
)
{
#if defined(BOOST_GEOMETRY_COUNT_BACKTRACK_WARNINGS)
@@ -62,7 +73,7 @@ extern int g_backtrack_warning_count;
g_backtrack_warning_count++;
#endif
//std::cout << "!";
-//std::cout << "WARNING " << reason << std::endl;
+//std::cout << "WARNING " << traverse_error_string(traverse_error) << std::endl;
state.m_good = false;
@@ -78,6 +89,41 @@ g_backtrack_warning_count++;
}
};
+struct buffer_overlay_visitor
+{
+public :
+ void print(char const* header)
+ {
+ }
+
+ template <typename Turns>
+ void print(char const* header, Turns const& turns, int turn_index)
+ {
+ }
+
+ template <typename Turns>
+ void print(char const* header, Turns const& turns, int turn_index, int op_index)
+ {
+ }
+
+ template <typename Turns>
+ void visit_turns(int , Turns const& ) {}
+
+ template <typename Clusters, typename Turns>
+ void visit_clusters(Clusters const& , Turns const& ) {}
+
+ template <typename Turns, typename Turn, typename Operation>
+ void visit_traverse(Turns const& turns, Turn const& turn, Operation const& op, const char* header)
+ {
+ }
+
+ template <typename Turns, typename Turn, typename Operation>
+ void visit_traverse_reject(Turns const& , Turn const& , Operation const& ,
+ detail::overlay::traverse_error_type )
+ {}
+};
+
+
// Should follow traversal-turn-concept (enrichment, visit structure)
// and adds index in piece vector to find it back
template <typename Point, typename SegmentRatio>
diff --git a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
index b580cf5b9b..3fc3c2347a 100644
--- a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
@@ -2,6 +2,10 @@
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2016.
+// Modifications copyright (c) 2016 Oracle and/or its affiliates.
+// 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)
@@ -255,8 +259,11 @@ struct buffered_piece_collection
{
geometry::envelope(m_ring, m_box);
- // create monotonic sections in y-dimension
- typedef boost::mpl::vector_c<std::size_t, 1> dimensions;
+ // create monotonic sections in x-dimension
+ // The dimension is critical because the direction is later used
+ // in the optimization for within checks using winding strategy
+ // and this strategy is scanning in x direction.
+ typedef boost::mpl::vector_c<std::size_t, 0> dimensions;
geometry::sectionalize<false, dimensions>(m_ring,
detail::no_rescale_policy(), m_sections);
}
@@ -286,6 +293,15 @@ struct buffered_piece_collection
typedef geometry::sections<robust_box_type, 2> sections_type;
sections_type monotonic_sections;
+ // Define the clusters, mapping cluster_id -> turns
+ typedef std::map
+ <
+ signed_size_type,
+ std::set<signed_size_type>
+ > cluster_type;
+
+ cluster_type m_clusters;
+
RobustPolicy const& m_robust_policy;
@@ -479,7 +495,8 @@ struct buffered_piece_collection
// Within can have in rare cases a rounding issue. We don't discard this
// point, so it can be used to continue started rings in traversal. But
// will never start a new ring from this type of points.
- it->selectable_start = false;
+ it->operations[0].enriched.startable = false;
+ it->operations[1].enriched.startable = false;
}
#endif
}
@@ -931,8 +948,12 @@ struct buffered_piece_collection
piece pc;
pc.type = type;
pc.index = static_cast<signed_size_type>(boost::size(m_pieces));
+
+ current_segment_id.piece_index = pc.index;
+
pc.first_seg_id = current_segment_id;
+
// Assign left/right (for first/last piece per ring they will be re-assigned later)
pc.left_index = pc.index - 1;
pc.right_index = pc.index + 1;
@@ -1196,7 +1217,7 @@ struct buffered_piece_collection
>::type side_strategy_type;
enrich_intersection_points<false, false, overlay_union>(m_turns,
- detail::overlay::operation_union,
+ m_clusters, detail::overlay::operation_union,
offsetted_rings, offsetted_rings,
m_robust_policy, side_strategy_type());
}
@@ -1213,7 +1234,7 @@ struct buffered_piece_collection
offsetted_rings[it->operations[0].seg_id.multi_index].has_discarded_intersections = true;
offsetted_rings[it->operations[1].seg_id.multi_index].has_discarded_intersections = true;
}
- else if (! it->both(detail::overlay::operation_union))
+ else
{
offsetted_rings[it->operations[0].seg_id.multi_index].has_accepted_intersections = true;
offsetted_rings[it->operations[1].seg_id.multi_index].has_accepted_intersections = true;
@@ -1331,13 +1352,15 @@ struct buffered_piece_collection
false, false,
buffered_ring_collection<buffered_ring<Ring> >,
buffered_ring_collection<buffered_ring<Ring > >,
+ detail::overlay::operation_union,
backtrack_for_buffer
> traverser;
traversed_rings.clear();
+ buffer_overlay_visitor visitor;
traverser::apply(offsetted_rings, offsetted_rings,
- detail::overlay::operation_union,
- m_robust_policy, m_turns, traversed_rings);
+ m_robust_policy, m_turns, traversed_rings,
+ m_clusters, visitor);
}
inline void reverse()
diff --git a/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp b/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp
index 29a618b923..db6136e1ae 100644
--- a/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp
@@ -149,6 +149,14 @@ struct ring_type
}
+
+template <>
+struct single_tag_of<detail::buffer::buffered_ring_collection_tag>
+{
+ typedef ring_tag type;
+};
+
+
namespace dispatch
{
@@ -213,6 +221,21 @@ struct within
};
+template <typename Geometry>
+struct is_empty<Geometry, detail::buffer::buffered_ring_collection_tag>
+ : detail::is_empty::multi_is_empty<detail::is_empty::range_is_empty>
+{};
+
+
+template <typename Geometry>
+struct envelope<Geometry, detail::buffer::buffered_ring_collection_tag>
+ : detail::envelope::envelope_multi_range
+ <
+ detail::envelope::envelope_range
+ >
+{};
+
+
} // namespace dispatch
namespace detail { namespace overlay
diff --git a/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp b/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp
index 05fc6df8ff..da1d084d32 100644
--- a/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp
+++ b/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp
@@ -2,6 +2,10 @@
// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2016.
+// Modifications copyright (c) 2016 Oracle and/or its affiliates.
+// Contributed and/or modified by 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)
@@ -103,32 +107,32 @@ template
typename Iterator
>
inline bool point_in_section(Strategy& strategy, State& state,
- Point const& point, CoordinateType const& point_y,
+ Point const& point, CoordinateType const& point_x,
Iterator begin, Iterator end,
int direction)
{
if (direction == 0)
{
- // Not a monotonic section, or no change in Y-direction
+ // Not a monotonic section, or no change in X-direction
return point_in_range(strategy, state, point, begin, end);
}
- // We're in a monotonic section in y-direction
+ // We're in a monotonic section in x-direction
Iterator it = begin;
for (Iterator previous = it++; it != end; ++previous, ++it)
{
// Depending on sections.direction we can quit for this section
- CoordinateType const previous_y = geometry::get<1>(*previous);
+ CoordinateType const previous_x = geometry::get<0>(*previous);
- if (direction == 1 && point_y < previous_y)
+ if (direction == 1 && point_x < previous_x)
{
- // Section goes upwards, y increases, point is is below section
+ // Section goes upwards, x increases, point is is below section
return true;
}
- else if (direction == -1 && point_y > previous_y)
+ else if (direction == -1 && point_x > previous_x)
{
- // Section goes downwards, y decreases, point is above section
+ // Section goes downwards, x decreases, point is above section
return true;
}
@@ -145,6 +149,9 @@ inline bool point_in_section(Strategy& strategy, State& state,
template <typename Point, typename Original>
inline int point_in_original(Point const& point, Original const& original)
{
+ // The winding strategy is scanning in x direction
+ // therefore it's critical to pass direction calculated
+ // for x dimension below.
typedef strategy::within::winding<Point> strategy_type;
typename strategy_type::state_type state;
@@ -166,7 +173,7 @@ inline int point_in_original(Point const& point, Original const& original)
typedef typename boost::range_value<sections_type const>::type section_type;
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
- coordinate_type const point_y = geometry::get<1>(point);
+ coordinate_type const point_x = geometry::get<0>(point);
// Walk through all monotonic sections of this original
for (iterator_type it = boost::begin(original.m_sections);
@@ -177,11 +184,11 @@ inline int point_in_original(Point const& point, Original const& original)
if (! section.duplicate
&& section.begin_index < section.end_index
- && point_y >= geometry::get<min_corner, 1>(section.bounding_box)
- && point_y <= geometry::get<max_corner, 1>(section.bounding_box))
+ && point_x >= geometry::get<min_corner, 0>(section.bounding_box)
+ && point_x <= geometry::get<max_corner, 0>(section.bounding_box))
{
- // y-coordinate of point overlaps with section
- if (! point_in_section(strategy, state, point, point_y,
+ // x-coordinate of point overlaps with section
+ if (! point_in_section(strategy, state, point, point_x,
boost::begin(original.m_ring) + section.begin_index,
boost::begin(original.m_ring) + section.end_index + 1,
section.directions[0]))
diff --git a/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp b/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp
index 0aca21ce88..d7146befb9 100644
--- a/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp
+++ b/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp
@@ -2,6 +2,10 @@
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2016.
+// Modifications copyright (c) 2016 Oracle and/or its affiliates.
+// 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)
@@ -218,16 +222,16 @@ public :
BOOST_GEOMETRY_ASSERT(! piece.sections.empty());
- coordinate_type const point_y = geometry::get<1>(turn.robust_point);
+ coordinate_type const point_x = geometry::get<0>(turn.robust_point);
for (std::size_t s = 0; s < piece.sections.size(); s++)
{
section_type const& section = piece.sections[s];
- // If point within vertical range of monotonic section:
+ // If point within horizontal range of monotonic section:
if (! section.duplicate
&& section.begin_index < section.end_index
- && point_y >= geometry::get<min_corner, 1>(section.bounding_box) - 1
- && point_y <= geometry::get<max_corner, 1>(section.bounding_box) + 1)
+ && point_x >= geometry::get<min_corner, 0>(section.bounding_box) - 1
+ && point_x <= geometry::get<max_corner, 0>(section.bounding_box) + 1)
{
for (signed_size_type i = section.begin_index + 1; i <= section.end_index; i++)
{
@@ -239,21 +243,21 @@ public :
// First check if it is in range - if it is not, the
// expensive side_of_intersection does not need to be
// applied
- coordinate_type y1 = geometry::get<1>(previous);
- coordinate_type y2 = geometry::get<1>(current);
+ coordinate_type x1 = geometry::get<0>(previous);
+ coordinate_type x2 = geometry::get<0>(current);
- if (y1 > y2)
+ if (x1 > x2)
{
- std::swap(y1, y2);
+ std::swap(x1, x2);
}
- if (point_y >= y1 - 1 && point_y <= y2 + 1)
+ if (point_x >= x1 - 1 && point_x <= x2 + 1)
{
segment_type const r(previous, current);
int const side = strategy::side::side_of_intersection::apply(p, q, r,
turn.robust_point);
- // Sections are monotonic in y-dimension
+ // Sections are monotonic in x-dimension
if (side == 1)
{
// Left on segment
diff --git a/boost/geometry/algorithms/detail/direction_code.hpp b/boost/geometry/algorithms/detail/direction_code.hpp
new file mode 100644
index 0000000000..26d53ab4e5
--- /dev/null
+++ b/boost/geometry/algorithms/detail/direction_code.hpp
@@ -0,0 +1,79 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
+
+// This file was modified by Oracle on 2015.
+// Modifications copyright (c) 2015 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP
+
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/util/math.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <std::size_t Index, typename Point1, typename Point2>
+inline int sign_of_difference(Point1 const& point1, Point2 const& point2)
+{
+ return
+ math::equals(geometry::get<Index>(point1), geometry::get<Index>(point2))
+ ?
+ 0
+ :
+ (geometry::get<Index>(point1) > geometry::get<Index>(point2) ? 1 : -1);
+}
+
+
+// Gives sense of direction for point p, collinear w.r.t. segment (a,b)
+// Returns -1 if p goes backward w.r.t (a,b), so goes from b in direction of a
+// Returns 1 if p goes forward, so extends (a,b)
+// Returns 0 if p is equal with b, or if (a,b) is degenerate
+// Note that it does not do any collinearity test, that should be done before
+template <typename Point1, typename Point2>
+inline int direction_code(Point1 const& segment_a, Point1 const& segment_b,
+ const Point2& p)
+{
+ // Suppose segment = (4 3,4 4) and p =(4 2)
+ // Then sign_a1 = 1 and sign_p1 = 1 -> goes backward -> return -1
+
+ int const sign_a0 = sign_of_difference<0>(segment_b, segment_a);
+ int const sign_a1 = sign_of_difference<1>(segment_b, segment_a);
+
+ if (sign_a0 == 0 && sign_a1 == 0)
+ {
+ return 0;
+ }
+
+ int const sign_p0 = sign_of_difference<0>(segment_b, p);
+ int const sign_p1 = sign_of_difference<1>(segment_b, p);
+
+ if (sign_p0 == 0 && sign_p1 == 0)
+ {
+ return 0;
+ }
+
+ return sign_a0 == sign_p0 && sign_a1 == sign_p1 ? -1 : 1;
+}
+
+
+} // namespace detail
+#endif //DOXYGEN_NO_DETAIL
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP
diff --git a/boost/geometry/algorithms/detail/disjoint/box_box.hpp b/boost/geometry/algorithms/detail/disjoint/box_box.hpp
index 6074af982b..3b81755e20 100644
--- a/boost/geometry/algorithms/detail/disjoint/box_box.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/box_box.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2015.
-// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2016.
+// Modifications copyright (c) 2013-2016, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -28,6 +28,9 @@
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
+#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
namespace boost { namespace geometry
{
@@ -39,7 +42,13 @@ namespace detail { namespace disjoint
template
<
typename Box1, typename Box2,
- std::size_t Dimension, std::size_t DimensionCount
+ std::size_t Dimension = 0,
+ std::size_t DimensionCount = dimension<Box1>::value,
+ typename CSTag = typename tag_cast
+ <
+ typename cs_tag<Box1>::type,
+ spherical_tag
+ >::type
>
struct box_box
{
@@ -62,8 +71,8 @@ struct box_box
};
-template <typename Box1, typename Box2, std::size_t DimensionCount>
-struct box_box<Box1, Box2, DimensionCount, DimensionCount>
+template <typename Box1, typename Box2, std::size_t DimensionCount, typename CSTag>
+struct box_box<Box1, Box2, DimensionCount, DimensionCount, CSTag>
{
static inline bool apply(Box1 const& , Box2 const& )
{
@@ -72,6 +81,51 @@ struct box_box<Box1, Box2, DimensionCount, DimensionCount>
};
+template <typename Box1, typename Box2, std::size_t DimensionCount>
+struct box_box<Box1, Box2, 0, DimensionCount, spherical_tag>
+{
+ static inline bool apply(Box1 const& box1, Box2 const& box2)
+ {
+ typedef typename geometry::select_most_precise
+ <
+ typename coordinate_type<Box1>::type,
+ typename coordinate_type<Box2>::type
+ >::type calc_t;
+ typedef typename coordinate_system<Box1>::type::units units_t;
+ typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
+
+ calc_t const b1_min = get<min_corner, 0>(box1);
+ calc_t const b1_max = get<max_corner, 0>(box1);
+ calc_t const b2_min = get<min_corner, 0>(box2);
+ calc_t const b2_max = get<max_corner, 0>(box2);
+
+ // min <= max <=> diff >= 0
+ calc_t const diff1 = b1_max - b1_min;
+ calc_t const diff2 = b2_max - b2_min;
+
+ // check the intersection if neither box cover the whole globe
+ if (diff1 < constants::period() && diff2 < constants::period())
+ {
+ // calculate positive longitude translation with b1_min as origin
+ calc_t const diff_min = math::longitude_distance_unsigned<units_t>(b1_min, b2_min);
+ calc_t const b2_min_transl = b1_min + diff_min; // always right of b1_min
+
+ if (b2_min_transl > b1_max // b2_min right of b1_max
+ && b2_min_transl - constants::period() + diff2 < b1_min) // b2_max left of b1_min
+ {
+ return true;
+ }
+ }
+
+ return box_box
+ <
+ Box1, Box2,
+ 1, DimensionCount
+ >::apply(box1, box2);
+ }
+};
+
+
/*!
\brief Internal utility function to detect if boxes are disjoint
\note Is used from other algorithms, declared separately
@@ -80,11 +134,7 @@ struct box_box<Box1, Box2, DimensionCount, DimensionCount>
template <typename Box1, typename Box2>
inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2)
{
- return box_box
- <
- Box1, Box2,
- 0, dimension<Box1>::type::value
- >::apply(box1, box2);
+ return box_box<Box1, Box2>::apply(box1, box2);
}
diff --git a/boost/geometry/algorithms/detail/disjoint/point_box.hpp b/boost/geometry/algorithms/detail/disjoint/point_box.hpp
index 73b7b70990..2f1085ada9 100644
--- a/boost/geometry/algorithms/detail/disjoint/point_box.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/point_box.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland
-// This file was modified by Oracle on 2013-2015.
-// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2016.
+// Modifications copyright (c) 2013-2016, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -28,6 +28,7 @@
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
+#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
namespace boost { namespace geometry
{
@@ -37,49 +38,19 @@ namespace detail { namespace disjoint
{
-template
-<
- typename Point, typename Box,
- std::size_t Dimension, std::size_t DimensionCount
->
-struct point_box
-{
- static inline bool apply(Point const& point, Box const& box)
- {
- if (get<Dimension>(point) < get<min_corner, Dimension>(box)
- || get<Dimension>(point) > get<max_corner, Dimension>(box))
- {
- return true;
- }
- return point_box
- <
- Point, Box,
- Dimension + 1, DimensionCount
- >::apply(point, box);
- }
-};
-
-
-template <typename Point, typename Box, std::size_t DimensionCount>
-struct point_box<Point, Box, DimensionCount, DimensionCount>
-{
- static inline bool apply(Point const& , Box const& )
- {
- return false;
- }
-};
-
/*!
\brief Internal utility function to detect if point/box are disjoint
*/
template <typename Point, typename Box>
inline bool disjoint_point_box(Point const& point, Box const& box)
{
- return detail::disjoint::point_box
- <
- Point, Box,
- 0, dimension<Point>::type::value
- >::apply(point, box);
+ // ! covered_by(point, box)
+ return ! strategy::within::relate_point_box_loop
+ <
+ strategy::within::covered_by_range,
+ Point, Box,
+ 0, dimension<Point>::type::value
+ >::apply(point, box);
}
@@ -94,8 +65,18 @@ namespace dispatch
template <typename Point, typename Box, std::size_t DimensionCount>
struct disjoint<Point, Box, DimensionCount, point_tag, box_tag, false>
- : detail::disjoint::point_box<Point, Box, 0, DimensionCount>
-{};
+{
+ static inline bool apply(Point const& point, Box const& box)
+ {
+ // ! covered_by(point, box)
+ return ! strategy::within::relate_point_box_loop
+ <
+ strategy::within::covered_by_range,
+ Point, Box,
+ 0, DimensionCount
+ >::apply(point, box);
+ }
+};
} // namespace dispatch
diff --git a/boost/geometry/algorithms/detail/disjoint/segment_box.hpp b/boost/geometry/algorithms/detail/disjoint/segment_box.hpp
index 5368432ed4..cc0c7949e3 100644
--- a/boost/geometry/algorithms/detail/disjoint/segment_box.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/segment_box.hpp
@@ -128,7 +128,9 @@ struct disjoint_segment_box_impl
&& t_min.first > ti_max)
||
(geometry::math::equals(t_max.second, 0)
- && t_max.first < ti_min) )
+ && t_max.first < ti_min)
+ ||
+ (math::sign(ti_min) * math::sign(ti_max) > 0) )
{
return true;
}
@@ -197,6 +199,11 @@ struct disjoint_segment_box_impl
{
if ( geometry::math::equals(t_min.first, 0) ) { t_min.first = -1; }
if ( geometry::math::equals(t_max.first, 0) ) { t_max.first = 1; }
+
+ if (math::sign(t_min.first) * math::sign(t_max.first) > 0)
+ {
+ return true;
+ }
}
if ( t_min.first > diff || t_max.first < 0 )
diff --git a/boost/geometry/algorithms/detail/envelope/segment.hpp b/boost/geometry/algorithms/detail/envelope/segment.hpp
index 570f0e1a43..6186e72a3a 100644
--- a/boost/geometry/algorithms/detail/envelope/segment.hpp
+++ b/boost/geometry/algorithms/detail/envelope/segment.hpp
@@ -4,10 +4,11 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2016.
+// Modifications copyright (c) 2015-2016, 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
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -84,6 +85,7 @@ class compute_mbr_of_segment
private:
// computes the azimuths of the segment with endpoints (lon1, lat1)
// and (lon2, lat2)
+ // radians
template <typename CalculationType>
static inline void azimuths(CalculationType const& lon1,
CalculationType const& lat1,
@@ -92,7 +94,7 @@ private:
CalculationType& a1,
CalculationType& a2)
{
- BOOST_GEOMETRY_ASSERT(math::smaller(lon1, lon2));
+ BOOST_GEOMETRY_ASSERT(lon1 <= lon2);
CalculationType dlon = lon2 - lon1;
CalculationType sin_dlon = sin(dlon);
@@ -108,8 +110,9 @@ private:
a2 = atan2(-sin_dlon * cos_lat1,
cos_lat2 * sin_lat1 - sin_lat2 * cos_lat1 * cos_dlon);
a2 += math::pi<CalculationType>();
- }
+ }
+ // degrees or radians
template <typename CalculationType>
static inline void swap(CalculationType& lon1,
CalculationType& lat1,
@@ -120,6 +123,7 @@ private:
std::swap(lat1, lat2);
}
+ // radians
template <typename CalculationType>
static inline bool contains_pi_half(CalculationType const& a1,
CalculationType const& a2)
@@ -134,13 +138,20 @@ private:
: (a1 > pi_half && pi_half > a2);
}
- template <typename CoordinateType>
+ // radians or degrees
+ template <typename Units, typename CoordinateType>
static inline bool crosses_antimeridian(CoordinateType const& lon1,
CoordinateType const& lon2)
{
- return math::larger(math::abs(lon1 - lon2), math::pi<CoordinateType>());
+ typedef math::detail::constants_on_spheroid
+ <
+ CoordinateType, Units
+ > constants;
+
+ return math::abs(lon1 - lon2) > constants::half_period(); // > pi
}
+ // radians
template <typename CalculationType>
static inline CalculationType max_latitude(CalculationType const& azimuth,
CalculationType const& latitude)
@@ -149,39 +160,46 @@ private:
return acos( math::abs(cos(latitude) * sin(azimuth)) );
}
- template <typename CalculationType>
+ // degrees or radians
+ template <typename Units, typename CalculationType>
static inline void compute_box_corners(CalculationType& lon1,
CalculationType& lat1,
CalculationType& lon2,
- CalculationType& lat2,
- CalculationType const& a1,
- CalculationType const& a2)
+ CalculationType& lat2)
{
// coordinates are assumed to be in radians
- BOOST_GEOMETRY_ASSERT(! math::larger(lon1, lon2));
+ BOOST_GEOMETRY_ASSERT(lon1 <= lon2);
- if (math::equals(a1, a2))
+ CalculationType lon1_rad = math::as_radian<Units>(lon1);
+ CalculationType lat1_rad = math::as_radian<Units>(lat1);
+ CalculationType lon2_rad = math::as_radian<Units>(lon2);
+ CalculationType lat2_rad = math::as_radian<Units>(lat2);
+
+ CalculationType a1 = 0, a2 = 0;
+ azimuths(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a2);
+
+ if (lat1 > lat2)
{
- // the segment must lie on the equator; nothing to do
- BOOST_GEOMETRY_ASSERT(math::equals(lat1, CalculationType(0)));
- BOOST_GEOMETRY_ASSERT(math::equals(lat2, CalculationType(0)));
- return;
+ std::swap(lat1, lat2);
+ std::swap(lat1_rad, lat2_rad);
}
- if (math::larger(lat1, lat2))
+ if (math::equals(a1, a2))
{
- std::swap(lat1, lat2);
+ // the segment must lie on the equator or is very short
+ return;
}
if (contains_pi_half(a1, a2))
{
- CalculationType mid_lat = lat1 + lat2;
+ CalculationType const mid_lat = lat1 + lat2;
if (mid_lat < 0)
{
// update using min latitude
- CalculationType lat_min = -max_latitude(a1, lat1);
+ CalculationType const lat_min_rad = -max_latitude(a1, lat1_rad);
+ CalculationType const lat_min = math::from_radian<Units>(lat_min_rad);
- if (math::larger(lat1, lat_min))
+ if (lat1 > lat_min)
{
lat1 = lat_min;
}
@@ -189,9 +207,10 @@ private:
else if (mid_lat > 0)
{
// update using max latitude
- CalculationType lat_max = max_latitude(a1, lat1);
+ CalculationType const lat_max_rad = max_latitude(a1, lat1_rad);
+ CalculationType const lat_max = math::from_radian<Units>(lat_max_rad);
- if (math::smaller(lat2, lat_max))
+ if (lat2 < lat_max)
{
lat2 = lat_max;
}
@@ -199,24 +218,27 @@ private:
}
}
- template <typename CalculationType>
+ template <typename Units, typename CalculationType>
static inline void apply(CalculationType& lon1,
CalculationType& lat1,
CalculationType& lon2,
CalculationType& lat2)
{
- CalculationType const half_pi = math::half_pi<CalculationType>();
+ typedef math::detail::constants_on_spheroid
+ <
+ CalculationType, Units
+ > constants;
- bool is_pole1 = math::equals(math::abs(lat1), half_pi);
- bool is_pole2 = math::equals(math::abs(lat2), half_pi);
+ bool is_pole1 = math::equals(math::abs(lat1), constants::max_latitude());
+ bool is_pole2 = math::equals(math::abs(lat2), constants::max_latitude());
if (is_pole1 && is_pole2)
{
// both points are poles; nothing more to do:
// longitudes are already normalized to 0
- BOOST_GEOMETRY_ASSERT(lon1 == CalculationType(0)
- &&
- lon2 == CalculationType(0));
+ // but just in case
+ lon1 = 0;
+ lon2 = 0;
}
else if (is_pole1 && !is_pole2)
{
@@ -233,10 +255,10 @@ private:
lon2 = lon1;
}
- if (math::equals(lon1, lon2))
+ if (lon1 == lon2)
{
// segment lies on a meridian
- if (math::larger(lat1, lat2))
+ if (lat1 > lat2)
{
std::swap(lat1, lat2);
}
@@ -245,25 +267,22 @@ private:
BOOST_GEOMETRY_ASSERT(!is_pole1 && !is_pole2);
- if (math::larger(lon1, lon2))
+ if (lon1 > lon2)
{
swap(lon1, lat1, lon2, lat2);
}
- if (crosses_antimeridian(lon1, lon2))
+ if (crosses_antimeridian<Units>(lon1, lon2))
{
- lon1 += math::two_pi<CalculationType>();
+ lon1 += constants::period();
swap(lon1, lat1, lon2, lat2);
}
- CalculationType a1 = 0, a2 = 0;
- azimuths(lon1, lat1, lon2, lat2, a1, a2);
-
- compute_box_corners(lon1, lat1, lon2, lat2, a1, a2);
+ compute_box_corners<Units>(lon1, lat1, lon2, lat2);
}
public:
- template <typename CalculationType, typename Box>
+ template <typename Units, typename CalculationType, typename Box>
static inline void apply(CalculationType lon1,
CalculationType lat1,
CalculationType lon2,
@@ -274,12 +293,12 @@ public:
typedef typename helper_geometry
<
- Box, box_coordinate_type, radian
+ Box, box_coordinate_type, Units
>::type helper_box_type;
helper_box_type radian_mbr;
- apply(lon1, lat1, lon2, lat2);
+ apply<Units>(lon1, lat1, lon2, lat2);
geometry::set
<
@@ -316,11 +335,14 @@ struct envelope_segment_on_sphere
Point p1_normalized = detail::return_normalized<Point>(p1);
Point p2_normalized = detail::return_normalized<Point>(p2);
- compute_mbr_of_segment::apply(geometry::get_as_radian<0>(p1_normalized),
- geometry::get_as_radian<1>(p1_normalized),
- geometry::get_as_radian<0>(p2_normalized),
- geometry::get_as_radian<1>(p2_normalized),
- mbr);
+ typedef typename coordinate_system<Point>::type::units units_type;
+
+ compute_mbr_of_segment::template apply<units_type>(
+ geometry::get<0>(p1_normalized),
+ geometry::get<1>(p1_normalized),
+ geometry::get<0>(p2_normalized),
+ geometry::get<1>(p2_normalized),
+ mbr);
// now compute the envelope range for coordinates of
// dimension 2 and higher
diff --git a/boost/geometry/algorithms/detail/intersection/interface.hpp b/boost/geometry/algorithms/detail/intersection/interface.hpp
index 2af618d974..fd989866dd 100644
--- a/boost/geometry/algorithms/detail/intersection/interface.hpp
+++ b/boost/geometry/algorithms/detail/intersection/interface.hpp
@@ -54,7 +54,7 @@ struct intersection
<
Geometry1, Geometry2, OneOut,
overlay_intersection
- >::apply(geometry1, geometry2, robust_policy, std::back_inserter(geometry_out), strategy);
+ >::apply(geometry1, geometry2, robust_policy, range::back_inserter(geometry_out), strategy);
return true;
}
diff --git a/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp b/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp
index 285edfdd6c..03c06c28d1 100644
--- a/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp
+++ b/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp
@@ -72,7 +72,7 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point,
<< geometry::get<0>(point) << ", " << geometry::get<1>(point) << ")"
<< std::endl;
#endif
- // The code below thies condition checks all spikes/dups
+ // The code below this condition checks all spikes/dups
// for geometries >= 3 points.
// So we have to check the first potential duplicate differently
if (boost::size(range) == 1
diff --git a/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp b/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp
index 90901dee70..a8171e1482 100644
--- a/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp
+++ b/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp
@@ -48,7 +48,6 @@ inline void clear_visit_info(Turns& turns)
{
op_it->visited.clear();
}
- it->discarded = false;
}
}
@@ -62,6 +61,34 @@ struct backtrack_state
};
+enum traverse_error_type
+{
+ traverse_error_none,
+ traverse_error_no_next_ip_at_start,
+ traverse_error_no_next_ip,
+ traverse_error_dead_end_at_start,
+ traverse_error_dead_end,
+ traverse_error_visit_again,
+ traverse_error_endless_loop
+};
+
+inline std::string traverse_error_string(traverse_error_type error)
+{
+ switch (error)
+ {
+ case traverse_error_none : return "";
+ case traverse_error_no_next_ip_at_start : return "No next IP at start";
+ case traverse_error_no_next_ip : return "No next IP";
+ case traverse_error_dead_end_at_start : return "Dead end at start";
+ case traverse_error_dead_end : return "Dead end";
+ case traverse_error_visit_again : return "Visit again";
+ case traverse_error_endless_loop : return "Endless loop";
+ default : return "";
+ }
+ return "";
+}
+
+
template
<
typename Geometry1,
@@ -73,23 +100,28 @@ class backtrack_check_self_intersections
{
bool m_checked;
inline state()
- : m_checked()
+ : m_checked(true)
{}
};
public :
typedef state state_type;
- template <typename Operation, typename Rings, typename Ring, typename Turns, typename RobustPolicy>
+ template <typename Operation, typename Rings, typename Ring, typename Turns, typename RobustPolicy, typename Visitor>
static inline void apply(std::size_t size_at_start,
Rings& rings, Ring& ring,
- Turns& turns, Operation& operation,
- std::string const& ,
+ Turns& turns,
+ typename boost::range_value<Turns>::type const& turn,
+ Operation& operation,
+ traverse_error_type traverse_error,
Geometry1 const& geometry1,
Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
- state_type& state
+ state_type& state,
+ Visitor& visitor
)
{
+ visitor.visit_traverse_reject(turns, turn, operation, traverse_error);
+
state.m_good = false;
// Check self-intersections and throw exception if appropriate
diff --git a/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp b/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp
index dbf3770357..790819917c 100644
--- a/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp
+++ b/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp
@@ -22,7 +22,9 @@
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/util/range.hpp>
-#include <boost/geometry/views/detail/normalized_view.hpp>
+#include <boost/geometry/iterators/ever_circling_iterator.hpp>
+#include <boost/geometry/views/closeable_view.hpp>
+#include <boost/geometry/views/reversible_view.hpp>
namespace boost { namespace geometry
@@ -38,25 +40,33 @@ template <typename Range, bool Reverse, typename SegmentIdentifier, typename Poi
struct copy_segment_point_range
{
static inline bool apply(Range const& range,
- SegmentIdentifier const& seg_id, bool second,
+ SegmentIdentifier const& seg_id, int offset,
PointOut& point)
{
- detail::normalized_view<Range const> view(range);
+ typedef typename closeable_view
+ <
+ Range const,
+ closure<Range>::value
+ >::type cview_type;
- signed_size_type const n = boost::size(view);
- signed_size_type index = seg_id.segment_index;
- if (second)
+ typedef typename reversible_view
+ <
+ cview_type const,
+ Reverse ? iterate_reverse : iterate_forward
+ >::type rview_type;
+
+ cview_type cview(range);
+ rview_type view(cview);
+
+ typedef typename boost::range_iterator<rview_type>::type iterator;
+ geometry::ever_circling_iterator<iterator> it(boost::begin(view), boost::end(view),
+ boost::begin(view) + seg_id.segment_index, true);
+
+ for (signed_size_type i = 0; i < offset; ++i, ++it)
{
- index++;
- if (index >= n)
- {
- index = 0;
- }
}
- BOOST_GEOMETRY_ASSERT(index >= 0 && index < n);
-
- geometry::convert(*(boost::begin(view) + index), point);
+ geometry::convert(*it, point);
return true;
}
};
@@ -66,7 +76,7 @@ template <typename Polygon, bool Reverse, typename SegmentIdentifier, typename P
struct copy_segment_point_polygon
{
static inline bool apply(Polygon const& polygon,
- SegmentIdentifier const& seg_id, bool second,
+ SegmentIdentifier const& seg_id, int offset,
PointOut& point)
{
// Call ring-version with the right ring
@@ -81,7 +91,7 @@ struct copy_segment_point_polygon
seg_id.ring_index < 0
? geometry::exterior_ring(polygon)
: range::at(geometry::interior_rings(polygon), seg_id.ring_index),
- seg_id, second,
+ seg_id, offset,
point
);
}
@@ -92,11 +102,11 @@ template <typename Box, bool Reverse, typename SegmentIdentifier, typename Point
struct copy_segment_point_box
{
static inline bool apply(Box const& box,
- SegmentIdentifier const& seg_id, bool second,
+ SegmentIdentifier const& seg_id, int offset,
PointOut& point)
{
signed_size_type index = seg_id.segment_index;
- if (second)
+ for (int i = 0; i < offset; i++)
{
index++;
}
@@ -119,7 +129,7 @@ template
struct copy_segment_point_multi
{
static inline bool apply(MultiGeometry const& multi,
- SegmentIdentifier const& seg_id, bool second,
+ SegmentIdentifier const& seg_id, int offset,
PointOut& point)
{
@@ -130,7 +140,7 @@ struct copy_segment_point_multi
);
// Call the single-version
- return Policy::apply(range::at(multi, seg_id.multi_index), seg_id, second, point);
+ return Policy::apply(range::at(multi, seg_id.multi_index), seg_id, offset, point);
}
};
@@ -271,7 +281,7 @@ struct copy_segment_point
*/
template<bool Reverse, typename Geometry, typename SegmentIdentifier, typename PointOut>
inline bool copy_segment_point(Geometry const& geometry,
- SegmentIdentifier const& seg_id, bool second,
+ SegmentIdentifier const& seg_id, int offset,
PointOut& point_out)
{
concept::check<Geometry const>();
@@ -283,7 +293,7 @@ inline bool copy_segment_point(Geometry const& geometry,
Reverse,
SegmentIdentifier,
PointOut
- >::apply(geometry, seg_id, second, point_out);
+ >::apply(geometry, seg_id, offset, point_out);
}
@@ -300,7 +310,7 @@ template
typename PointOut
>
inline bool copy_segment_point(Geometry1 const& geometry1, Geometry2 const& geometry2,
- SegmentIdentifier const& seg_id, bool second,
+ SegmentIdentifier const& seg_id, int offset,
PointOut& point_out)
{
concept::check<Geometry1 const>();
@@ -317,7 +327,7 @@ inline bool copy_segment_point(Geometry1 const& geometry1, Geometry2 const& geom
Reverse1,
SegmentIdentifier,
PointOut
- >::apply(geometry1, seg_id, second, point_out);
+ >::apply(geometry1, seg_id, offset, point_out);
}
else if (seg_id.source_index == 1)
{
@@ -328,7 +338,7 @@ inline bool copy_segment_point(Geometry1 const& geometry1, Geometry2 const& geom
Reverse2,
SegmentIdentifier,
PointOut
- >::apply(geometry2, seg_id, second, point_out);
+ >::apply(geometry2, seg_id, offset, point_out);
}
// Exception?
return false;
@@ -354,10 +364,33 @@ inline bool copy_segment_points(Geometry1 const& geometry1, Geometry2 const& geo
concept::check<Geometry1 const>();
concept::check<Geometry2 const>();
- return copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, false, point1)
- && copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, true, point2);
+ return copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 0, point1)
+ && copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 1, point2);
}
+/*!
+ \brief Helper function, copies three points: two from the specified segment
+ (from, to) and the next one
+ \ingroup overlay
+ */
+template
+<
+ bool Reverse1, bool Reverse2,
+ typename Geometry1, typename Geometry2,
+ typename SegmentIdentifier,
+ typename PointOut
+>
+inline bool copy_segment_points(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ SegmentIdentifier const& seg_id,
+ PointOut& point1, PointOut& point2, PointOut& point3)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+
+ return copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 0, point1)
+ && copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 1, point2)
+ && copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 2, point3);
+}
diff --git a/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp b/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
index bc84286241..c79c9cf500 100644
--- a/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
+++ b/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
@@ -24,17 +24,20 @@
#include <boost/range.hpp>
+#include <boost/geometry/iterators/ever_circling_iterator.hpp>
#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>
#include <boost/geometry/algorithms/detail/overlay/handle_colocations.hpp>
-#include <boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp>
+#include <boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
+#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>
#include <boost/geometry/policies/robustness/robust_type.hpp>
#include <boost/geometry/strategies/side.hpp>
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
# include <boost/geometry/algorithms/detail/overlay/check_enrich.hpp>
#endif
+
namespace boost { namespace geometry
{
@@ -42,183 +45,6 @@ namespace boost { namespace geometry
namespace detail { namespace overlay
{
-// Wraps "turn_operation" from turn_info.hpp,
-// giving it extra information
-template <typename TurnOperation>
-struct indexed_turn_operation
-{
- typedef TurnOperation type;
-
- std::size_t turn_index;
- std::size_t operation_index;
- bool discarded;
- // use pointers to avoid copies, const& is not possible because of usage in vector
- segment_identifier const* other_seg_id; // segment id of other segment of intersection of two segments
- TurnOperation const* subject;
-
- inline indexed_turn_operation(std::size_t ti, std::size_t oi,
- TurnOperation const& sub,
- segment_identifier const& oid)
- : turn_index(ti)
- , operation_index(oi)
- , discarded(false)
- , other_seg_id(&oid)
- , subject(boost::addressof(sub))
- {}
-
-};
-
-template <typename IndexedTurnOperation>
-struct remove_discarded
-{
- inline bool operator()(IndexedTurnOperation const& operation) const
- {
- return operation.discarded;
- }
-};
-
-
-template
-<
- typename TurnPoints,
- typename Indexed,
- typename Geometry1, typename Geometry2,
- typename RobustPolicy,
- bool Reverse1, bool Reverse2,
- typename Strategy
->
-struct sort_on_segment_and_ratio
-{
- inline sort_on_segment_and_ratio(TurnPoints const& turn_points
- , Geometry1 const& geometry1
- , Geometry2 const& geometry2
- , RobustPolicy const& robust_policy
- , Strategy const& strategy
- , bool* clustered)
- : m_turn_points(turn_points)
- , m_geometry1(geometry1)
- , m_geometry2(geometry2)
- , m_robust_policy(robust_policy)
- , m_strategy(strategy)
- , m_clustered(clustered)
- {
- }
-
-private :
-
- TurnPoints const& m_turn_points;
- Geometry1 const& m_geometry1;
- Geometry2 const& m_geometry2;
- RobustPolicy const& m_robust_policy;
- Strategy const& m_strategy;
- mutable bool* m_clustered;
-
- typedef typename geometry::point_type<Geometry1>::type point_type;
-
- inline bool default_order(Indexed const& left, Indexed const& right) const
- {
- // We've nothing to sort on. Take the indexes
- return left.turn_index < right.turn_index;
- }
-
- inline bool consider_relative_order(Indexed const& left,
- Indexed const& right) const
- {
- point_type pi, pj, ri, rj, si, sj;
-
- geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
- left.subject->seg_id,
- pi, pj);
- geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
- *left.other_seg_id,
- ri, rj);
- geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
- *right.other_seg_id,
- si, sj);
-
- typedef typename strategy::side::services::default_strategy
- <
- typename cs_tag<point_type>::type
- >::type strategy;
-
- int const side_rj_p = strategy::apply(pi, pj, rj);
- int const side_sj_p = strategy::apply(pi, pj, sj);
-
- // Put the one turning left (1; right == -1) as last
- if (side_rj_p != side_sj_p)
- {
- return side_rj_p < side_sj_p;
- }
-
- int const side_sj_r = strategy::apply(ri, rj, sj);
- int const side_rj_s = strategy::apply(si, sj, rj);
-
- // If they both turn left: the most left as last
- // If they both turn right: this is not relevant, but take also here most left
- if (side_rj_s != side_sj_r)
- {
- return side_rj_s < side_sj_r;
- }
-
- return default_order(left, right);
- }
-
-public :
-
- // Note that left/right do NOT correspond to m_geometry1/m_geometry2
- // but to the "indexed_turn_operation"
- inline bool operator()(Indexed const& left, Indexed const& right) const
- {
- if (! (left.subject->seg_id == right.subject->seg_id))
- {
- return left.subject->seg_id < right.subject->seg_id;
- }
-
- // Both left and right are located on the SAME segment.
-
- if (! (left.subject->fraction == right.subject->fraction))
- {
- return left.subject->fraction < right.subject->fraction;
- }
-
-
- // First check "real" intersection (crosses)
- // -> distance zero due to precision, solve it by sorting
- if (m_turn_points[left.turn_index].method == method_crosses
- && m_turn_points[right.turn_index].method == method_crosses)
- {
- return consider_relative_order(left, right);
- }
-
- // If that is not the case, cluster it later on.
- // Indicate that this is necessary.
- *m_clustered = true;
-
- return default_order(left, right);
- }
-};
-
-
-template<typename Turns, typename Operations>
-inline void update_discarded(Turns& turn_points, Operations& operations)
-{
- // Vice-versa, set discarded to true for discarded operations;
- // AND set discarded points to true
- for (typename boost::range_iterator<Operations>::type it = boost::begin(operations);
- it != boost::end(operations);
- ++it)
- {
- if (turn_points[it->turn_index].discarded)
- {
- it->discarded = true;
- }
- else if (it->discarded)
- {
- turn_points[it->turn_index].discarded = true;
- }
- }
-}
-
// Sorts IP-s of this ring on segment-identifier, and if on same segment,
// on distance.
@@ -227,148 +53,88 @@ inline void update_discarded(Turns& turn_points, Operations& operations)
// (might be on another segment)
template
<
- typename IndexType,
bool Reverse1, bool Reverse2,
- typename Container,
- typename TurnPoints,
+ typename Operations,
+ typename Turns,
typename Geometry1, typename Geometry2,
typename RobustPolicy,
typename Strategy
>
-inline void enrich_sort(Container& operations,
- TurnPoints& turn_points,
+inline void enrich_sort(Operations& operations,
+ Turns const& turns,
operation_type for_operation,
- Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
Strategy const& strategy)
{
- typedef typename IndexType::type operations_type;
-
- bool clustered = false;
std::sort(boost::begin(operations),
- boost::end(operations),
- sort_on_segment_and_ratio
- <
- TurnPoints,
- IndexType,
- Geometry1, Geometry2,
- RobustPolicy,
- Reverse1, Reverse2,
- Strategy
- >(turn_points, geometry1, geometry2, robust_policy, strategy, &clustered));
-
- // DONT'T discard xx / (for union) ix / ii / (for intersection) ux / uu here
- // It would give way to "lonely" ui turn points, traveling all
- // the way round. See #105
-
- if (clustered)
- {
- typedef typename boost::range_iterator<Container>::type nc_iterator;
- nc_iterator it = boost::begin(operations);
- nc_iterator begin_cluster = boost::end(operations);
- for (nc_iterator prev = it++;
- it != boost::end(operations);
- prev = it++)
- {
- operations_type& prev_op = turn_points[prev->turn_index]
- .operations[prev->operation_index];
- operations_type& op = turn_points[it->turn_index]
- .operations[it->operation_index];
-
- if (prev_op.seg_id == op.seg_id
- && (turn_points[prev->turn_index].method != method_crosses
- || turn_points[it->turn_index].method != method_crosses)
- && prev_op.fraction == op.fraction)
- {
- if (begin_cluster == boost::end(operations))
- {
- begin_cluster = prev;
- }
- }
- else if (begin_cluster != boost::end(operations))
- {
- handle_cluster<IndexType, Reverse1, Reverse2>(begin_cluster, it, turn_points,
- for_operation, geometry1, geometry2, robust_policy, strategy);
- begin_cluster = boost::end(operations);
- }
- }
- if (begin_cluster != boost::end(operations))
- {
- handle_cluster<IndexType, Reverse1, Reverse2>(begin_cluster, it, turn_points,
- for_operation, geometry1, geometry2, robust_policy, strategy);
- }
- }
-
- update_discarded(turn_points, operations);
+ boost::end(operations),
+ less_by_segment_ratio
+ <
+ Turns,
+ typename boost::range_value<Operations>::type,
+ Geometry1, Geometry2,
+ RobustPolicy,
+ Reverse1, Reverse2
+ >(turns, for_operation, geometry1, geometry2, robust_policy));
}
-template
-<
- typename IndexType,
- typename Container,
- typename TurnPoints
->
-inline void enrich_discard(Container& operations, TurnPoints& turn_points)
-{
- update_discarded(turn_points, operations);
-
- // Then delete discarded operations from vector
- remove_discarded<IndexType> predicate;
- operations.erase(
- std::remove_if(boost::begin(operations),
- boost::end(operations),
- predicate),
- boost::end(operations));
-}
-
-template
-<
- typename IndexType,
- typename Container,
- typename TurnPoints,
- typename Geometry1,
- typename Geometry2,
- typename Strategy
->
-inline void enrich_assign(Container& operations,
- TurnPoints& turn_points,
- operation_type ,
- Geometry1 const& , Geometry2 const& ,
- Strategy const& )
+template <typename Operations, typename Turns>
+inline void enrich_assign(Operations& operations, Turns& turns)
{
- typedef typename IndexType::type operations_type;
- typedef typename boost::range_iterator<Container const>::type iterator_type;
+ typedef typename boost::range_value<Turns>::type turn_type;
+ typedef typename turn_type::turn_operation_type op_type;
+ typedef typename boost::range_iterator<Operations>::type iterator_type;
if (operations.size() > 0)
{
// Assign travel-to-vertex/ip index for each turning point.
- // Because IP's are circular, PREV starts at the very last one,
- // being assigned from the first one.
- // "next ip on same segment" should not be considered circular.
- bool first = true;
- iterator_type it = boost::begin(operations);
- for (iterator_type prev = it + (boost::size(operations) - 1);
- it != boost::end(operations);
- prev = it++)
+ // Iterator "next" is circular
+
+ geometry::ever_circling_range_iterator<Operations const> next(operations);
+ ++next;
+
+ for (iterator_type it = boost::begin(operations);
+ it != boost::end(operations); ++it)
{
- operations_type& prev_op
- = turn_points[prev->turn_index].operations[prev->operation_index];
- operations_type& op
- = turn_points[it->turn_index].operations[it->operation_index];
-
- prev_op.enriched.travels_to_ip_index
- = static_cast<signed_size_type>(it->turn_index);
- prev_op.enriched.travels_to_vertex_index
- = it->subject->seg_id.segment_index;
-
- if (! first
- && prev_op.seg_id.segment_index == op.seg_id.segment_index)
+ turn_type& turn = turns[it->turn_index];
+ op_type& op = turn.operations[it->operation_index];
+
+ // Normal behaviour: next should point at next turn:
+ if (it->turn_index == next->turn_index)
+ {
+ ++next;
+ }
+
+ // Cluster behaviour: next should point after cluster, unless
+ // their seg_ids are not the same
+ while (turn.cluster_id != -1
+ && it->turn_index != next->turn_index
+ && turn.cluster_id == turns[next->turn_index].cluster_id
+ && op.seg_id == turns[next->turn_index].operations[next->operation_index].seg_id)
+ {
+ ++next;
+ }
+
+ turn_type const& next_turn = turns[next->turn_index];
+ op_type const& next_op = next_turn.operations[next->operation_index];
+
+ op.enriched.travels_to_ip_index
+ = static_cast<signed_size_type>(next->turn_index);
+ op.enriched.travels_to_vertex_index
+ = next->subject->seg_id.segment_index;
+
+ if (op.seg_id.segment_index == next_op.seg_id.segment_index
+ && op.fraction < next_op.fraction)
{
- prev_op.enriched.next_ip_index = static_cast<signed_size_type>(it->turn_index);
+ // Next turn is located further on same segment
+ // assign next_ip_index
+ // (this is one not circular therefore fraction is considered)
+ op.enriched.next_ip_index = static_cast<signed_size_type>(next->turn_index);
}
- first = false;
}
}
@@ -379,20 +145,20 @@ inline void enrich_assign(Container& operations,
it != boost::end(operations);
++it)
{
- operations_type& op = turn_points[it->turn_index]
+ op_type& op = turns[it->turn_index]
.operations[it->operation_index];
std::cout << it->turn_index
- << " meth: " << method_char(turn_points[it->turn_index].method)
- << " seg: " << op.seg_id
- << " dst: " << op.fraction // needs define
- << " op: " << operation_char(turn_points[it->turn_index].operations[0].operation)
- << operation_char(turn_points[it->turn_index].operations[1].operation)
- << " dsc: " << (turn_points[it->turn_index].discarded ? "T" : "F")
- << " ->vtx " << op.enriched.travels_to_vertex_index
- << " ->ip " << op.enriched.travels_to_ip_index
- << " ->nxt ip " << op.enriched.next_ip_index
- //<< " vis: " << visited_char(op.visited)
+ << " cl=" << turns[it->turn_index].cluster_id
+ << " meth=" << method_char(turns[it->turn_index].method)
+ << " seg=" << op.seg_id
+ << " dst=" << op.fraction // needs define
+ << " op=" << operation_char(turns[it->turn_index].operations[0].operation)
+ << operation_char(turns[it->turn_index].operations[1].operation)
+ << " (" << operation_char(op.operation) << ")"
+ << " nxt=" << op.enriched.next_ip_index
+ << " / " << op.enriched.travels_to_ip_index
+ << " [vx " << op.enriched.travels_to_vertex_index << "]"
<< std::endl;
;
}
@@ -403,43 +169,57 @@ inline void enrich_assign(Container& operations,
}
-template <typename IndexedType, typename TurnPoints, typename MappedVector>
-inline void create_map(TurnPoints const& turn_points, MappedVector& mapped_vector)
+template <typename Turns, typename MappedVector>
+inline void create_map(Turns const& turns,
+ detail::overlay::operation_type for_operation,
+ MappedVector& mapped_vector)
{
- typedef typename boost::range_value<TurnPoints>::type turn_point_type;
- typedef typename turn_point_type::container_type container_type;
+ typedef typename boost::range_value<Turns>::type turn_type;
+ typedef typename turn_type::container_type container_type;
+ typedef typename MappedVector::mapped_type mapped_type;
+ typedef typename boost::range_value<mapped_type>::type indexed_type;
std::size_t index = 0;
- for (typename boost::range_iterator<TurnPoints const>::type
- it = boost::begin(turn_points);
- it != boost::end(turn_points);
+ for (typename boost::range_iterator<Turns const>::type
+ it = boost::begin(turns);
+ it != boost::end(turns);
++it, ++index)
{
- // Add operations on this ring, but skip discarded ones
- if (! it->discarded)
+ // Add all (non discarded) operations on this ring
+ // Blocked operations or uu on clusters (for intersection)
+ // should be included, to block potential paths in clusters
+ turn_type const& turn = *it;
+ if (turn.discarded)
{
- std::size_t op_index = 0;
- for (typename boost::range_iterator<container_type const>::type
- op_it = boost::begin(it->operations);
- op_it != boost::end(it->operations);
- ++op_it, ++op_index)
- {
- // We should NOT skip blocked operations here
- // because they can be relevant for "the other side"
- // NOT if (op_it->operation != operation_blocked)
-
- ring_identifier ring_id
- (
- op_it->seg_id.source_index,
- op_it->seg_id.multi_index,
- op_it->seg_id.ring_index
- );
- mapped_vector[ring_id].push_back
- (
- IndexedType(index, op_index, *op_it,
- it->operations[1 - op_index].seg_id)
- );
- }
+ continue;
+ }
+
+ if (for_operation == operation_intersection
+ && turn.cluster_id == -1
+ && turn.both(operation_union))
+ {
+ // Only include uu turns if part of cluster (to block potential paths),
+ // otherwise they can block possibly viable paths
+ continue;
+ }
+
+ std::size_t op_index = 0;
+ for (typename boost::range_iterator<container_type const>::type
+ op_it = boost::begin(turn.operations);
+ op_it != boost::end(turn.operations);
+ ++op_it, ++op_index)
+ {
+ ring_identifier const ring_id
+ (
+ op_it->seg_id.source_index,
+ op_it->seg_id.multi_index,
+ op_it->seg_id.ring_index
+ );
+ mapped_vector[ring_id].push_back
+ (
+ indexed_type(index, op_index, *op_it,
+ it->operations[1 - op_index].seg_id)
+ );
}
}
}
@@ -453,12 +233,12 @@ inline void create_map(TurnPoints const& turn_points, MappedVector& mapped_vecto
/*!
\brief All intersection points are enriched with successor information
\ingroup overlay
-\tparam TurnPoints type of intersection container
+\tparam Turns type of intersection container
(e.g. vector of "intersection/turn point"'s)
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam Strategy side strategy type
-\param turn_points container containing intersectionpoints
+\param turns container containing intersectionpoints
\param for_operation operation_type (union or intersection)
\param geometry1 \param_geometry
\param geometry2 \param_geometry
@@ -469,22 +249,24 @@ template
<
bool Reverse1, bool Reverse2,
overlay_type OverlayType,
- typename TurnPoints,
+ typename Turns,
+ typename Clusters,
typename Geometry1, typename Geometry2,
typename RobustPolicy,
typename Strategy
>
-inline void enrich_intersection_points(TurnPoints& turn_points,
+inline void enrich_intersection_points(Turns& turns,
+ Clusters& clusters,
detail::overlay::operation_type for_operation,
Geometry1 const& geometry1, Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
Strategy const& strategy)
{
- typedef typename boost::range_value<TurnPoints>::type turn_point_type;
- typedef typename turn_point_type::turn_operation_type turn_operation_type;
+ typedef typename boost::range_value<Turns>::type turn_type;
+ typedef typename turn_type::turn_operation_type op_type;
typedef detail::overlay::indexed_turn_operation
<
- turn_operation_type
+ op_type
> indexed_turn_operation;
typedef std::map
@@ -493,51 +275,27 @@ inline void enrich_intersection_points(TurnPoints& turn_points,
std::vector<indexed_turn_operation>
> mapped_vector_type;
- // Iterate through turns and discard uu
- // and check if there are possible colocations
- bool check_colocations = false;
- for (typename boost::range_iterator<TurnPoints>::type
- it = boost::begin(turn_points);
- it != boost::end(turn_points);
+ bool const has_colocations
+ = detail::overlay::handle_colocations<Reverse1, Reverse2>(turns,
+ clusters, geometry1, geometry2);
+
+ // Discard none turns, if any
+ for (typename boost::range_iterator<Turns>::type
+ it = boost::begin(turns);
+ it != boost::end(turns);
++it)
{
- if (it->both(detail::overlay::operation_union))
- {
- // Discard (necessary for a.o. #76). With uu, at all points there
- // is the risk that rings are being traversed twice or more.
- // Without uu, all rings having only uu will be untouched
- // and gathered by assemble
- it->discarded = true;
- check_colocations = true;
- }
- else if (it->combination(detail::overlay::operation_union,
- detail::overlay::operation_blocked))
- {
- check_colocations = true;
- }
- else if (OverlayType == overlay_difference
- && it->both(detail::overlay::operation_intersection))
- {
- // For difference operation (u/u -> i/i)
- check_colocations = true;
- }
- else if (it->both(detail::overlay::operation_none))
+ if (it->both(detail::overlay::operation_none))
{
it->discarded = true;
}
}
- if (check_colocations)
- {
- detail::overlay::handle_colocations<OverlayType>(turn_points);
- }
-
// Create a map of vectors of indexed operation-types to be able
// to sort intersection points PER RING
mapped_vector_type mapped_vector;
- detail::overlay::create_map<indexed_turn_operation>(turn_points, mapped_vector);
-
+ detail::overlay::create_map(turns, for_operation, mapped_vector);
// No const-iterator; contents of mapped copy is temporary,
// and changed by enrich
@@ -550,8 +308,10 @@ inline void enrich_intersection_points(TurnPoints& turn_points,
std::cout << "ENRICH-sort Ring "
<< mit->first << std::endl;
#endif
- detail::overlay::enrich_sort<indexed_turn_operation, Reverse1, Reverse2>(mit->second, turn_points, for_operation,
- geometry1, geometry2, robust_policy, strategy);
+ detail::overlay::enrich_sort<Reverse1, Reverse2>(
+ mit->second, turns, for_operation,
+ geometry1, geometry2,
+ robust_policy, strategy);
}
for (typename mapped_vector_type::iterator mit
@@ -560,27 +320,20 @@ inline void enrich_intersection_points(TurnPoints& turn_points,
++mit)
{
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
- std::cout << "ENRICH-discard Ring "
+ std::cout << "ENRICH-assign Ring "
<< mit->first << std::endl;
#endif
- detail::overlay::enrich_discard<indexed_turn_operation>(mit->second, turn_points);
+ detail::overlay::enrich_assign(mit->second, turns);
}
- for (typename mapped_vector_type::iterator mit
- = mapped_vector.begin();
- mit != mapped_vector.end();
- ++mit)
+ if (has_colocations)
{
-#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
- std::cout << "ENRICH-assign Ring "
- << mit->first << std::endl;
-#endif
- detail::overlay::enrich_assign<indexed_turn_operation>(mit->second, turn_points, for_operation,
- geometry1, geometry2, strategy);
+ detail::overlay::assign_startable_in_clusters<Reverse1, Reverse2>(
+ clusters, turns, for_operation, geometry1, geometry2);
}
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
- //detail::overlay::check_graph(turn_points, for_operation);
+ //detail::overlay::check_graph(turns, for_operation);
#endif
}
diff --git a/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp b/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp
index 5964f3ba44..f5c5cc6a2e 100644
--- a/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp
+++ b/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp
@@ -32,6 +32,9 @@ struct enrichment_info
: travels_to_vertex_index(-1)
, travels_to_ip_index(-1)
, next_ip_index(-1)
+ , startable(true)
+ , count_left(0)
+ , count_right(0)
{}
// vertex to which is free travel after this IP,
@@ -44,6 +47,12 @@ struct enrichment_info
// index of next IP on this segment, -1 if there is no one
signed_size_type next_ip_index;
+
+ bool startable; // Can be used to start in traverse
+
+ // Counts if polygons left/right of this operation
+ std::size_t count_left;
+ std::size_t count_right;
};
diff --git a/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp b/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
index 6f332ddff2..ad75127fab 100644
--- a/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
+++ b/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
@@ -16,6 +16,7 @@
#include <boost/range.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
+#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
@@ -34,6 +35,29 @@ namespace boost { namespace geometry
namespace detail { namespace overlay
{
+template <typename SegmentRatio>
+struct segment_fraction
+{
+ segment_identifier seg_id;
+ SegmentRatio fraction;
+
+ segment_fraction(segment_identifier const& id, SegmentRatio const& fr)
+ : seg_id(id)
+ , fraction(fr)
+ {}
+
+ segment_fraction()
+ {}
+
+ bool operator<(segment_fraction<SegmentRatio> const& other) const
+ {
+ return seg_id == other.seg_id
+ ? fraction < other.fraction
+ : seg_id < other.seg_id;
+ }
+
+};
+
struct turn_operation_index
{
turn_operation_index(signed_size_type ti = -1,
@@ -43,22 +67,22 @@ struct turn_operation_index
{}
signed_size_type turn_index;
- signed_size_type op_index; // basically only 0,1
+ signed_size_type op_index; // only 0,1
};
-template <typename TurnPoints>
+template <typename Turns>
struct less_by_fraction_and_type
{
- inline less_by_fraction_and_type(TurnPoints const& turn_points)
- : m_turns(turn_points)
+ inline less_by_fraction_and_type(Turns const& turns)
+ : m_turns(turns)
{
}
inline bool operator()(turn_operation_index const& left,
turn_operation_index const& right) const
{
- typedef typename boost::range_value<TurnPoints>::type turn_type;
+ typedef typename boost::range_value<Turns>::type turn_type;
typedef typename turn_type::turn_operation_type turn_operation_type;
turn_type const& left_turn = m_turns[left.turn_index];
@@ -74,6 +98,29 @@ struct less_by_fraction_and_type
return left_op.fraction < right_op.fraction;
}
+ // Order xx first - used to discard any following colocated turn
+ bool const left_both_xx = left_turn.both(operation_blocked);
+ bool const right_both_xx = right_turn.both(operation_blocked);
+ if (left_both_xx && ! right_both_xx)
+ {
+ return true;
+ }
+ if (! left_both_xx && right_both_xx)
+ {
+ return false;
+ }
+
+ bool const left_both_uu = left_turn.both(operation_union);
+ bool const right_both_uu = right_turn.both(operation_union);
+ if (left_both_uu && ! right_both_uu)
+ {
+ return true;
+ }
+ if (! left_both_uu && right_both_uu)
+ {
+ return false;
+ }
+
turn_operation_type const& left_other_op
= left_turn.operations[1 - left.op_index];
@@ -86,88 +133,219 @@ struct less_by_fraction_and_type
}
private:
- TurnPoints const& m_turns;
+ Turns const& m_turns;
};
-template <overlay_type OverlayType, typename TurnPoints, typename OperationVector>
-inline void handle_colocation_cluster(TurnPoints& turn_points,
- segment_identifier const& current_ring_seg_id,
- OperationVector const& vec)
+template <typename Operation, typename ClusterPerSegment>
+inline signed_size_type get_cluster_id(Operation const& op, ClusterPerSegment const& cluster_per_segment)
+{
+ typedef typename ClusterPerSegment::key_type segment_fraction_type;
+
+ segment_fraction_type seg_frac(op.seg_id, op.fraction);
+ typename ClusterPerSegment::const_iterator it
+ = cluster_per_segment.find(seg_frac);
+
+ if (it == cluster_per_segment.end())
+ {
+ return -1;
+ }
+ return it->second;
+}
+
+template <typename Operation, typename ClusterPerSegment>
+inline void add_cluster_id(Operation const& op,
+ ClusterPerSegment& cluster_per_segment, signed_size_type id)
{
- typedef typename boost::range_value<TurnPoints>::type turn_type;
+ typedef typename ClusterPerSegment::key_type segment_fraction_type;
+
+ segment_fraction_type seg_frac(op.seg_id, op.fraction);
+
+ cluster_per_segment[seg_frac] = id;
+}
+
+template <typename Turn, typename ClusterPerSegment>
+inline signed_size_type add_turn_to_cluster(Turn const& turn,
+ ClusterPerSegment& cluster_per_segment, signed_size_type& cluster_id)
+{
+ signed_size_type cid0 = get_cluster_id(turn.operations[0], cluster_per_segment);
+ signed_size_type cid1 = get_cluster_id(turn.operations[1], cluster_per_segment);
+
+ if (cid0 == -1 && cid1 == -1)
+ {
+ ++cluster_id;
+ add_cluster_id(turn.operations[0], cluster_per_segment, cluster_id);
+ add_cluster_id(turn.operations[1], cluster_per_segment, cluster_id);
+ return cluster_id;
+ }
+ else if (cid0 == -1 && cid1 != -1)
+ {
+ add_cluster_id(turn.operations[0], cluster_per_segment, cid1);
+ return cid1;
+ }
+ else if (cid0 != -1 && cid1 == -1)
+ {
+ add_cluster_id(turn.operations[1], cluster_per_segment, cid0);
+ return cid0;
+ }
+ else if (cid0 == cid1)
+ {
+ // Both already added to same cluster, no action
+ return cid0;
+ }
+
+ // Both operations.seg_id/fraction were already part of any cluster, and
+ // these clusters are not the same. Merge of two clusters is necessary
+ std::cout << " TODO: merge " << cid0 << " and " << cid1 << std::endl;
+ return cid0;
+}
+
+template
+<
+ bool Reverse1, bool Reverse2,
+ typename Turns,
+ typename ClusterPerSegment,
+ typename Operations,
+ typename Geometry1,
+ typename Geometry2
+>
+inline void handle_colocation_cluster(Turns& turns,
+ signed_size_type& cluster_id,
+ ClusterPerSegment& cluster_per_segment,
+ Operations const& operations,
+ Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ typedef typename boost::range_value<Turns>::type turn_type;
typedef typename turn_type::turn_operation_type turn_operation_type;
- std::vector<turn_operation_index>::const_iterator vit = vec.begin();
+ std::vector<turn_operation_index>::const_iterator vit = operations.begin();
- turn_type cluster_turn = turn_points[vit->turn_index];
- turn_operation_type cluster_op
- = cluster_turn.operations[vit->op_index];
- segment_identifier cluster_other_id
- = cluster_turn.operations[1 - vit->op_index].seg_id;
- bool const discard_colocated
- = cluster_turn.both(operation_union)
- || cluster_turn.combination(operation_blocked, operation_union);
+ turn_operation_index ref_toi = *vit;
+ signed_size_type ref_id = -1;
- for (++vit; vit != vec.end(); ++vit)
+ for (++vit; vit != operations.end(); ++vit)
{
+ turn_type& ref_turn = turns[ref_toi.turn_index];
+ turn_operation_type const& ref_op
+ = ref_turn.operations[ref_toi.op_index];
+
turn_operation_index const& toi = *vit;
- turn_type& turn = turn_points[toi.turn_index];
+ turn_type& turn = turns[toi.turn_index];
turn_operation_type const& op = turn.operations[toi.op_index];
- segment_identifier const& other_id
- = turn.operations[1 - toi.op_index].seg_id;
- if (cluster_op.fraction == op.fraction)
+ BOOST_ASSERT(ref_op.seg_id == op.seg_id);
+
+ if (ref_op.fraction == op.fraction)
{
- // Two turns of current ring with same source are colocated,
- // one is from exterior ring, one from interior ring
- bool const colocated_ext_int
- = cluster_other_id.multi_index == other_id.multi_index
- && cluster_other_id.ring_index == -1
- && other_id.ring_index >= 0;
-
- // Turn of current interior ring with other interior ring
- bool const touch_int_int
- = current_ring_seg_id.ring_index >= 0
- && other_id.ring_index >= 0;
-
- if (discard_colocated && colocated_ext_int)
+ turn_operation_type const& other_op = turn.operations[1 - toi.op_index];
+
+ if (ref_id == -1)
{
- // If the two turns on this same segment are a
- // colocation with two different segments on the
- // other geometry, of the same polygon but with
- // the outer (u/u or u/x) and the inner ring (non u/u),
- // that turn with inner ring should be discarded
- turn.discarded = true;
- turn.colocated = true;
+ ref_id = add_turn_to_cluster(ref_turn, cluster_per_segment, cluster_id);
}
- else if (cluster_turn.colocated
- && touch_int_int
- && turn.both(operation_intersection))
+ BOOST_ASSERT(ref_id != -1);
+
+ // ref_turn (both operations) are already added to cluster,
+ // so also "op" is already added to cluster,
+ // We only need to add other_op
+ signed_size_type id = get_cluster_id(other_op, cluster_per_segment);
+ if (id != -1 && id != ref_id)
{
- // Two holes touch each other at a point where the
- // exterior ring also touches
- turn.discarded = true;
- turn.colocated = true;
}
- else if (OverlayType == overlay_difference
- && turn.both(operation_intersection)
- && colocated_ext_int)
+ else if (id == -1)
+ {
+ // Add to same cluster
+ add_cluster_id(other_op, cluster_per_segment, ref_id);
+ id = ref_id;
+ }
+
+ // In case of colocated xx turns, all other turns may NOT be
+ // followed at all. xx cannot be discarded (otherwise colocated
+ // turns are followed).
+ if (ref_turn.both(operation_blocked))
{
- // For difference (polygon inside out) we need to
- // discard i/i instead, in case of colocations
turn.discarded = true;
- turn.colocated = true;
+ // We can either set or not set colocated because it is not effective on blocked turns
}
}
else
{
// Not on same fraction on this segment
- // assign for next potential cluster
- cluster_turn = turn;
- cluster_op = op;
- cluster_other_id = other_id;
+ // assign for next
+ ref_toi = toi;
+ ref_id = -1;
}
+ }
+}
+
+template
+<
+ typename Turns,
+ typename Clusters,
+ typename ClusterPerSegment
+>
+inline void assign_cluster_to_turns(Turns& turns,
+ Clusters& clusters,
+ ClusterPerSegment const& cluster_per_segment)
+{
+ typedef typename boost::range_value<Turns>::type turn_type;
+ typedef typename turn_type::turn_operation_type turn_operation_type;
+ typedef typename ClusterPerSegment::key_type segment_fraction_type;
+ signed_size_type turn_index = 0;
+ for (typename boost::range_iterator<Turns>::type it = turns.begin();
+ it != turns.end(); ++it, ++turn_index)
+ {
+ turn_type& turn = *it;
+
+ if (turn.discarded)
+ {
+ // They were processed (to create proper map) but will not be added
+ // This might leave a cluster with only 1 turn, which will be fixed
+ // afterwards
+ continue;
+ }
+
+ for (int i = 0; i < 2; i++)
+ {
+ turn_operation_type const& op = turn.operations[i];
+ segment_fraction_type seg_frac(op.seg_id, op.fraction);
+ typename ClusterPerSegment::const_iterator it = cluster_per_segment.find(seg_frac);
+ if (it != cluster_per_segment.end())
+ {
+ if (turn.cluster_id != -1
+ && turn.cluster_id != it->second)
+ {
+ std::cout << " CONFLICT " << std::endl;
+ }
+ turn.cluster_id = it->second;
+ clusters[turn.cluster_id].insert(turn_index);
+ }
+ }
+ }
+}
+
+template
+<
+ typename Turns,
+ typename Clusters
+>
+inline void remove_clusters(Turns& turns, Clusters& clusters)
+{
+ typename Clusters::iterator it = clusters.begin();
+ while (it != clusters.end())
+ {
+ // Hold iterator and increase. We can erase cit, this keeps the
+ // iterator valid (cf The standard associative-container erase idiom)
+ typename Clusters::iterator current_it = it;
+ ++it;
+
+ std::set<signed_size_type> const& turn_indices = current_it->second;
+ if (turn_indices.size() == 1)
+ {
+ signed_size_type turn_index = *turn_indices.begin();
+ turns[turn_index].cluster_id = -1;
+ clusters.erase(current_it);
+ }
}
}
@@ -179,8 +357,16 @@ inline void handle_colocation_cluster(TurnPoints& turn_points,
// This function can be extended to replace handle_tangencies: at each
// colocation incoming and outgoing vectors should be inspected
-template <overlay_type OverlayType, typename TurnPoints>
-inline void handle_colocations(TurnPoints& turn_points)
+template
+<
+ bool Reverse1, bool Reverse2,
+ typename Turns,
+ typename Clusters,
+ typename Geometry1,
+ typename Geometry2
+>
+inline bool handle_colocations(Turns& turns, Clusters& clusters,
+ Geometry1 const& geometry1, Geometry2 const& geometry2)
{
typedef std::map
<
@@ -195,9 +381,9 @@ inline void handle_colocations(TurnPoints& turn_points)
map_type map;
int index = 0;
- for (typename boost::range_iterator<TurnPoints>::type
- it = boost::begin(turn_points);
- it != boost::end(turn_points);
+ for (typename boost::range_iterator<Turns>::type
+ it = boost::begin(turns);
+ it != boost::end(turns);
++it, ++index)
{
map[it->operations[0].seg_id].push_back(turn_operation_index(index, 0));
@@ -220,27 +406,43 @@ inline void handle_colocations(TurnPoints& turn_points)
if (! colocations)
{
- return;
+ return false;
}
// Sort all vectors, per same segment
- less_by_fraction_and_type<TurnPoints> less(turn_points);
+ less_by_fraction_and_type<Turns> less(turns);
for (typename map_type::iterator it = map.begin();
it != map.end(); ++it)
{
std::sort(it->second.begin(), it->second.end(), less);
}
+ typedef typename boost::range_value<Turns>::type turn_type;
+ typedef typename turn_type::segment_ratio_type segment_ratio_type;
+
+ typedef std::map
+ <
+ segment_fraction<segment_ratio_type>,
+ signed_size_type
+ > cluster_per_segment_type;
+
+ cluster_per_segment_type cluster_per_segment;
+ signed_size_type cluster_id = 0;
+
for (typename map_type::const_iterator it = map.begin();
it != map.end(); ++it)
{
- if (it->second.size() > 1)
+ if (it->second.size() > 1u)
{
- handle_colocation_cluster<OverlayType>(turn_points,
- it->first, it->second);
+ handle_colocation_cluster<Reverse1, Reverse2>(turns, cluster_id,
+ cluster_per_segment, it->second,
+ geometry1, geometry2);
}
}
+ assign_cluster_to_turns(turns, clusters, cluster_per_segment);
+ remove_clusters(turns, clusters);
+
#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_COLOCATIONS)
std::cout << "*** Colocations " << map.size() << std::endl;
for (typename map_type::const_iterator it = map.begin();
@@ -251,21 +453,123 @@ inline void handle_colocations(TurnPoints& turn_points)
= it->second.begin(); vit != it->second.end(); ++vit)
{
turn_operation_index const& toi = *vit;
- std::cout << geometry::wkt(turn_points[toi.turn_index].point)
+ std::cout << geometry::wkt(turns[toi.turn_index].point)
<< std::boolalpha
- << " discarded=" << turn_points[toi.turn_index].discarded
- << " colocated=" << turn_points[toi.turn_index].colocated
- << " " << operation_char(turn_points[toi.turn_index].operations[0].operation)
- << " " << turn_points[toi.turn_index].operations[0].seg_id
- << " " << turn_points[toi.turn_index].operations[0].fraction
- << " // " << operation_char(turn_points[toi.turn_index].operations[1].operation)
- << " " << turn_points[toi.turn_index].operations[1].seg_id
- << " " << turn_points[toi.turn_index].operations[1].fraction
+ << " discarded=" << turns[toi.turn_index].discarded
+ << " colocated=" << turns[toi.turn_index].colocated
+ << " " << operation_char(turns[toi.turn_index].operations[0].operation)
+ << " " << turns[toi.turn_index].operations[0].seg_id
+ << " " << turns[toi.turn_index].operations[0].fraction
+ << " // " << operation_char(turns[toi.turn_index].operations[1].operation)
+ << " " << turns[toi.turn_index].operations[1].seg_id
+ << " " << turns[toi.turn_index].operations[1].fraction
<< std::endl;
}
}
#endif // DEBUG
+ return true;
+}
+
+
+struct is_turn_index
+{
+ is_turn_index(signed_size_type index)
+ : m_index(index)
+ {}
+
+ template <typename Indexed>
+ inline bool operator()(Indexed const& indexed) const
+ {
+ // Indexed is a indexed_turn_operation<Operation>
+ return indexed.turn_index == m_index;
+ }
+
+ std::size_t m_index;
+};
+
+
+template
+<
+ bool Reverse1, bool Reverse2,
+ typename Turns,
+ typename Clusters,
+ typename Geometry1,
+ typename Geometry2
+>
+inline void assign_startable_in_clusters(Clusters& clusters, Turns& turns,
+ operation_type for_operation,
+ Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ typedef typename boost::range_value<Turns>::type turn_type;
+ typedef typename turn_type::point_type point_type;
+ typedef typename turn_type::turn_operation_type turn_operation_type;
+
+ // Define sorter, sorting counter-clockwise such that polygons are on the
+ // right side
+ typedef sort_by_side::side_sorter
+ <
+ Reverse1, Reverse2, point_type, std::less<int>
+ > sbs_type;
+
+ for (typename Clusters::iterator mit = clusters.begin();
+ mit != clusters.end(); ++mit)
+ {
+ std::set<signed_size_type> const& ids = mit->second;
+ if (ids.empty())
+ {
+ continue;
+ }
+
+ sbs_type sbs;
+ point_type turn_point; // should be all the same for all turns in cluster
+
+ bool first = true;
+ for (typename std::set<signed_size_type>::const_iterator sit = ids.begin();
+ sit != ids.end(); ++sit)
+ {
+ signed_size_type turn_index = *sit;
+ turn_type const& turn = turns[turn_index];
+ if (first)
+ {
+ turn_point = turn.point;
+ }
+ for (int i = 0; i < 2; i++)
+ {
+ turn_operation_type const& op = turn.operations[i];
+ sbs.add(op, turn_index, i, geometry1, geometry2, first);
+ first = false;
+ }
+ }
+ sbs.apply(turn_point);
+
+ sbs.find_open();
+
+ // Unset the startable flag for all 'closed' spaces
+ for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
+ {
+ const typename sbs_type::rp& ranked = sbs.m_ranked_points[i];
+ turn_type& turn = turns[ranked.turn_index];
+ turn_operation_type& op = turn.operations[ranked.op_index];
+
+ if (ranked.index != sort_by_side::index_to)
+ {
+ continue;
+ }
+
+ op.enriched.count_left = ranked.left_count;
+ op.enriched.count_right = ranked.right_count;
+
+ if ((for_operation == operation_union
+ && ranked.left_count != 0)
+ || (for_operation == operation_intersection
+ && ranked.right_count != 2))
+ {
+ op.enriched.startable = false;
+ }
+ }
+
+ }
}
diff --git a/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp b/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp
deleted file mode 100644
index 277a223d47..0000000000
--- a/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp
+++ /dev/null
@@ -1,786 +0,0 @@
-// Boost.Geometry (aka GGL, Generic Geometry Library)
-
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-
-// Use, modification and distribution is subject to the Boost Software License,
-// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_TANGENCIES_HPP
-#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_TANGENCIES_HPP
-
-#include <algorithm>
-
-#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
-#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>
-#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
-#include <boost/geometry/algorithms/detail/recalculate.hpp>
-
-#include <boost/geometry/policies/robustness/robust_point_type.hpp>
-#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
-#include <boost/geometry/policies/robustness/robust_type.hpp>
-
-#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_TANGENCIES)
-#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
-#endif
-
-#include <boost/geometry/geometries/point.hpp>
-#include <boost/geometry/geometries/segment.hpp>
-
-
-// TODO: the approach below should be completely replaced by the new
-// get_left_turns, to keep the outgoing vector which has open space one of its
-// sides.
-
-
-namespace boost { namespace geometry
-{
-
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail { namespace overlay
-{
-
-
-template
-<
- typename TurnPoints,
- typename Indexed,
- typename Geometry1, typename Geometry2,
- typename RobustPolicy,
- bool Reverse1, bool Reverse2,
- typename Strategy
->
-struct sort_in_cluster
-{
- inline sort_in_cluster(TurnPoints const& turn_points
- , Geometry1 const& geometry1
- , Geometry2 const& geometry2
- , RobustPolicy const& robust_policy
- , Strategy const& strategy)
- : m_turn_points(turn_points)
- , m_geometry1(geometry1)
- , m_geometry2(geometry2)
- , m_rescale_policy(robust_policy)
- , m_strategy(strategy)
- {}
-
-private :
-
- TurnPoints const& m_turn_points;
- Geometry1 const& m_geometry1;
- Geometry2 const& m_geometry2;
- RobustPolicy const& m_rescale_policy;
- Strategy const& m_strategy;
-
- typedef typename Indexed::type turn_operation_type;
- typedef typename geometry::point_type<Geometry1>::type point_type;
-
- typedef typename geometry::robust_point_type
- <
- point_type,
- RobustPolicy
- >::type robust_point_type;
-
- inline bool default_order(Indexed const& left, Indexed const& right) const
- {
- // We've nothing to sort on. Take the indexes
- return left.turn_index < right.turn_index;
- }
-
- // Still necessary in some situations,
- // for example #case_102_multi, #case_107_multi, #case_recursive_boxes_3
- inline void get_situation_map(Indexed const& left, Indexed const& right,
- robust_point_type& pi_rob, robust_point_type& pj_rob,
- robust_point_type& ri_rob, robust_point_type& rj_rob,
- robust_point_type& si_rob, robust_point_type& sj_rob) const
- {
- point_type pi, pj, ri, rj, si, sj;
-
- geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
- left.subject->seg_id,
- pi, pj);
- geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
- *left.other_seg_id,
- ri, rj);
- geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
- *right.other_seg_id,
- si, sj);
-
- geometry::recalculate(pi_rob, pi, m_rescale_policy);
- geometry::recalculate(pj_rob, pj, m_rescale_policy);
- geometry::recalculate(ri_rob, ri, m_rescale_policy);
- geometry::recalculate(rj_rob, rj, m_rescale_policy);
- geometry::recalculate(si_rob, si, m_rescale_policy);
- geometry::recalculate(sj_rob, sj, m_rescale_policy);
- }
-
-#if BOOST_GEOMETRY_HANDLE_TANGENCIES_WITH_OVERLAP_INFO
- // This method was still called but did no effect whatsoever on the results,
- // with or without robustness-rescaling.
- // Probable cause: we rescale in this file ourselves, ignoring passed policy
- // TODO: check this more.
- // Besides this, it currently does not compile for yet unknown reasons
- // (does not find specialization for segment_ratio_type)
- // It is currently only called from the Unit Test "multi_intersection.cpp"
-
- // Determine how p/r and p/s are located.
- inline void overlap_info(
- robust_point_type const& pi, robust_point_type const& pj,
- robust_point_type const& ri, robust_point_type const& rj,
- robust_point_type const& si, robust_point_type const& sj,
- bool& pr_overlap, bool& ps_overlap, bool& rs_overlap) const
- {
- // Determine how p/r and p/s are located.
- // One of them is coming from opposite direction.
-
- typedef segment_intersection_points
- <
- point_type,
- typename segment_ratio_type
- <
- point_type, RobustPolicy
- >::type
- > intersection_return_type;
-
- typedef strategy::intersection::relate_cartesian_segments
- <
- policies::relate::segments_intersection_points
- <
- intersection_return_type
- >
- > policy;
-
- typedef model::referring_segment<robust_point_type const> segment_type;
- segment_type p(pi, pj);
- segment_type r(ri, rj);
- segment_type s(si, sj);
-
- // Get the intersection point (or two points)
- intersection_return_type pr = policy::apply(p, r, m_rescale_policy, pi, pj, ri, rj);
- intersection_return_type ps = policy::apply(p, s, m_rescale_policy, pi, pj, si, sj);
- intersection_return_type rs = policy::apply(r, s, m_rescale_policy, ri, rj, si, sj);
-
- // Check on overlap
- pr_overlap = pr.count == 2;
- ps_overlap = ps.count == 2;
- rs_overlap = rs.count == 2;
- }
-#endif
-
-
-#ifdef BOOST_GEOMETRY_DEBUG_HANDLE_TANGENCIES
- inline void debug_consider(int order, Indexed const& left,
- Indexed const& right, std::string const& header,
- bool skip = true,
- std::string const& extra = "", bool ret = false
- ) const
- {
- if (skip) return;
-
- std::cout << "Case: " << header << " for " << left.turn_index << " / " << right.turn_index << std::endl;
-
- robust_point_type pi, pj, ri, rj, si, sj;
- get_situation_map(left, right, pi, pj, ri, rj, si, sj);
-
-#if BOOST_GEOMETRY_HANDLE_TANGENCIES_WITH_OVERLAP_INFO
- bool prc = false, psc = false, rsc = false;
- overlap_info(pi, pj, ri, rj, si, sj, prc, psc, rsc);
-#endif
-
- int const side_ri_p = m_strategy.apply(pi, pj, ri);
- int const side_rj_p = m_strategy.apply(pi, pj, rj);
- int const side_si_p = m_strategy.apply(pi, pj, si);
- int const side_sj_p = m_strategy.apply(pi, pj, sj);
- int const side_si_r = m_strategy.apply(ri, rj, si);
- int const side_sj_r = m_strategy.apply(ri, rj, sj);
-
-#ifdef BOOST_GEOMETRY_DEBUG_HANDLE_TANGENCIES_MORE
- std::cout << " Segment p:" << geometry::wkt(pi) << " .. " << geometry::wkt(pj) << std::endl;
- std::cout << " Segment r:" << geometry::wkt(ri) << " .. " << geometry::wkt(rj) << std::endl;
- std::cout << " Segment s:" << geometry::wkt(si) << " .. " << geometry::wkt(sj) << std::endl;
-
- std::cout << " r//p: " << side_ri_p << " / " << side_rj_p << std::endl;
- std::cout << " s//p: " << side_si_p << " / " << side_sj_p << std::endl;
- std::cout << " s//r: " << side_si_r << " / " << side_sj_r << std::endl;
-#endif
-
- std::cout << header
- //<< " order: " << order
- << " ops: " << operation_char(left.subject->operation)
- << "/" << operation_char(right.subject->operation)
- << " ri//p: " << side_ri_p
- << " si//p: " << side_si_p
- << " si//r: " << side_si_r
-#if BOOST_GEOMETRY_HANDLE_TANGENCIES_WITH_OVERLAP_INFO
- << " cnts: " << int(prc) << "," << int(psc) << "," << int(rsc)
-#endif
- //<< " idx: " << left.turn_index << "/" << right.turn_index
- ;
-
- if (! extra.empty())
- {
- std::cout << " " << extra << " " << (ret ? "true" : "false");
- }
- std::cout << std::endl;
- }
-#else
- inline void debug_consider(int, Indexed const& ,
- Indexed const& , std::string const& ,
- bool = true,
- std::string const& = "", bool = false
- ) const
- {}
-#endif
-
-
- // ux/ux
- inline bool consider_ux_ux(Indexed const& left,
- Indexed const& right
- , std::string const& // header
- ) const
- {
- bool ret = left.turn_index < right.turn_index;
-
- // In combination of u/x, x/u: take first union, then blocked.
- // Solves #88, #61, #56, #80
- if (left.subject->operation == operation_union
- && right.subject->operation == operation_blocked)
- {
- ret = true;
- }
- else if (left.subject->operation == operation_blocked
- && right.subject->operation == operation_union)
- {
- ret = false;
- }
- else
- {
-#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_TANGENCIES)
- std::cout << "ux/ux unhandled" << std::endl;
-#endif
- }
-
- //debug_consider(0, left, right, header, false, "-> return ", ret);
-
- return ret;
- }
-
- inline bool consider_iu_ux(Indexed const& left,
- Indexed const& right,
- int order // 1: iu first, -1: ux first
- , std::string const& // header
- ) const
- {
- bool ret = false;
-
- if (left.subject->operation == operation_union
- && right.subject->operation == operation_union)
- {
- ret = order == 1;
- }
- else if (left.subject->operation == operation_union
- && right.subject->operation == operation_blocked)
- {
- ret = true;
- }
- else if (right.subject->operation == operation_union
- && left.subject->operation == operation_blocked)
- {
- ret = false;
- }
- else if (left.subject->operation == operation_union)
- {
- ret = true;
- }
- else if (right.subject->operation == operation_union)
- {
- ret = false;
- }
- else
- {
-#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_TANGENCIES)
- // this still happens in the traverse.cpp test
- std::cout << " iu/ux unhandled" << std::endl;
-#endif
- ret = order == 1;
- }
-
- //debug_consider(0, left, right, header, false, "-> return", ret);
- return ret;
- }
-
- inline bool consider_iu_ix(Indexed const& left,
- Indexed const& right,
- int order // 1: iu first, -1: ix first
- , std::string const& // header
- ) const
- {
- //debug_consider(order, left, right, header, false, "iu/ix");
-
- return left.subject->operation == operation_intersection
- && right.subject->operation == operation_intersection ? order == 1
- : left.subject->operation == operation_intersection ? false
- : right.subject->operation == operation_intersection ? true
- : order == 1;
- }
-
- inline bool consider_ix_ix(Indexed const& left, Indexed const& right
- , std::string const& // header
- ) const
- {
- // Take first intersection, then blocked.
- if (left.subject->operation == operation_intersection
- && right.subject->operation == operation_blocked)
- {
- return true;
- }
- else if (left.subject->operation == operation_blocked
- && right.subject->operation == operation_intersection)
- {
- return false;
- }
-
- // Default case, should not occur
-
-#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_TANGENCIES)
- std::cout << "ix/ix unhandled" << std::endl;
-#endif
- //debug_consider(0, left, right, header, false, "-> return", ret);
-
- return default_order(left, right);
- }
-
-
- inline bool consider_iu_iu(Indexed const& left, Indexed const& right,
- std::string const& header, bool redo = false) const
- {
- //debug_consider(0, left, right, header);
-
- // In general, order it like "union, intersection".
- if (left.subject->operation == operation_intersection
- && right.subject->operation == operation_union)
- {
- //debug_consider(0, left, right, header, false, "i,u", false);
- return false;
- }
- else if (left.subject->operation == operation_union
- && right.subject->operation == operation_intersection)
- {
- //debug_consider(0, left, right, header, false, "u,i", true);
- return true;
- }
-
- robust_point_type pi, pj, ri, rj, si, sj;
- get_situation_map(left, right, pi, pj, ri, rj, si, sj);
-
- int const side_ri_p = m_strategy.apply(pi, pj, ri);
- int const side_si_p = m_strategy.apply(pi, pj, si);
- int const side_si_r = m_strategy.apply(ri, rj, si);
-
- // Both located at same side (#58, pie_21_7_21_0_3)
- if (side_ri_p * side_si_p == 1 && side_si_r != 0)
- {
- if (left.subject->operation == operation_union
- && right.subject->operation == operation_union)
- {
- int const side_ri_s = m_strategy.apply(si, sj, ri);
- if (side_si_r == side_ri_s)
- {
- return default_order(left, right);
- }
-
- // Take the most left one
- bool const ret = side_si_r == 1;
- //debug_consider(0, left, right, header, false, "same side", ret);
- return ret;
- }
- }
-
-
- // Coming from opposite sides (#59, #99)
- if (side_ri_p * side_si_p == -1)
- {
- bool ret = false;
-
- {
- ret = side_ri_p == 1; // #100
- debug_consider(0, left, right, header, false, "opp.", ret);
- return ret;
- }
-#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_TANGENCIES)
- std::cout << " iu/iu coming from opposite unhandled" << std::endl;
-#endif
- }
-
-#if BOOST_GEOMETRY_HANDLE_TANGENCIES_WITH_OVERLAP_INFO
- // We need EXTRA information here: are p/r/s overlapping?
- bool pr_ov = false, ps_ov = false, rs_ov = false;
- overlap_info(pi, pj, ri, rj, si, sj, pr_ov, ps_ov, rs_ov);
-#else
- // std::cout << "Boost.Geometry: skipping overlap_info" << std::endl;
-#endif
-
- // One coming from right (#83,#90)
- // One coming from left (#90, #94, #95)
- if (side_si_r != 0 && (side_ri_p != 0 || side_si_p != 0))
- {
- int const side_ri_s = m_strategy.apply(si, sj, ri);
- if (side_si_r == side_ri_s)
- {
- return default_order(left, right);
- }
-
- bool ret = false;
-
-#if BOOST_GEOMETRY_HANDLE_TANGENCIES_WITH_OVERLAP_INFO
- if (pr_ov || ps_ov)
- {
- int r = side_ri_p != 0 ? side_ri_p : side_si_p;
- ret = r * side_si_r == 1;
- }
- else
-#endif
- {
- ret = side_si_r == 1;
- }
-
- debug_consider(0, left, right, header, false, "left or right", ret);
- return ret;
- }
-
- // All aligned (#92, #96)
- if (side_ri_p == 0 && side_si_p == 0 && side_si_r == 0)
- {
- // One of them is coming from opposite direction.
-
- // Take the one NOT overlapping
- bool ret = false;
- bool found = false;
-#if BOOST_GEOMETRY_HANDLE_TANGENCIES_WITH_OVERLAP_INFO
- if (pr_ov && ! ps_ov)
- {
- ret = true;
- found = true;
- }
- else if (!pr_ov && ps_ov)
- {
- ret = false;
- found = true;
- }
-#endif
-
- debug_consider(0, left, right, header, false, "aligned", ret);
- if (found)
- {
- return ret;
- }
- }
-
-#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_TANGENCIES)
- std::cout << " iu/iu unhandled" << std::endl;
- debug_consider(0, left, right, header, false, "unhandled", left.turn_index < right.turn_index);
-#endif
- if (! redo)
- {
- // In some cases behaviour is not symmetrical. TODO: fix this properly
- // OR: alternatively we might consider calling all these functions one-way anyway
- return ! consider_iu_iu(right, left, header, true);
- }
-
- return default_order(left, right);
- }
-
- inline bool consider_ii(Indexed const& left, Indexed const& right,
- std::string const& header) const
- {
- debug_consider(0, left, right, header);
-
- robust_point_type pi, pj, ri, rj, si, sj;
- get_situation_map(left, right, pi, pj, ri, rj, si, sj);
-
- int const side_ri_p = m_strategy.apply(pi, pj, ri);
- int const side_si_p = m_strategy.apply(pi, pj, si);
-
- // Two other points are (mostly) lying both right of the considered segment
- // Take the most left one
- int const side_si_r = m_strategy.apply(ri, rj, si);
- if (side_ri_p == -1
- && side_si_p == -1
- && side_si_r != 0)
- {
- bool const ret = side_si_r != 1;
- return ret;
- }
- return default_order(left, right);
- }
-
-
-public :
- inline bool operator()(Indexed const& left, Indexed const& right) const
- {
- if ((m_turn_points[left.turn_index].discarded || left.discarded)
- && (m_turn_points[right.turn_index].discarded || right.discarded))
- {
- return default_order(left, right);
- }
- else if (m_turn_points[left.turn_index].discarded || left.discarded)
- {
- // Be careful to sort discarded first, then all others
- return true;
- }
- else if (m_turn_points[right.turn_index].discarded || right.discarded)
- {
- // See above so return false here such that right (discarded)
- // is sorted before left (not discarded)
- return false;
- }
- else if (m_turn_points[left.turn_index].combination(operation_blocked, operation_union)
- && m_turn_points[right.turn_index].combination(operation_blocked, operation_union))
- {
- // ux/ux
- return consider_ux_ux(left, right, "ux/ux");
- }
- else if (m_turn_points[left.turn_index].both(operation_union)
- && m_turn_points[right.turn_index].both(operation_union))
- {
- // uu/uu, Order is arbitrary
- // Note: uu/uu is discarded now before so this point will
- // not be reached.
- return default_order(left, right);
- }
- else if (m_turn_points[left.turn_index].combination(operation_intersection, operation_union)
- && m_turn_points[right.turn_index].combination(operation_intersection, operation_union))
- {
- return consider_iu_iu(left, right, "iu/iu");
- }
- else if (m_turn_points[left.turn_index].combination(operation_intersection, operation_blocked)
- && m_turn_points[right.turn_index].combination(operation_intersection, operation_blocked))
- {
- return consider_ix_ix(left, right, "ix/ix");
- }
- else if (m_turn_points[left.turn_index].both(operation_intersection)
- && m_turn_points[right.turn_index].both(operation_intersection))
- {
- return consider_ii(left, right, "ii/ii");
- }
- else if (m_turn_points[left.turn_index].combination(operation_union, operation_blocked)
- && m_turn_points[right.turn_index].combination(operation_intersection, operation_union))
- {
- return consider_iu_ux(left, right, -1, "ux/iu");
- }
- else if (m_turn_points[left.turn_index].combination(operation_intersection, operation_union)
- && m_turn_points[right.turn_index].combination(operation_union, operation_blocked))
- {
- return consider_iu_ux(left, right, 1, "iu/ux");
- }
- else if (m_turn_points[left.turn_index].combination(operation_intersection, operation_blocked)
- && m_turn_points[right.turn_index].combination(operation_intersection, operation_union))
- {
- return consider_iu_ix(left, right, 1, "ix/iu");
- }
- else if (m_turn_points[left.turn_index].combination(operation_intersection, operation_union)
- && m_turn_points[right.turn_index].combination(operation_intersection, operation_blocked))
- {
- return consider_iu_ix(left, right, -1, "iu/ix");
- }
- else if (m_turn_points[left.turn_index].method != method_equal
- && m_turn_points[right.turn_index].method == method_equal
- )
- {
- // If one of them was EQUAL or CONTINUES, it should always come first
- return false;
- }
- else if (m_turn_points[left.turn_index].method == method_equal
- && m_turn_points[right.turn_index].method != method_equal
- )
- {
- return true;
- }
-
- // Now we have no clue how to sort.
-
-#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_TANGENCIES)
- std::cout << " Consider: " << operation_char(m_turn_points[left.turn_index].operations[0].operation)
- << operation_char(m_turn_points[left.turn_index].operations[1].operation)
- << "/" << operation_char(m_turn_points[right.turn_index].operations[0].operation)
- << operation_char(m_turn_points[right.turn_index].operations[1].operation)
- << " " << " Take " << left.turn_index << " < " << right.turn_index
- << std::endl;
-#endif
-
- return default_order(left, right);
- }
-};
-
-
-
-template
-<
- typename IndexType,
- typename Iterator,
- typename TurnPoints,
- typename Geometry1,
- typename Geometry2,
- typename Strategy
->
-inline void inspect_cluster(Iterator begin_cluster, Iterator end_cluster,
- TurnPoints& turn_points,
- operation_type ,
- Geometry1 const& , Geometry2 const& ,
- Strategy const& )
-{
- int count = 0;
-
- // Make an analysis about all occuring cases here.
- std::map<std::pair<operation_type, operation_type>, int> inspection;
- for (Iterator it = begin_cluster; it != end_cluster; ++it)
- {
- operation_type first = turn_points[it->turn_index].operations[0].operation;
- operation_type second = turn_points[it->turn_index].operations[1].operation;
- if (first > second)
- {
- std::swap(first, second);
- }
- inspection[std::make_pair(first, second)]++;
- count++;
- }
-
-
- bool keep_cc = false;
-
- // Decide about which is going to be discarded here.
- if (inspection[std::make_pair(operation_union, operation_union)] == 1
- && inspection[std::make_pair(operation_continue, operation_continue)] == 1)
- {
- // In case of uu/cc, discard the uu, that indicates a tangency and
- // inclusion would disturb the (e.g.) cc-cc-cc ordering
- // NOTE: uu is now discarded anyhow.
- keep_cc = true;
- }
- else if (count == 2
- && inspection[std::make_pair(operation_intersection, operation_intersection)] == 1
- && inspection[std::make_pair(operation_union, operation_intersection)] == 1)
- {
- // In case of ii/iu, discard the iu. The ii should always be visited,
- // Because (in case of not discarding iu) correctly ordering of ii/iu appears impossible
- for (Iterator it = begin_cluster; it != end_cluster; ++it)
- {
- if (turn_points[it->turn_index].combination(operation_intersection, operation_union))
- {
- it->discarded = true;
- }
- }
- }
-
- // Discard any continue turn, unless it is the only thing left
- // (necessary to avoid cc-only rings, all being discarded
- // e.g. traversal case #75)
- int nd_count= 0, cc_count = 0;
- for (Iterator it = begin_cluster; it != end_cluster; ++it)
- {
- if (! it->discarded)
- {
- nd_count++;
- if (turn_points[it->turn_index].both(operation_continue))
- {
- cc_count++;
- }
- }
- }
-
- if (nd_count == cc_count)
- {
- keep_cc = true;
- }
-
- if (! keep_cc)
- {
- for (Iterator it = begin_cluster; it != end_cluster; ++it)
- {
- if (turn_points[it->turn_index].both(operation_continue))
- {
- it->discarded = true;
- }
- }
- }
-}
-
-
-template
-<
- typename IndexType,
- bool Reverse1, bool Reverse2,
- typename Iterator,
- typename TurnPoints,
- typename Geometry1,
- typename Geometry2,
- typename RobustPolicy,
- typename Strategy
->
-inline void handle_cluster(Iterator begin_cluster, Iterator end_cluster,
- TurnPoints& turn_points,
- operation_type for_operation,
- Geometry1 const& geometry1, Geometry2 const& geometry2,
- RobustPolicy& robust_policy,
- Strategy const& strategy)
-{
- // First inspect and (possibly) discard rows
- inspect_cluster<IndexType>(begin_cluster, end_cluster, turn_points,
- for_operation, geometry1, geometry2, strategy);
-
-
- // Then sort this range (discarded rows will be ordered first and will be removed in enrich_assign)
- std::sort(begin_cluster, end_cluster,
- sort_in_cluster
- <
- TurnPoints,
- IndexType,
- Geometry1, Geometry2,
- RobustPolicy,
- Reverse1, Reverse2,
- Strategy
- >(turn_points, geometry1, geometry2, robust_policy, strategy));
-
-#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_TANGENCIES)
- typedef typename IndexType::type operations_type;
- operations_type const& op = turn_points[begin_cluster->turn_index].operations[begin_cluster->operation_index];
- std::cout << std::endl << "Clustered points on equal distance " << op.fraction << std::endl;
-
- std::cout << "->Indexes ";
- for (Iterator it = begin_cluster; it != end_cluster; ++it)
- {
- std::cout << " " << it->turn_index;
- }
- std::cout << std::endl << "->Methods: ";
- for (Iterator it = begin_cluster; it != end_cluster; ++it)
- {
- std::cout << " " << method_char(turn_points[it->turn_index].method);
- }
- std::cout << std::endl << "->Operations: ";
- for (Iterator it = begin_cluster; it != end_cluster; ++it)
- {
- std::cout << " " << operation_char(turn_points[it->turn_index].operations[0].operation)
- << operation_char(turn_points[it->turn_index].operations[1].operation);
- }
- std::cout << std::endl << "->Discarded: ";
- for (Iterator it = begin_cluster; it != end_cluster; ++it)
- {
- std::cout << " " << (it->discarded ? "true" : "false");
- }
- std::cout << std::endl;
- //<< "\tOn segments: " << prev_op.seg_id << " / " << prev_op.other_id
- //<< " and " << op.seg_id << " / " << op.other_id
- //<< geometry::distance(turn_points[prev->turn_index].point, turn_points[it->turn_index].point)
-#endif
-
-}
-
-
-}} // namespace detail::overlay
-#endif //DOXYGEN_NO_DETAIL
-
-
-}} // namespace boost::geometry
-
-
-#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_TANGENCIES_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/handle_touch.hpp b/boost/geometry/algorithms/detail/overlay/handle_touch.hpp
new file mode 100644
index 0000000000..1febefc83a
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/handle_touch.hpp
@@ -0,0 +1,336 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_TOUCH_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_TOUCH_HPP
+
+#include <cstddef>
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
+#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+template <typename Turns, typename Visitor>
+class handle_touch_uu
+{
+private :
+ typedef typename boost::range_value<Turns>::type turn_type;
+ typedef typename boost::range_iterator<Turns>::type turn_iterator;
+ typedef typename boost::range_iterator<Turns const>::type turn_const_iterator;
+
+ typedef typename boost::range_iterator
+ <
+ typename turn_type::container_type const
+ >::type operation_const_iterator;
+
+public :
+
+ handle_touch_uu(Visitor& visitor)
+ : m_visitor(visitor)
+ {}
+
+ inline void apply(detail::overlay::operation_type operation, Turns& turns)
+ {
+ if (! has_uu(turns))
+ {
+ // Performance - if there is no u/u at all, nothing to be done
+ return;
+ }
+
+ // Iterate through all u/u points
+ int turn_index = 0;
+ for (turn_iterator it = boost::begin(turns);
+ it != boost::end(turns);
+ ++it, ++turn_index)
+ {
+ turn_type& turn = *it;
+ if (! turn.both(operation_union))
+ {
+ continue;
+ }
+
+ m_visitor.print("handle_touch uu:", turns, turn_index);
+
+ bool const traverse = turn_should_be_traversed(turns, turn, turn_index);
+ bool const start = traverse
+ && turn_should_be_startable(turns, turn, turn_index);
+ m_visitor.print("handle_touch, ready ", turns, turn_index);
+// << std::boolalpha
+// << traverse << " " << start
+
+ if (traverse)
+ {
+ // Indicate the sources should switch here to create
+ // separate rings (outer ring / inner ring)
+ turn.switch_source = true;
+ }
+ // TODO: this is often not correct, fix this
+ turn.operations[0].enriched.startable = start;
+ turn.operations[1].enriched.startable = start;
+ }
+ }
+
+private :
+
+ // Generic utility to be moved somewhere else
+ static inline
+ ring_identifier ring_id_from_seg_id(const segment_identifier& seg_id)
+ {
+ return ring_identifier(seg_id.source_index,
+ seg_id.multi_index,
+ seg_id.ring_index);
+ }
+
+ static inline
+ ring_identifier ring_id_from_op(const turn_type& turn,
+ int operation_index)
+ {
+ return ring_id_from_seg_id(turn.operations[operation_index].seg_id);
+ }
+
+ static inline bool in_range(const Turns& turns, signed_size_type index)
+ {
+ signed_size_type const turns_size =
+ static_cast<signed_size_type>(boost::size(turns));
+ return index >= 0 && index < turns_size;
+ }
+
+ static inline bool has_uu(const Turns& turns)
+ {
+ for (turn_const_iterator it = boost::begin(turns);
+ it != boost::end(turns);
+ ++it)
+ {
+ const turn_type& turn = *it;
+ if (turn.both(operation_union))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static inline
+ bool turn_should_be_startable(const Turns& turns,
+ const turn_type& uu_turn,
+ signed_size_type uu_turn_index)
+ {
+ return turn_startable(turns, uu_turn, 0, uu_turn_index)
+ || turn_startable(turns, uu_turn, 1, uu_turn_index);
+
+ }
+
+ static inline
+ bool turn_startable(const Turns& turns,
+ const turn_type& uu_turn,
+ std::size_t op_index,
+ signed_size_type original_turn_index,
+ std::size_t iteration = 0)
+ {
+ if (iteration >= boost::size(turns))
+ {
+ // Defensive check to avoid infinite recursion
+ return false;
+ }
+
+ signed_size_type const index
+ = uu_turn.operations[op_index].enriched.travels_to_ip_index;
+ if (index == original_turn_index)
+ {
+ // Completely traveled, having u/u only, via this op_index
+ return true;
+ }
+
+ if (! in_range(turns, index))
+ {
+ return false;
+ }
+
+ const turn_type& new_turn = turns[index];
+
+ if (new_turn.operations[0].enriched.startable)
+ {
+ // Already selectable - no need to select u/u turn too
+ return false;
+ }
+
+ // If this u/u turn is traversed normally (without skipping), sources are switched
+ return turn_startable(turns, new_turn, 1 - op_index,
+ original_turn_index, iteration + 1);
+ }
+
+ inline bool turn_should_be_traversed(const Turns& turns,
+ const turn_type& uu_turn,
+ signed_size_type uu_turn_index)
+ {
+ return turn_should_be_traversed(turns, uu_turn, uu_turn_index, 0)
+ || turn_should_be_traversed(turns, uu_turn, uu_turn_index, 1);
+ }
+
+ inline bool turn_should_be_traversed(const Turns& turns,
+ const turn_type& uu_turn,
+ signed_size_type uu_turn_index,
+ int uu_operation_index)
+ {
+ // Suppose this is a u/u turn between P and Q
+ // Examine all other turns on P and check if Q can be reached
+ // Use one of the operations and check if you can reach the other
+ signed_size_type const to_turn_index
+ = uu_turn.operations[uu_operation_index].enriched.travels_to_ip_index;
+ if (! in_range(turns, to_turn_index))
+ {
+ return false;
+ }
+
+ m_visitor.print("Examine:", turns, to_turn_index);
+ ring_identifier const other_ring_id
+ = ring_id_from_op(uu_turn, 1 - uu_operation_index);
+
+ bool complete = false;
+ return can_reach(complete, turns, turns[to_turn_index], uu_operation_index,
+ other_ring_id, uu_turn_index, to_turn_index);
+ }
+
+ inline bool can_reach(bool& complete, const Turns& turns,
+ const turn_type& turn,
+ signed_size_type uu_operation_index,
+ const ring_identifier& target_ring_id,
+ signed_size_type uu_turn_index,
+ signed_size_type to_turn_index,
+ std::size_t iteration = 0)
+ {
+ if (complete)
+ {
+ return false;
+ }
+
+ if (turn.cluster_id >= 0)
+ {
+ // Clustered turns are yet not supported
+ return false;
+ }
+
+ if (iteration >= boost::size(turns))
+ {
+ m_visitor.print("Too much iterations");
+ // Defensive check to avoid infinite recursion
+ return false;
+ }
+
+ if (uu_operation_index != -1 && turn.both(operation_union))
+ {
+ // If we end up in a u/u turn, check the way how, for this operation
+ m_visitor.print("Via u/u");
+ return can_reach_via(complete, turns, uu_operation_index,
+ turn.operations[uu_operation_index],
+ target_ring_id,
+ uu_turn_index, to_turn_index, iteration);
+ }
+ else
+ {
+ // Check if specified ring can be reached via one of both operations
+ return can_reach_via(complete, turns, 0, turn.operations[0], target_ring_id,
+ uu_turn_index, to_turn_index, iteration)
+ || can_reach_via(complete, turns, 1, turn.operations[1], target_ring_id,
+ uu_turn_index, to_turn_index, iteration);
+ }
+ }
+
+ template <typename Operation>
+ inline bool can_reach_via(bool& complete, const Turns& turns,
+ signed_size_type operation_index,
+ const Operation& operation,
+ const ring_identifier& target_ring_id,
+ signed_size_type uu_turn_index,
+ signed_size_type to_turn_index,
+ std::size_t iteration = 0)
+ {
+ if (operation.operation != operation_union
+ && operation.operation != operation_continue)
+ {
+ return false;
+ }
+
+ signed_size_type const index = operation.enriched.travels_to_ip_index;
+ if (index == to_turn_index)
+ {
+ m_visitor.print("Dead end at", turns, index);
+ // Completely traveled, the target is not found
+ return false;
+ }
+ if (index == uu_turn_index)
+ {
+ // End up where trial was started
+ m_visitor.print("Travel complete at", turns, index);
+ complete = true;
+ return false;
+ }
+
+ if (! in_range(turns, index))
+ {
+ return false;
+ }
+
+ m_visitor.print("Now to", turns, index, operation_index);
+ const turn_type& new_turn = turns[index];
+
+ if (new_turn.both(operation_union))
+ {
+ ring_identifier const ring_id = ring_id_from_op(new_turn, operation_index);
+ if (ring_id == target_ring_id)
+ {
+ m_visitor.print("Found (at u/u)!");
+ return true;
+ }
+ }
+ else
+ {
+ ring_identifier const ring_id1 = ring_id_from_op(new_turn, 0);
+ ring_identifier const ring_id2 = ring_id_from_op(new_turn, 1);
+ if (ring_id1 == target_ring_id || ring_id2 == target_ring_id)
+ {
+ m_visitor.print("Found!");
+ return true;
+ }
+ }
+
+ // Recursively check this turn
+ return can_reach(complete, turns, new_turn, operation_index, target_ring_id,
+ uu_turn_index, to_turn_index, iteration + 1);
+ }
+
+private :
+ Visitor m_visitor;
+};
+
+template <typename Turns, typename Visitor>
+inline void handle_touch(detail::overlay::operation_type operation,
+ Turns& turns, Visitor& visitor)
+{
+ handle_touch_uu<Turns, Visitor> handler(visitor);
+ handler.apply(operation, turns);
+}
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_TOUCH_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp b/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp
new file mode 100644
index 0000000000..21868a2939
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp
@@ -0,0 +1,203 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2015 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_SORT_ON_SEGMENT_RATIO_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SORT_ON_SEGMENT_RATIO_HPP
+
+#include <cstddef>
+#include <algorithm>
+#include <map>
+#include <set>
+#include <vector>
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>
+#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>
+#include <boost/geometry/strategies/side.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+// Wraps "turn_operation" from turn_info.hpp,
+// giving it extra information, necessary for sorting
+template <typename TurnOperation>
+struct indexed_turn_operation
+{
+ typedef TurnOperation type;
+
+ std::size_t turn_index;
+ std::size_t operation_index;
+ bool skip;
+ // use pointers to avoid copies, const& is not possible because of usage in vector
+ segment_identifier const* other_seg_id; // segment id of other segment of intersection of two segments
+ TurnOperation const* subject;
+
+ inline indexed_turn_operation(std::size_t ti, std::size_t oi,
+ TurnOperation const& sub,
+ segment_identifier const& oid)
+ : turn_index(ti)
+ , operation_index(oi)
+ , skip(false)
+ , other_seg_id(&oid)
+ , subject(boost::addressof(sub))
+ {}
+
+};
+
+template
+<
+ typename Turns,
+ typename Indexed,
+ typename Geometry1, typename Geometry2,
+ typename RobustPolicy,
+ bool Reverse1, bool Reverse2
+>
+struct less_by_segment_ratio
+{
+ inline less_by_segment_ratio(Turns const& turns
+ , operation_type for_operation
+ , Geometry1 const& geometry1
+ , Geometry2 const& geometry2
+ , RobustPolicy const& robust_policy)
+ : m_turns(turns)
+ , m_for_operation(for_operation)
+ , m_geometry1(geometry1)
+ , m_geometry2(geometry2)
+ , m_robust_policy(robust_policy)
+ {
+ }
+
+private :
+
+ Turns const& m_turns;
+ operation_type m_for_operation;
+ Geometry1 const& m_geometry1;
+ Geometry2 const& m_geometry2;
+ RobustPolicy const& m_robust_policy;
+
+ typedef typename geometry::point_type<Geometry1>::type point_type;
+
+ inline bool default_order(Indexed const& left, Indexed const& right) const
+ {
+ // We've nothing to sort on. Take the indexes
+ return left.turn_index < right.turn_index;
+ }
+
+ inline bool consider_relative_order(Indexed const& left,
+ Indexed const& right) const
+ {
+ point_type pi, pj, ri, rj, si, sj;
+
+ geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
+ left.subject->seg_id,
+ pi, pj);
+ geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
+ *left.other_seg_id,
+ ri, rj);
+ geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
+ *right.other_seg_id,
+ si, sj);
+
+ typedef typename strategy::side::services::default_strategy
+ <
+ typename cs_tag<point_type>::type
+ >::type strategy;
+
+ int const side_rj_p = strategy::apply(pi, pj, rj);
+ int const side_sj_p = strategy::apply(pi, pj, sj);
+
+ // Put the one turning left (1; right == -1) as last
+ if (side_rj_p != side_sj_p)
+ {
+ return side_rj_p < side_sj_p;
+ }
+
+ int const side_sj_r = strategy::apply(ri, rj, sj);
+ int const side_rj_s = strategy::apply(si, sj, rj);
+
+ // If they both turn left: the most left as last
+ // If they both turn right: this is not relevant, but take also here most left
+ if (side_rj_s != side_sj_r)
+ {
+ return side_rj_s < side_sj_r;
+ }
+
+ return default_order(left, right);
+ }
+
+
+public :
+
+ // Note that left/right do NOT correspond to m_geometry1/m_geometry2
+ // but to the "indexed_turn_operation"
+ inline bool operator()(Indexed const& left, Indexed const& right) const
+ {
+ if (! (left.subject->seg_id == right.subject->seg_id))
+ {
+ return left.subject->seg_id < right.subject->seg_id;
+ }
+
+ // Both left and right are located on the SAME segment.
+
+ if (! (left.subject->fraction == right.subject->fraction))
+ {
+ return left.subject->fraction < right.subject->fraction;
+ }
+
+
+ typedef typename boost::range_value<Turns>::type turn_type;
+ turn_type const& left_turn = m_turns[left.turn_index];
+ turn_type const& right_turn = m_turns[right.turn_index];
+
+ // First check "real" intersection (crosses)
+ // -> distance zero due to precision, solve it by sorting
+ if (left_turn.method == method_crosses
+ && right_turn.method == method_crosses)
+ {
+ return consider_relative_order(left, right);
+ }
+
+ bool const left_both_xx = left_turn.both(operation_blocked);
+ bool const right_both_xx = right_turn.both(operation_blocked);
+ if (left_both_xx && ! right_both_xx)
+ {
+ return true;
+ }
+ if (! left_both_xx && right_both_xx)
+ {
+ return false;
+ }
+
+ bool const left_both_uu = left_turn.both(operation_union);
+ bool const right_both_uu = right_turn.both(operation_union);
+ if (left_both_uu && ! right_both_uu)
+ {
+ return true;
+ }
+ if (! left_both_uu && right_both_uu)
+ {
+ return false;
+ }
+
+ return default_order(left, right);
+ }
+};
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SORT_ON_SEGMENT_RATIO_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/overlay.hpp b/boost/geometry/algorithms/detail/overlay/overlay.hpp
index 6eb0b8864c..c3ecaa0b01 100644
--- a/boost/geometry/algorithms/detail/overlay/overlay.hpp
+++ b/boost/geometry/algorithms/detail/overlay/overlay.hpp
@@ -26,6 +26,7 @@
#include <boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp>
#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
+#include <boost/geometry/algorithms/detail/overlay/handle_touch.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
#include <boost/geometry/algorithms/detail/overlay/traverse.hpp>
#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
@@ -59,28 +60,50 @@ namespace detail { namespace overlay
{
-template <typename TurnPoints, typename TurnInfoMap>
-inline void get_ring_turn_info(TurnInfoMap& turn_info_map,
- TurnPoints const& turn_points)
+//! Default visitor for overlay, doing nothing
+struct overlay_null_visitor
{
- typedef typename boost::range_value<TurnPoints>::type turn_point_type;
- typedef typename turn_point_type::container_type container_type;
+ void print(char const* ) {}
- for (typename boost::range_iterator<TurnPoints const>::type
- it = boost::begin(turn_points);
- it != boost::end(turn_points);
+ template <typename Turns>
+ void print(char const* , Turns const& , int) {}
+
+ template <typename Turns>
+ void print(char const* , Turns const& , int , int ) {}
+
+ template <typename Turns>
+ void visit_turns(int , Turns const& ) {}
+
+ template <typename Clusters, typename Turns>
+ void visit_clusters(Clusters const& , Turns const& ) {}
+
+ template <typename Turns, typename Turn, typename Operation>
+ void visit_traverse(Turns const& , Turn const& , Operation const& , char const*)
+ {}
+
+ template <typename Turns, typename Turn, typename Operation>
+ void visit_traverse_reject(Turns const& , Turn const& , Operation const& , traverse_error_type )
+ {}
+};
+
+template <typename Turns, typename TurnInfoMap>
+inline void get_ring_turn_info(TurnInfoMap& turn_info_map, Turns const& turns)
+{
+ typedef typename boost::range_value<Turns>::type turn_type;
+ typedef typename turn_type::container_type container_type;
+
+ for (typename boost::range_iterator<Turns const>::type
+ it = boost::begin(turns);
+ it != boost::end(turns);
++it)
{
- typename boost::range_value<TurnPoints>::type const& turn_info = *it;
- bool both_uu = turn_info.both(operation_union);
- bool skip = (turn_info.discarded || both_uu)
- && ! turn_info.any_blocked()
- && ! turn_info.both(operation_intersection)
- ;
+ typename boost::range_value<Turns>::type const& turn_info = *it;
- if (! both_uu && turn_info.colocated)
+ if (turn_info.discarded
+ && ! turn_info.any_blocked()
+ && ! turn_info.colocated)
{
- skip = true;
+ continue;
}
for (typename boost::range_iterator<container_type const>::type
@@ -88,21 +111,13 @@ inline void get_ring_turn_info(TurnInfoMap& turn_info_map,
op_it != boost::end(turn_info.operations);
++op_it)
{
- ring_identifier ring_id
+ ring_identifier const ring_id
(
op_it->seg_id.source_index,
op_it->seg_id.multi_index,
op_it->seg_id.ring_index
);
-
- if (! skip)
- {
- turn_info_map[ring_id].has_normal_turn = true;
- }
- else if (both_uu)
- {
- turn_info_map[ring_id].has_uu_turn = true;
- }
+ turn_info_map[ring_id].has_normal_turn = true;
}
}
}
@@ -164,12 +179,13 @@ template
>
struct overlay
{
- template <typename RobustPolicy, typename OutputIterator, typename Strategy>
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy, typename Visitor>
static inline OutputIterator apply(
Geometry1 const& geometry1, Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
OutputIterator out,
- Strategy const& )
+ Strategy const& ,
+ Visitor& visitor)
{
bool const is_empty1 = geometry::is_empty(geometry1);
bool const is_empty2 = geometry::is_empty(geometry2);
@@ -193,14 +209,23 @@ struct overlay
point_type,
typename geometry::segment_ratio_type<point_type, RobustPolicy>::type
> turn_info;
- typedef std::deque<turn_info> container_type;
+ typedef std::deque<turn_info> turn_container_type;
typedef std::deque
<
typename geometry::ring_type<GeometryOut>::type
> ring_container_type;
- container_type turn_points;
+ // Define the clusters, mapping cluster_id -> turns
+ typedef std::map
+ <
+ signed_size_type,
+ std::set<signed_size_type>
+ > cluster_type;
+
+ cluster_type clusters;
+
+ turn_container_type turns;
#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "get turns" << std::endl;
@@ -210,20 +235,42 @@ std::cout << "get turns" << std::endl;
<
Reverse1, Reverse2,
detail::overlay::assign_null_policy
- >(geometry1, geometry2, robust_policy, turn_points, policy);
+ >(geometry1, geometry2, robust_policy, turns, policy);
+
+ visitor.visit_turns(1, turns);
+
+ static const operation_type op_type
+ = OverlayType == overlay_union
+ ? geometry::detail::overlay::operation_union
+ : geometry::detail::overlay::operation_intersection;
#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "enrich" << std::endl;
#endif
typename Strategy::side_strategy_type side_strategy;
- geometry::enrich_intersection_points<Reverse1, Reverse2, OverlayType>(turn_points,
- OverlayType == overlay_union
- ? geometry::detail::overlay::operation_union
- : geometry::detail::overlay::operation_intersection,
+ geometry::enrich_intersection_points<Reverse1, Reverse2, OverlayType>(turns,
+ clusters, op_type,
geometry1, geometry2,
robust_policy,
side_strategy);
+ visitor.visit_turns(2, turns);
+
+ visitor.visit_clusters(clusters, turns);
+
+
+#if 0
+ // TODO: does not work always correctly, move to traverse and fix
+ if (op_type == geometry::detail::overlay::operation_union)
+ {
+ #ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
+ std::cout << "handle_touch" << std::endl;
+ #endif
+
+ handle_touch(op_type, turns, visitor);
+ }
+#endif
+
#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "traverse" << std::endl;
#endif
@@ -231,18 +278,17 @@ std::cout << "traverse" << std::endl;
// Note that these rings are always in clockwise order, even in CCW polygons,
// and are marked as "to be reversed" below
ring_container_type rings;
- traverse<Reverse1, Reverse2, Geometry1, Geometry2>::apply
+ traverse<Reverse1, Reverse2, Geometry1, Geometry2, op_type>::apply
(
geometry1, geometry2,
- OverlayType == overlay_union
- ? geometry::detail::overlay::operation_union
- : geometry::detail::overlay::operation_intersection,
robust_policy,
- turn_points, rings
+ turns, rings,
+ clusters,
+ visitor
);
std::map<ring_identifier, ring_turn_info> turn_info_per_ring;
- get_ring_turn_info(turn_info_per_ring, turn_points);
+ get_ring_turn_info(turn_info_per_ring, turns);
typedef ring_properties
<
@@ -272,6 +318,17 @@ std::cout << "traverse" << std::endl;
return add_rings<GeometryOut>(selected_ring_properties, geometry1, geometry2, rings, out);
}
+
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>
+ static inline OutputIterator apply(
+ Geometry1 const& geometry1, Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ OutputIterator out,
+ Strategy const& strategy)
+ {
+ overlay_null_visitor visitor;
+ return apply(geometry1, geometry2, robust_policy, out, strategy, visitor);
+ }
};
diff --git a/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp b/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp
index e77a163dd5..5447c8813e 100644
--- a/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp
+++ b/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp
@@ -38,6 +38,7 @@ struct segment_identifier
, multi_index(-1)
, ring_index(-1)
, segment_index(-1)
+ , piece_index(-1)
{}
inline segment_identifier(signed_size_type src,
@@ -48,6 +49,7 @@ struct segment_identifier
, multi_index(mul)
, ring_index(rin)
, segment_index(seg)
+ , piece_index(-1)
{}
inline bool operator<(segment_identifier const& other) const
@@ -85,6 +87,9 @@ struct segment_identifier
signed_size_type multi_index;
signed_size_type ring_index;
signed_size_type segment_index;
+
+ // For buffer - todo: move this to buffer-only
+ signed_size_type piece_index;
};
diff --git a/boost/geometry/algorithms/detail/overlay/select_rings.hpp b/boost/geometry/algorithms/detail/overlay/select_rings.hpp
index d18e012b2d..1b3cd866d7 100644
--- a/boost/geometry/algorithms/detail/overlay/select_rings.hpp
+++ b/boost/geometry/algorithms/detail/overlay/select_rings.hpp
@@ -35,13 +35,11 @@ namespace detail { namespace overlay
struct ring_turn_info
{
- bool has_uu_turn;
bool has_normal_turn;
bool within_other;
ring_turn_info()
- : has_uu_turn(false)
- , has_normal_turn(false)
+ : has_normal_turn(false)
, within_other(false)
{}
};
@@ -174,7 +172,7 @@ struct decide<overlay_union>
{
static bool include(ring_identifier const& , ring_turn_info const& info)
{
- return info.has_uu_turn || ! info.within_other;
+ return ! info.within_other;
}
static bool reversed(ring_identifier const& , ring_turn_info const& )
@@ -190,19 +188,16 @@ struct decide<overlay_difference>
{
// Difference: A - B
- // If this is A (source_index=0) and there is only a u/u turn,
- // then the ring is inside B
- // If this is B (source_index=1) and there is only a u/u turn,
- // then the ring is NOT inside A
+ // If this is A (source_index=0), then the ring is inside B
+ // If this is B (source_index=1), then the ring is NOT inside A
// If this is A and the ring is within the other geometry,
// then we should NOT include it.
// If this is B then we SHOULD include it.
- bool const is_first = id.source_index == 0;
- bool const within_other = info.within_other
- || (is_first && info.has_uu_turn);
- return is_first ? ! within_other : within_other;
+ return id.source_index == 0
+ ? ! info.within_other
+ : info.within_other;
}
static bool reversed(ring_identifier const& id, ring_turn_info const& info)
@@ -219,7 +214,7 @@ struct decide<overlay_intersection>
{
static bool include(ring_identifier const& , ring_turn_info const& info)
{
- return ! info.has_uu_turn && info.within_other;
+ return info.within_other;
}
static bool reversed(ring_identifier const& , ring_turn_info const& )
@@ -266,19 +261,16 @@ inline void update_ring_selection(Geometry1 const& geometry1,
continue;
}
- if (! info.has_uu_turn)
+ // Check if the ring is within the other geometry, by taking
+ // a point lying on the ring
+ switch(id.source_index)
{
- // Check if the ring is within the other geometry, by taking
- // a point lying on the ring
- switch(id.source_index)
- {
- case 0 :
- info.within_other = geometry::within(it->second.point, geometry2);
- break;
- case 1 :
- info.within_other = geometry::within(it->second.point, geometry1);
- break;
- }
+ case 0 :
+ info.within_other = geometry::within(it->second.point, geometry2);
+ break;
+ case 1 :
+ info.within_other = geometry::within(it->second.point, geometry1);
+ break;
}
if (decide<OverlayType>::include(id, info))
diff --git a/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp b/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp
new file mode 100644
index 0000000000..894cddab87
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp
@@ -0,0 +1,434 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015 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_SORT_BY_SIDE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SORT_BY_SIDE_HPP
+
+#include <algorithm>
+#include <vector>
+
+#include <boost/geometry/algorithms/detail/direction_code.hpp>
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
+#include <boost/geometry/strategies/side.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay { namespace sort_by_side
+{
+
+enum index_type { index_unknown = -1, index_from = 0, index_to = 1 };
+
+// Point-wrapper, adding some properties
+template <typename Point>
+struct ranked_point
+{
+ ranked_point()
+ : main_rank(0)
+ , turn_index(-1)
+ , op_index(-1)
+ , index(index_unknown)
+ , left_count(0)
+ , right_count(0)
+ , operation(operation_none)
+ {}
+
+ ranked_point(const Point& p, signed_size_type ti, signed_size_type oi,
+ index_type i, operation_type op, segment_identifier sid)
+ : point(p)
+ , main_rank(0)
+ , turn_index(ti)
+ , op_index(oi)
+ , index(i)
+ , left_count(0)
+ , right_count(0)
+ , operation(op)
+ , seg_id(sid)
+ {}
+
+ Point point;
+ std::size_t main_rank;
+ signed_size_type turn_index;
+ signed_size_type op_index;
+ index_type index;
+ std::size_t left_count;
+ std::size_t right_count;
+ operation_type operation;
+ segment_identifier seg_id;
+};
+
+struct less_by_turn_index
+{
+ template <typename T>
+ inline bool operator()(const T& first, const T& second) const
+ {
+ return first.turn_index == second.turn_index
+ ? first.index < second.index
+ : first.turn_index < second.turn_index
+ ;
+ }
+};
+
+struct less_by_index
+{
+ template <typename T>
+ inline bool operator()(const T& first, const T& second) const
+ {
+ // First order by from/to
+ if (first.index != second.index)
+ {
+ return first.index < second.index;
+ }
+ // All the same, order by turn index (we might consider length too)
+ return first.turn_index < second.turn_index;
+ }
+};
+
+struct less_false
+{
+ template <typename T>
+ inline bool operator()(const T&, const T& ) const
+ {
+ return false;
+ }
+};
+
+template <typename Point, typename LessOnSame, typename Compare>
+struct less_by_side
+{
+ typedef typename strategy::side::services::default_strategy
+ <
+ typename cs_tag<Point>::type
+ >::type side;
+
+ less_by_side(const Point& p1, const Point& p2)
+ : m_p1(p1)
+ , m_p2(p2)
+ {}
+
+ template <typename T>
+ inline bool operator()(const T& first, const T& second) const
+ {
+ LessOnSame on_same;
+ Compare compare;
+
+ int const side_first = side::apply(m_p1, m_p2, first.point);
+ int const side_second = side::apply(m_p1, m_p2, second.point);
+
+ if (side_first == 0 && side_second == 0)
+ {
+ // 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);
+
+ // Order by code, backwards first, then forward.
+ return first_code != second_code
+ ? first_code < second_code
+ : on_same(first, second)
+ ;
+ }
+ else if (side_first == 0
+ && direction_code(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)
+ {
+ // Second is collinear and going backwards
+ // Order as very last, so return always false
+ return false;
+ }
+
+ // They are not both collinear
+
+ if (side_first != side_second)
+ {
+ return compare(side_first, side_second);
+ }
+
+ // They are both left, both right, and/or both collinear (with each other and/or with p1,p2)
+ // Check mutual side
+ int const side_second_wrt_first = side::apply(m_p2, first.point, second.point);
+
+ if (side_second_wrt_first == 0)
+ {
+ return on_same(first, second);
+ }
+
+ int const side_first_wrt_second = -side_second_wrt_first;
+
+ // Both are on same side, and not collinear
+ // Union: return true if second is right w.r.t. first, so -1,
+ // so other is 1. union has greater as compare functor
+ // Intersection: v.v.
+ return compare(side_first_wrt_second, side_second_wrt_first);
+ }
+
+private :
+ Point m_p1, m_p2;
+};
+
+template <bool Reverse1, bool Reverse2, typename Point, typename Compare>
+struct side_sorter
+{
+ typedef ranked_point<Point> rp;
+
+ inline void set_origin(Point const& origin)
+ {
+ m_origin = origin;
+ }
+
+ template <typename Operation, typename Geometry1, typename Geometry2>
+ void add(Operation const& op, signed_size_type turn_index, signed_size_type op_index,
+ Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ bool is_origin)
+ {
+ Point point1, point2, point3;
+ geometry::copy_segment_points<Reverse1, Reverse2>(geometry1, geometry2,
+ op.seg_id, point1, point2, point3);
+ Point const& point_to = op.fraction.is_one() ? point3 : point2;
+
+ m_ranked_points.push_back(rp(point1, turn_index, op_index, index_from, op.operation, op.seg_id));
+ m_ranked_points.push_back(rp(point_to, turn_index, op_index, index_to, op.operation, op.seg_id));
+
+ if (is_origin)
+ {
+ m_origin = point1;
+ }
+ }
+
+ void apply(Point const& turn_point)
+ {
+ // We need three compare functors:
+ // 1) to order clockwise (union) or counter clockwise (intersection)
+ // 2) to order by side, resulting in unique ranks for all points
+ // 3) to order by side, resulting in non-unique ranks
+ // to give colinear points
+
+ // Sort by side and assign rank
+ less_by_side<Point, less_by_index, Compare> less_unique(m_origin, turn_point);
+ less_by_side<Point, less_false, Compare> less_non_unique(m_origin, turn_point);
+
+ std::sort(m_ranked_points.begin(), m_ranked_points.end(), less_unique);
+
+ std::size_t colinear_rank = 0;
+ for (std::size_t i = 0; i < m_ranked_points.size(); i++)
+ {
+ if (i > 0
+ && less_non_unique(m_ranked_points[i - 1], m_ranked_points[i]))
+ {
+ // It is not collinear
+ colinear_rank++;
+ }
+
+ m_ranked_points[i].main_rank = colinear_rank;
+ }
+ }
+
+ template <signed_size_type segment_identifier::*Member, typename Map>
+ void find_open_generic(Map& handled)
+ {
+ for (std::size_t i = 0; i < m_ranked_points.size(); i++)
+ {
+ const rp& ranked = m_ranked_points[i];
+ if (ranked.index != index_from)
+ {
+ continue;
+ }
+
+ signed_size_type const& index = ranked.seg_id.*Member;
+ if (! handled[index])
+ {
+ find_polygons_for_source<Member>(index, i);
+ handled[index] = true;
+ }
+ }
+ }
+
+ void find_open()
+ {
+ // TODO: we might pass Buffer as overlay_type, instead on the fly below
+ bool one_source = true;
+ for (std::size_t i = 0; i < m_ranked_points.size(); i++)
+ {
+ const rp& ranked = m_ranked_points[i];
+ signed_size_type const& src = ranked.seg_id.source_index;
+ if (src != 0)
+ {
+ one_source = false;
+ break;
+ }
+ }
+
+ if (one_source)
+ {
+ // by multi index
+ std::map<signed_size_type, bool> handled;
+ find_open_generic
+ <
+ &segment_identifier::piece_index
+ >(handled);
+ }
+ else
+ {
+ // by source (there should only source 0,1) TODO assert this
+ bool handled[2] = {false, false};
+ find_open_generic
+ <
+ &segment_identifier::source_index
+ >(handled);
+ }
+ }
+
+ void reverse()
+ {
+ if (m_ranked_points.empty())
+ {
+ return;
+ }
+
+ int const last = 1 + m_ranked_points.back().main_rank;
+
+ // Move iterator after main_rank==0
+ bool has_first = false;
+ typename container_type::iterator it = m_ranked_points.begin() + 1;
+ for (; it != m_ranked_points.end() && it->main_rank == 0; ++it)
+ {
+ has_first = true;
+ }
+
+ if (has_first)
+ {
+ // Reverse first part (having main_rank == 0), if any,
+ // but skip the very first row
+ std::reverse(m_ranked_points.begin() + 1, it);
+ for (typename container_type::iterator fit = m_ranked_points.begin();
+ fit != it; ++fit)
+ {
+ BOOST_ASSERT(fit->main_rank == 0);
+ }
+ }
+
+ // Reverse the rest (main rank > 0)
+ std::reverse(it, m_ranked_points.end());
+ for (; it != m_ranked_points.end(); ++it)
+ {
+ BOOST_ASSERT(it->main_rank > 0);
+ it->main_rank = last - it->main_rank;
+ }
+ }
+
+//protected :
+
+ typedef std::vector<rp> container_type;
+ container_type m_ranked_points;
+ Point m_origin;
+
+private :
+
+
+ std::size_t move(std::size_t index) const
+ {
+ std::size_t const result = index + 1;
+ return result >= m_ranked_points.size() ? 0 : result;
+ }
+
+ //! member is pointer to member (source_index or multi_index)
+ template <signed_size_type segment_identifier::*Member>
+ std::size_t move(signed_size_type member_index, std::size_t index) const
+ {
+ std::size_t result = move(index);
+ while (m_ranked_points[result].seg_id.*Member != member_index)
+ {
+ result = move(result);
+ }
+ return result;
+ }
+
+ void assign_ranks(std::size_t min_rank, std::size_t max_rank, int side_index)
+ {
+ for (std::size_t i = 0; i < m_ranked_points.size(); i++)
+ {
+ rp& ranked = m_ranked_points[i];
+ // Suppose there are 8 ranks, if min=4,max=6: assign 4,5,6
+ // if min=5,max=2: assign from 5,6,7,1,2
+ bool const in_range
+ = max_rank >= min_rank
+ ? ranked.main_rank >= min_rank && ranked.main_rank <= max_rank
+ : ranked.main_rank >= min_rank || ranked.main_rank <= max_rank
+ ;
+
+ if (in_range)
+ {
+ if (side_index == 1)
+ {
+ ranked.left_count++;
+ }
+ else if (side_index == 2)
+ {
+ ranked.right_count++;
+ }
+ }
+ }
+ }
+
+ template <signed_size_type segment_identifier::*Member>
+ void find_polygons_for_source(signed_size_type the_index,
+ std::size_t start_index)
+ {
+ int state = 1; // 'closed', because start_index is "from", arrives at the turn
+ std::size_t last_from_rank = m_ranked_points[start_index].main_rank;
+ std::size_t previous_rank = m_ranked_points[start_index].main_rank;
+
+ for (std::size_t index = move<Member>(the_index, start_index);
+ ;
+ index = move<Member>(the_index, index))
+ {
+ rp& ranked = m_ranked_points[index];
+
+ if (ranked.main_rank != previous_rank && state == 0)
+ {
+ assign_ranks(last_from_rank, previous_rank - 1, 1);
+ assign_ranks(last_from_rank + 1, previous_rank, 2);
+ }
+
+ if (index == start_index)
+ {
+ return;
+ }
+
+ if (ranked.index == index_from)
+ {
+ last_from_rank = ranked.main_rank;
+ state++;
+ }
+ else if (ranked.index == index_to)
+ {
+ state--;
+ }
+
+ previous_rank = ranked.main_rank;
+ }
+ }
+};
+
+
+}}} // namespace detail::overlay::sort_by_side
+#endif //DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SORT_BY_SIDE_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/traverse.hpp b/boost/geometry/algorithms/detail/overlay/traverse.hpp
index 45e15d13d0..a8f4232124 100644
--- a/boost/geometry/algorithms/detail/overlay/traverse.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traverse.hpp
@@ -15,6 +15,7 @@
#include <boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp>
#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>
+#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/algorithms/num_points.hpp>
#include <boost/geometry/core/access.hpp>
@@ -65,186 +66,740 @@ inline void debug_traverse(Turn const& , Operation, const char*)
#endif
-template <typename Info, typename Turn>
-inline void set_visited_for_continue(Info& info, Turn const& turn)
+//! Metafunction to define side_order (clockwise, ccw) by operation_type
+template <operation_type OpType>
+struct side_compare {};
+
+template <>
+struct side_compare<operation_union>
{
- // On "continue", set "visited" for ALL directions
- if (turn.operation == detail::overlay::operation_continue)
+ typedef std::greater<int> type;
+};
+
+template <>
+struct side_compare<operation_intersection>
+{
+ typedef std::less<int> type;
+};
+
+
+template
+<
+ bool Reverse1,
+ bool Reverse2,
+ operation_type OperationType,
+ typename Geometry1,
+ typename Geometry2,
+ typename Turns,
+ typename Clusters,
+ typename RobustPolicy,
+ typename Visitor,
+ typename Backtrack
+>
+struct traversal
+{
+ typedef typename side_compare<OperationType>::type side_compare_type;
+ typedef typename boost::range_value<Turns>::type turn_type;
+ typedef typename turn_type::turn_operation_type turn_operation_type;
+
+ typedef typename geometry::point_type<Geometry1>::type point_type;
+ typedef sort_by_side::side_sorter
+ <
+ Reverse1, Reverse2,
+ point_type, side_compare_type
+ > sbs_type;
+
+ inline traversal(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Turns& turns, Clusters const& clusters,
+ RobustPolicy const& robust_policy, Visitor& visitor)
+ : m_geometry1(geometry1)
+ , m_geometry2(geometry2)
+ , m_turns(turns)
+ , m_clusters(clusters)
+ , m_robust_policy(robust_policy)
+ , m_visitor(visitor)
+ , m_has_uu(false)
+ , m_has_only_uu(true)
+ , m_switch_at_uu(true)
+ {}
+
+
+ inline bool select_source(signed_size_type turn_index,
+ segment_identifier const& seg_id1,
+ segment_identifier const& seg_id2)
{
- for (typename boost::range_iterator
- <
- typename Info::container_type
- >::type it = boost::begin(info.operations);
- it != boost::end(info.operations);
- ++it)
+ if (OperationType == operation_intersection)
{
- if (it->visited.none())
+ // For intersections always switch sources
+ return seg_id1.source_index != seg_id2.source_index;
+ }
+ else if (OperationType == operation_union)
+ {
+ // For uu, only switch sources if indicated
+ turn_type const& turn = m_turns[turn_index];
+
+ // TODO: pass this information
+ bool const is_buffer
+ = turn.operations[0].seg_id.source_index
+ == turn.operations[1].seg_id.source_index;
+
+ if (is_buffer)
{
- it->visited.set_visited();
+ // Buffer does not use source_index (always 0)
+ return turn.switch_source
+ ? seg_id1.multi_index != seg_id2.multi_index
+ : seg_id1.multi_index == seg_id2.multi_index;
}
+
+ // Temporarily use m_switch_at_uu, which does not solve all cases,
+ // but the majority of the more simple cases, making the interior
+ // rings valid
+ return m_switch_at_uu // turn.switch_source
+ ? seg_id1.source_index != seg_id2.source_index
+ : seg_id1.source_index == seg_id2.source_index;
}
+ return false;
}
-}
+ inline
+ signed_size_type get_next_turn_index(turn_operation_type const& op) const
+ {
+ return op.enriched.next_ip_index == -1
+ ? op.enriched.travels_to_ip_index
+ : op.enriched.next_ip_index;
+ }
-template
-<
- bool Reverse1, bool Reverse2,
- typename GeometryOut,
- typename G1,
- typename G2,
- typename Turns,
- typename IntersectionInfo,
- typename RobustPolicy
->
-inline bool assign_next_ip(G1 const& g1, G2 const& g2,
- Turns& turns,
- typename boost::range_iterator<Turns>::type& ip,
- GeometryOut& current_output,
- IntersectionInfo& info,
- segment_identifier& seg_id,
- RobustPolicy const& robust_policy)
-{
- info.visited.set_visited();
- set_visited_for_continue(*ip, info);
+ inline bool traverse_possible(signed_size_type turn_index) const
+ {
+ if (turn_index == -1)
+ {
+ return false;
+ }
+
+ turn_type const& turn = m_turns[turn_index];
+
+ // It is not a dead end if there is an operation to continue, or of
+ // there is a cluster (assuming for now we can get out of the cluster)
+ return turn.cluster_id >= 0
+ || turn.has(OperationType)
+ || turn.has(operation_continue);
+ }
- // If there is no next IP on this segment
- if (info.enriched.next_ip_index < 0)
+ inline bool select_operation(turn_type& turn,
+ signed_size_type start_turn_index,
+ segment_identifier const& seg_id,
+ int& selected_op_index)
{
- if (info.enriched.travels_to_vertex_index < 0
- || info.enriched.travels_to_ip_index < 0)
+ if (turn.discarded)
{
return false;
}
- BOOST_GEOMETRY_ASSERT(info.enriched.travels_to_vertex_index >= 0);
- BOOST_GEOMETRY_ASSERT(info.enriched.travels_to_ip_index >= 0);
+ bool result = false;
+
+ typename turn_operation_type::comparable_distance_type
+ max_remaining_distance = 0;
- if (info.seg_id.source_index == 0)
+ selected_op_index = -1;
+ for (int i = 0; i < 2; i++)
{
- geometry::copy_segments<Reverse1>(g1, info.seg_id,
- info.enriched.travels_to_vertex_index,
- robust_policy,
- current_output);
+ turn_operation_type const& op = turn.operations[i];
+ if (op.visited.started())
+ {
+ selected_op_index = i;
+ return true;
+ }
+
+ signed_size_type const next_turn_index = get_next_turn_index(op);
+
+ // In some cases there are two alternatives.
+ // For "ii", take the other one (alternate)
+ // UNLESS the other one is already visited
+ // For "uu", take the same one (see above);
+ // For "cc", take either one, but if there is a starting one,
+ // take that one. If next is dead end, skip that one.
+ if ( (op.operation == operation_continue
+ && traverse_possible(next_turn_index)
+ && ! result)
+ || (op.operation == OperationType
+ && ! op.visited.finished()
+ && (! result
+ || select_source(next_turn_index, op.seg_id, seg_id)
+ )
+ )
+ )
+ {
+ if (op.operation == operation_continue)
+ {
+ max_remaining_distance = op.remaining_distance;
+ }
+ selected_op_index = i;
+ debug_traverse(turn, op, " Candidate");
+ result = true;
+ }
+
+ if (op.operation == operation_continue && result)
+ {
+ if (next_turn_index == start_turn_index)
+ {
+ selected_op_index = i;
+ debug_traverse(turn, op, " Candidate override (start)");
+ }
+ else if (op.remaining_distance > max_remaining_distance)
+ {
+ max_remaining_distance = op.remaining_distance;
+ selected_op_index = i;
+ debug_traverse(turn, op, " Candidate override (remaining)");
+ }
+ }
}
- else
+
+ if (result)
{
- geometry::copy_segments<Reverse2>(g2, info.seg_id,
- info.enriched.travels_to_vertex_index,
- robust_policy,
- current_output);
+ debug_traverse(turn, turn.operations[selected_op_index], " Accepted");
}
- seg_id = info.seg_id;
- ip = boost::begin(turns) + info.enriched.travels_to_ip_index;
+
+ return result;
}
- else
+
+ inline bool select_from_cluster(signed_size_type& turn_index,
+ int& op_index, signed_size_type start_turn_index,
+ sbs_type const& sbs, bool allow_pass_rank)
{
- ip = boost::begin(turns) + info.enriched.next_ip_index;
- seg_id = info.seg_id;
+ bool const is_union = OperationType == operation_union;
+ bool const is_intersection = OperationType == operation_intersection;
+
+ std::size_t selected_rank = 0;
+ std::size_t min_rank = 0;
+ bool result = false;
+ for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
+ {
+ typename sbs_type::rp const& ranked_point = sbs.m_ranked_points[i];
+ if (result && ranked_point.main_rank > selected_rank)
+ {
+ return result;
+ }
+
+ turn_type const& ranked_turn = m_turns[ranked_point.turn_index];
+ turn_operation_type const& ranked_op = ranked_turn.operations[ranked_point.op_index];
+
+ if (result && ranked_op.visited.finalized())
+ {
+ // One of the arcs in the same direction as the selected result
+ // is already traversed.
+ return false;
+ }
+
+ if (! allow_pass_rank && ranked_op.visited.finalized())
+ {
+ // Skip this one, go to next
+ min_rank = ranked_point.main_rank;
+ continue;
+ }
+
+ if (ranked_point.index == sort_by_side::index_to
+ && (ranked_point.main_rank > min_rank
+ || ranked_turn.both(operation_continue)))
+ {
+ if ((is_union
+ && ranked_op.enriched.count_left == 0
+ && ranked_op.enriched.count_right > 0)
+ || (is_intersection
+ && ranked_op.enriched.count_right == 2))
+ {
+ if (result && ranked_point.turn_index != start_turn_index)
+ {
+ // Don't override - only override if arrive at start
+ continue;
+ }
+
+ turn_index = ranked_point.turn_index;
+ op_index = ranked_point.op_index;
+
+ if (is_intersection
+ && ranked_turn.both(operation_intersection)
+ && ranked_op.visited.finalized())
+ {
+ // Override:
+ // For a ii turn, even though one operation might be selected,
+ // it should take the other one if the first one is used in a completed ring
+ op_index = 1 - ranked_point.op_index;
+ }
+
+ result = true;
+ selected_rank = ranked_point.main_rank;
+ }
+ else if (! allow_pass_rank)
+ {
+ return result;
+ }
+ }
+ }
+ return result;
}
- detail::overlay::append_no_dups_or_spikes(current_output, ip->point,
- robust_policy);
+ inline bool select_turn_from_cluster(signed_size_type& turn_index,
+ int& op_index, signed_size_type start_turn_index,
+ point_type const& point)
+ {
+ bool const is_union = OperationType == operation_union;
- return true;
-}
+ turn_type const& turn = m_turns[turn_index];
+ BOOST_ASSERT(turn.cluster_id >= 0);
+ typename Clusters::const_iterator mit = m_clusters.find(turn.cluster_id);
+ BOOST_ASSERT(mit != m_clusters.end());
-inline bool select_source(operation_type operation,
- signed_size_type source1,
- signed_size_type source2)
-{
- return (operation == operation_intersection && source1 != source2)
- || (operation == operation_union && source1 == source2)
- ;
-}
+ std::set<signed_size_type> const& ids = mit->second;
+ sbs_type sbs;
+ sbs.set_origin(point);
-template
-<
- typename Turn,
- typename Iterator
->
-inline bool select_next_ip(operation_type operation,
- Turn& turn,
- segment_identifier const& seg_id,
- Iterator& selected)
-{
- if (turn.discarded)
+ for (typename std::set<signed_size_type>::const_iterator sit = ids.begin();
+ sit != ids.end(); ++sit)
+ {
+ signed_size_type cluster_turn_index = *sit;
+ turn_type const& cluster_turn = m_turns[cluster_turn_index];
+ if (cluster_turn.discarded)
+ {
+ // Defensive check, discarded turns should not be in cluster
+ continue;
+ }
+
+ for (int i = 0; i < 2; i++)
+ {
+ sbs.add(cluster_turn.operations[i], cluster_turn_index, i,
+ m_geometry1, m_geometry2, false);
+ }
+ }
+
+ sbs.apply(turn.point);
+
+ int open_count = 0;
+ if (is_union)
+ {
+ // Check how many open spaces there are.
+ // TODO: might be moved to sbs itself, though it also uses turns
+
+ std::size_t last_rank = 0;
+ for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
+ {
+ typename sbs_type::rp const& ranked_point = sbs.m_ranked_points[i];
+
+ if (ranked_point.main_rank > last_rank
+ && ranked_point.index == sort_by_side::index_to)
+ {
+ turn_type const& ranked_turn = m_turns[ranked_point.turn_index];
+ turn_operation_type const& ranked_op = ranked_turn.operations[ranked_point.op_index];
+ if (ranked_op.enriched.count_left == 0
+ && ranked_op.enriched.count_right > 0)
+ {
+ open_count++;
+ last_rank = ranked_point.main_rank;
+ }
+ }
+ }
+ }
+
+ bool allow = false;
+ if (open_count > 1)
+ {
+ sbs.reverse();
+ allow = true;
+ }
+
+ return select_from_cluster(turn_index, op_index, start_turn_index, sbs, allow);
+ }
+
+ inline void change_index_for_self_turn(signed_size_type& to_vertex_index,
+ turn_type const& start_turn,
+ turn_operation_type const& start_op,
+ int start_op_index)
{
- return false;
+ turn_operation_type const& other_op
+ = start_turn.operations[1 - start_op_index];
+ if (start_op.seg_id.source_index != other_op.seg_id.source_index)
+ {
+ // Not a buffer/self-turn
+ return;
+ }
+
+ // It travels to itself, can happen. If this is a buffer, it can
+ // sometimes travel to itself in the following configuration:
+ //
+ // +---->--+
+ // | |
+ // | +---*----+ *: one turn, with segment index 2/7
+ // | | | |
+ // | +---C | C: closing point (start/end)
+ // | |
+ // +------------+
+ //
+ // If it starts on segment 2 and travels to itself on segment 2, that
+ // should be corrected to 7 because that is the shortest path
+ //
+ // Also a uu turn (touching with another buffered ring) might have this
+ // apparent configuration, but there it should
+ // always travel the whole ring
+
+ bool const correct
+ = ! start_turn.both(operation_union)
+ && start_op.seg_id.segment_index == to_vertex_index;
+
+#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSE)
+ std::cout << " WARNING: self-buffer "
+ << " correct=" << correct
+ << " turn=" << operation_char(start_turn.operations[0].operation)
+ << operation_char(start_turn.operations[1].operation)
+ << " start=" << start_op.seg_id.segment_index
+ << " from=" << to_vertex_index
+ << " to=" << other_op.enriched.travels_to_vertex_index
+ << std::endl;
+#endif
+
+ if (correct)
+ {
+ to_vertex_index = other_op.enriched.travels_to_vertex_index;
+ }
}
- bool has_tp = false;
+ template <typename Ring>
+ inline traverse_error_type travel_to_next_turn(signed_size_type start_turn_index,
+ int start_op_index,
+ signed_size_type& turn_index,
+ int& op_index,
+ segment_identifier& seg_id,
+ Ring& current_ring,
+ bool is_start)
+ {
+ int const previous_op_index = op_index;
+ signed_size_type const previous_turn_index = turn_index;
+ turn_type& previous_turn = m_turns[turn_index];
+ turn_operation_type& previous_op = previous_turn.operations[op_index];
- typedef typename std::iterator_traits
- <
- Iterator
- >::value_type operation_type;
+ // If there is no next IP on this segment
+ if (previous_op.enriched.next_ip_index < 0)
+ {
+ if (previous_op.enriched.travels_to_vertex_index < 0
+ || previous_op.enriched.travels_to_ip_index < 0)
+ {
+ return is_start
+ ? traverse_error_no_next_ip_at_start
+ : traverse_error_no_next_ip;
+ }
+
+ signed_size_type to_vertex_index = previous_op.enriched.travels_to_vertex_index;
+
+ if (is_start &&
+ previous_op.enriched.travels_to_ip_index == start_turn_index)
+ {
+ change_index_for_self_turn(to_vertex_index, previous_turn,
+ previous_op, start_op_index);
+ }
+
+ if (previous_op.seg_id.source_index == 0)
+ {
+ geometry::copy_segments<Reverse1>(m_geometry1,
+ previous_op.seg_id, to_vertex_index,
+ m_robust_policy, current_ring);
+ }
+ else
+ {
+ geometry::copy_segments<Reverse2>(m_geometry2,
+ previous_op.seg_id, to_vertex_index,
+ m_robust_policy, current_ring);
+ }
+ seg_id = previous_op.seg_id;
+ turn_index = previous_op.enriched.travels_to_ip_index;
+ }
+ else
+ {
+ turn_index = previous_op.enriched.next_ip_index;
+ seg_id = previous_op.seg_id;
+ }
+
+ // turn_index is not yet finally selected, can change for clusters
+ bool const has_cluster = m_turns[turn_index].cluster_id >= 0;
+ if (has_cluster)
+ {
+
+ if (! select_turn_from_cluster(turn_index, op_index,
+ start_turn_index, current_ring.back()))
+ {
+ return is_start
+ ? traverse_error_no_next_ip_at_start
+ : traverse_error_no_next_ip;
+ }
+
+ if (is_start && turn_index == previous_turn_index)
+ {
+ op_index = previous_op_index;
+ }
+ }
+
+ turn_type& current_turn = m_turns[turn_index];
+ detail::overlay::append_no_dups_or_spikes(current_ring, current_turn.point,
+ m_robust_policy);
+
+ if (is_start)
+ {
+ // Register the start
+ previous_op.visited.set_started();
+ m_visitor.visit_traverse(m_turns, previous_turn, previous_op, "Start");
+ }
+
+ if (! has_cluster)
+ {
+ if (! select_operation(current_turn,
+ start_turn_index,
+ seg_id,
+ op_index))
+ {
+ return is_start
+ ? traverse_error_dead_end_at_start
+ : traverse_error_dead_end;
+ }
+ }
+
+ turn_operation_type& op = current_turn.operations[op_index];
+ if (op.visited.finalized() || op.visited.visited())
+ {
+ return traverse_error_visit_again;
+ }
- typename operation_type::comparable_distance_type
- max_remaining_distance = 0;
+ // Register the visit
+ set_visited(current_turn, op);
+ m_visitor.visit_traverse(m_turns, current_turn, op, "Visit");
- selected = boost::end(turn.operations);
- for (Iterator it = boost::begin(turn.operations);
- it != boost::end(turn.operations);
- ++it)
+ return traverse_error_none;
+ }
+
+ inline void finalize_visit_info()
{
- if (it->visited.started())
+ for (typename boost::range_iterator<Turns>::type
+ it = boost::begin(m_turns);
+ it != boost::end(m_turns);
+ ++it)
{
- selected = it;
- //std::cout << " RETURN";
- return true;
+ turn_type& turn = *it;
+ for (int i = 0; i < 2; i++)
+ {
+ turn_operation_type& op = turn.operations[i];
+ op.visited.finalize();
+ }
}
+ }
- // In some cases there are two alternatives.
- // For "ii", take the other one (alternate)
- // UNLESS the other one is already visited
- // For "uu", take the same one (see above);
- // For "cc", take either one, but if there is a starting one,
- // take that one.
- if ( (it->operation == operation_continue
- && (! has_tp || it->visited.started()
- )
- )
- || (it->operation == operation
- && ! it->visited.finished()
- && (! has_tp
- || select_source(operation,
- it->seg_id.source_index, seg_id.source_index)
- )
- )
- )
+ inline void set_visited(turn_type& turn, turn_operation_type& op)
+ {
+ // On "continue", set "visited" for ALL directions in this turn
+ if (op.operation == detail::overlay::operation_continue)
{
- if (it->operation == operation_continue)
+ for (int i = 0; i < 2; i++)
{
- max_remaining_distance = it->remaining_distance;
+ turn_operation_type& op = turn.operations[i];
+ if (op.visited.none())
+ {
+ op.visited.set_visited();
+ }
}
- selected = it;
- debug_traverse(turn, *it, " Candidate");
- has_tp = true;
+ }
+ else
+ {
+ op.visited.set_visited();
+ }
+ }
+
+
+ template <typename Ring>
+ inline traverse_error_type traverse(Ring& ring,
+ signed_size_type start_turn_index, int start_op_index)
+ {
+ turn_type const& start_turn = m_turns[start_turn_index];
+ turn_operation_type& start_op = m_turns[start_turn_index].operations[start_op_index];
+
+ detail::overlay::append_no_dups_or_spikes(ring, start_turn.point,
+ m_robust_policy);
+
+ signed_size_type current_turn_index = start_turn_index;
+ int current_op_index = start_op_index;
+ segment_identifier current_seg_id;
+
+ traverse_error_type error = travel_to_next_turn(start_turn_index,
+ start_op_index,
+ current_turn_index, current_op_index, current_seg_id,
+ ring, true);
+
+ if (error != traverse_error_none)
+ {
+ // This is not necessarily a problem, it happens for clustered turns
+ // which are "build in" or otherwise point inwards
+ return error;
+ }
+
+ if (current_turn_index == start_turn_index)
+ {
+ start_op.visited.set_finished();
+ m_visitor.visit_traverse(m_turns, m_turns[current_turn_index], start_op, "Early finish");
+ return traverse_error_none;
}
- if (it->operation == operation_continue && has_tp)
+ std::size_t const max_iterations = 2 + 2 * m_turns.size();
+ for (std::size_t i = 0; i <= max_iterations; i++)
{
- if (it->remaining_distance > max_remaining_distance)
+ // We assume clockwise polygons only, non self-intersecting, closed.
+ // However, the input might be different, and checking validity
+ // is up to the library user.
+
+ // Therefore we make here some sanity checks. If the input
+ // violates the assumptions, the output polygon will not be correct
+ // but the routine will stop and output the current polygon, and
+ // will continue with the next one.
+
+ // Below three reasons to stop.
+ error = travel_to_next_turn(start_turn_index, start_op_index,
+ current_turn_index, current_op_index, current_seg_id,
+ ring, false);
+
+ if (error != traverse_error_none)
{
- max_remaining_distance = it->remaining_distance;
- selected = it;
- debug_traverse(turn, *it, " Candidate override");
+ return error;
+ }
+
+ if (current_turn_index == start_turn_index
+ && current_op_index == start_op_index)
+ {
+ start_op.visited.set_finished();
+ m_visitor.visit_traverse(m_turns, start_turn, start_op, "Finish");
+ return traverse_error_none;
}
}
+
+ return traverse_error_endless_loop;
}
- if (has_tp)
+ template <typename Rings>
+ void traverse_with_operation(turn_type const& start_turn,
+ std::size_t turn_index, int op_index,
+ Rings& rings, std::size_t& finalized_ring_size,
+ typename Backtrack::state_type& state)
{
- debug_traverse(turn, *selected, " Accepted");
+ typedef typename boost::range_value<Rings>::type ring_type;
+
+ turn_operation_type const& start_op = start_turn.operations[op_index];
+
+ if (! start_op.visited.none()
+ || ! start_op.enriched.startable
+ || start_op.visited.rejected()
+ || ! (start_op.operation == OperationType
+ || start_op.operation == detail::overlay::operation_continue))
+ {
+ return;
+ }
+
+ ring_type ring;
+ traverse_error_type traverse_error = traverse(ring, turn_index, op_index);
+
+ if (traverse_error == traverse_error_none)
+ {
+ std::size_t const min_num_points
+ = core_detail::closure::minimum_ring_size
+ <
+ geometry::closure<ring_type>::value
+ >::value;
+
+ if (geometry::num_points(ring) >= min_num_points)
+ {
+ clean_closing_dups_and_spikes(ring, m_robust_policy);
+ rings.push_back(ring);
+
+ finalize_visit_info();
+ finalized_ring_size++;
+ }
+ }
+ else
+ {
+ Backtrack::apply(
+ finalized_ring_size,
+ rings, ring, m_turns, start_turn,
+ m_turns[turn_index].operations[op_index],
+ traverse_error,
+ m_geometry1, m_geometry2, m_robust_policy,
+ state, m_visitor);
+ }
}
+ template <typename Rings>
+ void iterate(Rings& rings, std::size_t& finalized_ring_size,
+ typename Backtrack::state_type& state,
+ int pass)
+ {
+ if (pass == 1)
+ {
+ if (OperationType == operation_intersection)
+ {
+ // Second pass currently only used for uu
+ return;
+ }
+ if (! m_has_uu)
+ {
+ // There is no uu found in first pass
+ return;
+ }
+ if (m_has_only_uu)
+ {
+ m_switch_at_uu = false;
+ }
+ }
+
+ // Iterate through all unvisited points
+ for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index)
+ {
+ turn_type const& start_turn = m_turns[turn_index];
- return has_tp;
-}
+ if (start_turn.discarded || start_turn.blocked())
+ {
+ // Skip discarded and blocked turns
+ continue;
+ }
+ if (OperationType == operation_union)
+ {
+ if (start_turn.both(operation_union))
+ {
+ // Start with a uu-turn only in the second pass
+ m_has_uu = true;
+ if (pass == 0)
+ {
+ continue;
+ }
+ }
+ else
+ {
+ m_has_only_uu = false;
+ }
+ }
+
+ for (int op_index = 0; op_index < 2; op_index++)
+ {
+ traverse_with_operation(start_turn, turn_index, op_index,
+ rings, finalized_ring_size, state);
+ }
+ }
+ }
+private :
+ Geometry1 const& m_geometry1;
+ Geometry2 const& m_geometry2;
+ Turns& m_turns;
+ Clusters const& m_clusters;
+ RobustPolicy const& m_robust_policy;
+ Visitor& m_visitor;
+
+ // Next members are only used for operation union
+ bool m_has_uu;
+ bool m_has_only_uu;
+ bool m_switch_at_uu;
+};
/*!
@@ -256,185 +811,45 @@ template
bool Reverse1, bool Reverse2,
typename Geometry1,
typename Geometry2,
+ operation_type OperationType,
typename Backtrack = backtrack_check_self_intersections<Geometry1, Geometry2>
>
class traverse
{
public :
- template <typename RobustPolicy, typename Turns, typename Rings>
+ template
+ <
+ typename RobustPolicy,
+ typename Turns,
+ typename Rings,
+ typename Visitor,
+ typename Clusters
+ >
static inline void apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
- detail::overlay::operation_type operation,
RobustPolicy const& robust_policy,
- Turns& turns, Rings& rings)
+ Turns& turns, Rings& rings,
+ Clusters const& clusters,
+ Visitor& visitor)
{
- typedef typename boost::range_value<Rings>::type ring_type;
- typedef typename boost::range_iterator<Turns>::type turn_iterator;
- typedef typename boost::range_value<Turns>::type turn_type;
- typedef typename boost::range_iterator
+ traversal
<
- typename turn_type::container_type
- >::type turn_operation_iterator_type;
+ Reverse1, Reverse2, OperationType,
+ Geometry1, Geometry2,
+ Turns, Clusters,
+ RobustPolicy, Visitor,
+ Backtrack
+ > trav(geometry1, geometry2, turns, clusters,
+ robust_policy, visitor);
- std::size_t const min_num_points
- = core_detail::closure::minimum_ring_size
- <
- geometry::closure<ring_type>::value
- >::value;
-
- std::size_t size_at_start = boost::size(rings);
+ std::size_t finalized_ring_size = boost::size(rings);
typename Backtrack::state_type state;
- do
- {
- state.reset();
- // Iterate through all unvisited points
- for (turn_iterator it = boost::begin(turns);
- state.good() && it != boost::end(turns);
- ++it)
- {
- // Skip discarded ones
- if (! (it->discarded || ! it->selectable_start || it->blocked()))
- {
- for (turn_operation_iterator_type iit = boost::begin(it->operations);
- state.good() && iit != boost::end(it->operations);
- ++iit)
- {
- if (iit->visited.none()
- && ! iit->visited.rejected()
- && (iit->operation == operation
- || iit->operation == detail::overlay::operation_continue)
- )
- {
- set_visited_for_continue(*it, *iit);
-
- ring_type current_output;
- detail::overlay::append_no_dups_or_spikes(current_output,
- it->point, robust_policy);
-
- turn_iterator current = it;
- turn_operation_iterator_type current_iit = iit;
- segment_identifier current_seg_id;
-
- if (! detail::overlay::assign_next_ip<Reverse1, Reverse2>(
- geometry1, geometry2,
- turns,
- current, current_output,
- *iit, current_seg_id,
- robust_policy))
- {
- Backtrack::apply(
- size_at_start,
- rings, current_output, turns, *current_iit,
- "No next IP",
- geometry1, geometry2, robust_policy, state);
- }
-
- if (! detail::overlay::select_next_ip(
- operation,
- *current,
- current_seg_id,
- current_iit))
- {
- Backtrack::apply(
- size_at_start,
- rings, current_output, turns, *iit,
- "Dead end at start",
- geometry1, geometry2, robust_policy, state);
- }
- else
- {
-
- iit->visited.set_started();
- detail::overlay::debug_traverse(*it, *iit, "-> Started");
- detail::overlay::debug_traverse(*current, *current_iit, "Selected ");
-
-
- typename boost::range_size<Turns>::type i = 0;
-
- while (current_iit != iit && state.good())
- {
- if (current_iit->visited.visited())
- {
- // It visits a visited node again, without passing the start node.
- // This makes it suspicious for endless loops
- Backtrack::apply(
- size_at_start,
- rings, current_output, turns, *iit,
- "Visit again",
- geometry1, geometry2, robust_policy, state);
- }
- else
- {
-
-
- // We assume clockwise polygons only, non self-intersecting, closed.
- // However, the input might be different, and checking validity
- // is up to the library user.
-
- // Therefore we make here some sanity checks. If the input
- // violates the assumptions, the output polygon will not be correct
- // but the routine will stop and output the current polygon, and
- // will continue with the next one.
-
- // Below three reasons to stop.
- detail::overlay::assign_next_ip<Reverse1, Reverse2>(
- geometry1, geometry2,
- turns, current, current_output,
- *current_iit, current_seg_id,
- robust_policy);
-
- if (! detail::overlay::select_next_ip(
- operation,
- *current,
- current_seg_id,
- current_iit))
- {
- // Should not occur in valid (non-self-intersecting) polygons
- // Should not occur in self-intersecting polygons without spikes
- // Might occur in polygons with spikes
- Backtrack::apply(
- size_at_start,
- rings, current_output, turns, *iit,
- "Dead end",
- geometry1, geometry2, robust_policy, state);
- }
- else
- {
- detail::overlay::debug_traverse(*current, *current_iit, "Selected ");
- }
-
- if (i++ > 2 + 2 * turns.size())
- {
- // Sanity check: there may be never more loops
- // than turn points.
- // Turn points marked as "ii" can be visited twice.
- Backtrack::apply(
- size_at_start,
- rings, current_output, turns, *iit,
- "Endless loop",
- geometry1, geometry2, robust_policy, state);
- }
- }
- }
-
- if (state.good())
- {
- iit->visited.set_finished();
- detail::overlay::debug_traverse(*current, *iit, "->Finished");
- if (geometry::num_points(current_output) >= min_num_points)
- {
- clean_closing_dups_and_spikes(current_output, robust_policy);
- rings.push_back(current_output);
- }
- }
- }
- }
- }
- }
- }
- } while (! state.good());
+ for (int pass = 0; pass < 2; pass++)
+ {
+ trav.iterate(rings, finalized_ring_size, state, pass);
+ }
}
};
diff --git a/boost/geometry/algorithms/detail/overlay/turn_info.hpp b/boost/geometry/algorithms/detail/overlay/turn_info.hpp
index 1ac77d5796..699997fc38 100644
--- a/boost/geometry/algorithms/detail/overlay/turn_info.hpp
+++ b/boost/geometry/algorithms/detail/overlay/turn_info.hpp
@@ -58,6 +58,8 @@ enum method_type
template <typename Point, typename SegmentRatio>
struct turn_operation
{
+ typedef SegmentRatio segment_ratio_type;
+
operation_type operation;
segment_identifier seg_id;
SegmentRatio fraction;
@@ -91,23 +93,25 @@ template
struct turn_info
{
typedef Point point_type;
+ typedef SegmentRatio segment_ratio_type;
typedef Operation turn_operation_type;
typedef Container container_type;
Point point;
method_type method;
+ int cluster_id;
bool discarded;
- bool selectable_start; // Can be used as starting-turn in traverse
bool colocated;
-
+ bool switch_source; // For u/u turns which can either switch or not
Container operations;
inline turn_info()
: method(method_none)
+ , cluster_id(-1)
, discarded(false)
- , selectable_start(true)
, colocated(false)
+ , switch_source(false)
{}
inline bool both(operation_type type) const
diff --git a/boost/geometry/algorithms/detail/overlay/visit_info.hpp b/boost/geometry/algorithms/detail/overlay/visit_info.hpp
index 4284a801a1..9e1e6b9056 100644
--- a/boost/geometry/algorithms/detail/overlay/visit_info.hpp
+++ b/boost/geometry/algorithms/detail/overlay/visit_info.hpp
@@ -28,11 +28,13 @@ private :
int m_visit_code;
bool m_rejected;
+ bool m_final;
public:
inline visit_info()
: m_visit_code(0)
, m_rejected(false)
+ , m_final(false)
{}
inline void set_visited() { m_visit_code = VISITED; }
@@ -49,15 +51,24 @@ public:
inline bool started() const { return m_visit_code == STARTED; }
inline bool finished() const { return m_visit_code == FINISHED; }
inline bool rejected() const { return m_rejected; }
+ inline bool finalized() const { return m_final; }
inline void clear()
{
- if (! rejected())
+ if (! m_rejected && ! m_final)
{
m_visit_code = NONE;
}
}
+ inline void finalize()
+ {
+ if (visited() || started() || finished() )
+ {
+ m_final = true;
+ }
+ }
+
#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
friend std::ostream& operator<<(std::ostream &os, visit_info const& v)
{
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 399c8fbefc..607ba81531 100644
--- a/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp
+++ b/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp
@@ -17,6 +17,7 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_IS_EQUAL_OR_SPIKE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_IS_EQUAL_OR_SPIKE_HPP
+#include <boost/geometry/algorithms/detail/direction_code.hpp>
#include <boost/geometry/algorithms/detail/recalculate.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
#include <boost/geometry/strategies/side.hpp>
@@ -31,17 +32,6 @@ namespace boost { namespace geometry
namespace detail
{
-template <std::size_t Index, typename Point1, typename Point2>
-inline int sign_of_difference(Point1 const& point1, Point2 const& point2)
-{
- return
- math::equals(geometry::get<Index>(point1), geometry::get<Index>(point2))
- ?
- 0
- :
- (geometry::get<Index>(point1) > geometry::get<Index>(point2) ? 1 : -1);
-}
-
// Checks if a point ("last_point") causes a spike w.r.t.
// the specified two other points (segment_a, segment_b)
//
diff --git a/boost/geometry/algorithms/detail/recalculate.hpp b/boost/geometry/algorithms/detail/recalculate.hpp
index 056f7c6e1d..fd3ed6b8da 100644
--- a/boost/geometry/algorithms/detail/recalculate.hpp
+++ b/boost/geometry/algorithms/detail/recalculate.hpp
@@ -21,8 +21,10 @@
#include <boost/mpl/if.hpp>
#include <boost/numeric/conversion/bounds.hpp>
#include <boost/numeric/conversion/cast.hpp>
-#include <boost/range.hpp>
-#include <boost/type_traits.hpp>
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/iterator.hpp>
+#include <boost/range/size.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/algorithms/append.hpp>
diff --git a/boost/geometry/algorithms/detail/relate/result.hpp b/boost/geometry/algorithms/detail/relate/result.hpp
index b7b9264449..a92badf65b 100644
--- a/boost/geometry/algorithms/detail/relate/result.hpp
+++ b/boost/geometry/algorithms/detail/relate/result.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2015.
-// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2016.
+// Modifications copyright (c) 2013-2016 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -133,9 +133,6 @@ public:
matrix_handler()
{}
- matrix_handler(Matrix const&)
- {}
-
result_type const& result() const
{
return m_matrix;
@@ -604,10 +601,6 @@ public:
bool interrupt;
- inline mask_handler()
- : interrupt(false)
- {}
-
inline explicit mask_handler(Mask const& m)
: interrupt(false)
, m_mask(m)
diff --git a/boost/geometry/algorithms/difference.hpp b/boost/geometry/algorithms/difference.hpp
index 780436f015..dc31c7db4d 100644
--- a/boost/geometry/algorithms/difference.hpp
+++ b/boost/geometry/algorithms/difference.hpp
@@ -159,7 +159,7 @@ inline void difference(Geometry1 const& geometry1,
detail::difference::difference_insert<geometry_out>(
geometry1, geometry2, robust_policy,
- std::back_inserter(output_collection));
+ range::back_inserter(output_collection));
}
diff --git a/boost/geometry/algorithms/length.hpp b/boost/geometry/algorithms/length.hpp
index 58324bcc80..cf5234da1a 100644
--- a/boost/geometry/algorithms/length.hpp
+++ b/boost/geometry/algorithms/length.hpp
@@ -24,8 +24,6 @@
#include <boost/concept_check.hpp>
#include <boost/core/ignore_unused.hpp>
-#include <boost/range.hpp>
-
#include <boost/mpl/fold.hpp>
#include <boost/mpl/greater.hpp>
#include <boost/mpl/if.hpp>
@@ -34,8 +32,10 @@
#include <boost/mpl/set.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/transform.hpp>
-#include <boost/type_traits.hpp>
-
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/iterator.hpp>
+#include <boost/range/value_type.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
diff --git a/boost/geometry/algorithms/remove_spikes.hpp b/boost/geometry/algorithms/remove_spikes.hpp
index a96a2c29d0..080db92f6d 100644
--- a/boost/geometry/algorithms/remove_spikes.hpp
+++ b/boost/geometry/algorithms/remove_spikes.hpp
@@ -139,7 +139,7 @@ struct range_remove_spikes
// Copy output
geometry::clear(range);
- std::copy(cleaned.begin(), cleaned.end(), std::back_inserter(range));
+ std::copy(cleaned.begin(), cleaned.end(), range::back_inserter(range));
}
};
diff --git a/boost/geometry/algorithms/simplify.hpp b/boost/geometry/algorithms/simplify.hpp
index 9dd87f61a9..0b28eb7d15 100644
--- a/boost/geometry/algorithms/simplify.hpp
+++ b/boost/geometry/algorithms/simplify.hpp
@@ -77,7 +77,7 @@ struct simplify_copy
{
std::copy
(
- boost::begin(range), boost::end(range), std::back_inserter(out)
+ boost::begin(range), boost::end(range), geometry::range::back_inserter(out)
);
}
};
@@ -113,7 +113,7 @@ struct simplify_range
{
simplify_range_insert::apply
(
- range, std::back_inserter(out), max_distance, strategy
+ range, geometry::range::back_inserter(out), max_distance, strategy
);
}
}
diff --git a/boost/geometry/algorithms/sym_difference.hpp b/boost/geometry/algorithms/sym_difference.hpp
index 6c49ca634c..77a20c0885 100644
--- a/boost/geometry/algorithms/sym_difference.hpp
+++ b/boost/geometry/algorithms/sym_difference.hpp
@@ -332,7 +332,7 @@ inline void sym_difference(Geometry1 const& geometry1,
detail::sym_difference::sym_difference_insert<geometry_out>(
geometry1, geometry2, robust_policy,
- std::back_inserter(output_collection));
+ range::back_inserter(output_collection));
}
diff --git a/boost/geometry/algorithms/transform.hpp b/boost/geometry/algorithms/transform.hpp
index c7f3bd6cbb..f6748b11e3 100644
--- a/boost/geometry/algorithms/transform.hpp
+++ b/boost/geometry/algorithms/transform.hpp
@@ -162,7 +162,7 @@ struct transform_polygon
geometry::clear(poly2);
if (!transform_range_out<point2_type>(geometry::exterior_ring(poly1),
- std::back_inserter(geometry::exterior_ring(poly2)), strategy))
+ range::back_inserter(geometry::exterior_ring(poly2)), strategy))
{
return false;
}
@@ -189,7 +189,7 @@ struct transform_polygon
for ( ; it1 != boost::end(rings1); ++it1, ++it2)
{
if ( ! transform_range_out<point2_type>(*it1,
- std::back_inserter(*it2),
+ range::back_inserter(*it2),
strategy) )
{
return false;
@@ -228,7 +228,7 @@ struct transform_range
// Should NOT be done here!
// geometry::clear(range2);
return transform_range_out<point_type>(range1,
- std::back_inserter(range2), strategy);
+ range::back_inserter(range2), strategy);
}
};
diff --git a/boost/geometry/algorithms/union.hpp b/boost/geometry/algorithms/union.hpp
index ff16c60ea1..d15ee7655f 100644
--- a/boost/geometry/algorithms/union.hpp
+++ b/boost/geometry/algorithms/union.hpp
@@ -271,7 +271,7 @@ inline void union_(Geometry1 const& geometry1,
concept::check<geometry_out>();
detail::union_::union_insert<geometry_out>(geometry1, geometry2,
- std::back_inserter(output_collection));
+ range::back_inserter(output_collection));
}
diff --git a/boost/geometry/core/access.hpp b/boost/geometry/core/access.hpp
index 57f925763d..866fb19a4d 100644
--- a/boost/geometry/core/access.hpp
+++ b/boost/geometry/core/access.hpp
@@ -17,9 +17,10 @@
#include <cstddef>
+#include <boost/core/ignore_unused.hpp>
#include <boost/mpl/assert.hpp>
-#include <boost/concept_check.hpp>
#include <boost/type_traits/is_pointer.hpp>
+#include <boost/type_traits/remove_pointer.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/point_type.hpp>
@@ -271,7 +272,7 @@ inline typename coordinate_type<Geometry>::type get(Geometry const& geometry
#endif
)
{
- boost::ignore_unused_variable_warning(dummy);
+ boost::ignore_unused(dummy);
typedef core_dispatch::access
<
@@ -306,7 +307,7 @@ inline void set(Geometry& geometry
#endif
)
{
- boost::ignore_unused_variable_warning(dummy);
+ boost::ignore_unused(dummy);
typedef core_dispatch::access
<
@@ -341,7 +342,7 @@ inline typename coordinate_type<Geometry>::type get(Geometry const& geometry
#endif
)
{
- boost::ignore_unused_variable_warning(dummy);
+ boost::ignore_unused(dummy);
typedef core_dispatch::indexed_access
<
@@ -378,7 +379,7 @@ inline void set(Geometry& geometry
#endif
)
{
- boost::ignore_unused_variable_warning(dummy);
+ boost::ignore_unused(dummy);
typedef core_dispatch::indexed_access
<
diff --git a/boost/geometry/core/closure.hpp b/boost/geometry/core/closure.hpp
index b69dcda140..405a5a5f35 100644
--- a/boost/geometry/core/closure.hpp
+++ b/boost/geometry/core/closure.hpp
@@ -22,11 +22,11 @@
#include <boost/mpl/assert.hpp>
#include <boost/mpl/size_t.hpp>
#include <boost/range/value_type.hpp>
-#include <boost/type_traits/remove_const.hpp>
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/util/bare_type.hpp>
namespace boost { namespace geometry
{
diff --git a/boost/geometry/core/coordinate_dimension.hpp b/boost/geometry/core/coordinate_dimension.hpp
index 85da6b424e..19022f2fd2 100644
--- a/boost/geometry/core/coordinate_dimension.hpp
+++ b/boost/geometry/core/coordinate_dimension.hpp
@@ -18,7 +18,6 @@
#include <cstddef>
#include <boost/mpl/assert.hpp>
-#include <boost/mpl/equal_to.hpp>
#include <boost/static_assert.hpp>
#include <boost/geometry/core/point_type.hpp>
@@ -94,13 +93,7 @@ struct dimension
template <typename Geometry, int Dimensions>
inline void assert_dimension()
{
- BOOST_STATIC_ASSERT((
- boost::mpl::equal_to
- <
- boost::mpl::int_<geometry::dimension<Geometry>::value>,
- boost::mpl::int_<Dimensions>
- >::type::value
- ));
+ BOOST_STATIC_ASSERT(( static_cast<int>(dimension<Geometry>::value) == Dimensions ));
}
/*!
diff --git a/boost/geometry/core/coordinate_type.hpp b/boost/geometry/core/coordinate_type.hpp
index f138d59c8a..47c028fec2 100644
--- a/boost/geometry/core/coordinate_type.hpp
+++ b/boost/geometry/core/coordinate_type.hpp
@@ -17,8 +17,8 @@
#include <boost/mpl/assert.hpp>
-#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/util/bare_type.hpp>
#include <boost/geometry/util/promote_floating_point.hpp>
diff --git a/boost/geometry/core/exterior_ring.hpp b/boost/geometry/core/exterior_ring.hpp
index e5c97dd301..fa5a0a2b98 100644
--- a/boost/geometry/core/exterior_ring.hpp
+++ b/boost/geometry/core/exterior_ring.hpp
@@ -17,6 +17,7 @@
#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/remove_const.hpp>
diff --git a/boost/geometry/core/interior_type.hpp b/boost/geometry/core/interior_type.hpp
index e6c4537e41..66544b79af 100644
--- a/boost/geometry/core/interior_type.hpp
+++ b/boost/geometry/core/interior_type.hpp
@@ -17,7 +17,10 @@
#include <boost/mpl/assert.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/remove_reference.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
diff --git a/boost/geometry/core/mutable_range.hpp b/boost/geometry/core/mutable_range.hpp
index 9b53e40577..7cb5137830 100644
--- a/boost/geometry/core/mutable_range.hpp
+++ b/boost/geometry/core/mutable_range.hpp
@@ -17,8 +17,8 @@
#include <cstddef>
+#include <boost/range/value_type.hpp>
#include <boost/type_traits/remove_reference.hpp>
-#include <boost/range.hpp>
namespace boost { namespace geometry
diff --git a/boost/geometry/core/point_order.hpp b/boost/geometry/core/point_order.hpp
index d43adbd03a..df6d4bbfff 100644
--- a/boost/geometry/core/point_order.hpp
+++ b/boost/geometry/core/point_order.hpp
@@ -22,11 +22,11 @@
#include <boost/mpl/assert.hpp>
#include <boost/range/value_type.hpp>
-#include <boost/type_traits/remove_const.hpp>
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/util/bare_type.hpp>
namespace boost { namespace geometry
{
diff --git a/boost/geometry/core/radius.hpp b/boost/geometry/core/radius.hpp
index ee6d5d246f..6cbf6ac8f2 100644
--- a/boost/geometry/core/radius.hpp
+++ b/boost/geometry/core/radius.hpp
@@ -24,6 +24,7 @@
#include <cstddef>
#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_pointer.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
diff --git a/boost/geometry/core/reverse_dispatch.hpp b/boost/geometry/core/reverse_dispatch.hpp
index 2e4fb8005f..c95182a34d 100644
--- a/boost/geometry/core/reverse_dispatch.hpp
+++ b/boost/geometry/core/reverse_dispatch.hpp
@@ -18,9 +18,8 @@
#include <cstddef>
-#include <boost/type_traits.hpp>
#include <boost/mpl/if.hpp>
-#include <boost/mpl/greater.hpp>
+#include <boost/type_traits/integral_constant.hpp>
#include <boost/geometry/core/geometry_id.hpp>
diff --git a/boost/geometry/core/tag.hpp b/boost/geometry/core/tag.hpp
index 6bffcb932d..14a2242708 100644
--- a/boost/geometry/core/tag.hpp
+++ b/boost/geometry/core/tag.hpp
@@ -14,7 +14,6 @@
#ifndef BOOST_GEOMETRY_CORE_TAG_HPP
#define BOOST_GEOMETRY_CORE_TAG_HPP
-#include <boost/mpl/assert.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/bare_type.hpp>
diff --git a/boost/geometry/core/tag_cast.hpp b/boost/geometry/core/tag_cast.hpp
index cafd13cba9..e03d841f49 100644
--- a/boost/geometry/core/tag_cast.hpp
+++ b/boost/geometry/core/tag_cast.hpp
@@ -16,7 +16,7 @@
#include <boost/mpl/if.hpp>
-#include <boost/type_traits.hpp>
+#include <boost/type_traits/is_base_of.hpp>
namespace boost { namespace geometry
{
diff --git a/boost/geometry/extensions/algorithms/inverse.hpp b/boost/geometry/extensions/algorithms/inverse.hpp
new file mode 100644
index 0000000000..44f415be42
--- /dev/null
+++ b/boost/geometry/extensions/algorithms/inverse.hpp
@@ -0,0 +1,59 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright (c) 2015 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_INVERSE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_INVERSE_HPP
+
+#include <boost/geometry.hpp>
+
+namespace boost { namespace geometry
+{
+
+// TODO: this is shared with sectionalize, move to somewhere else (assign?)
+template <typename Box, typename Value>
+inline void enlarge_box(Box& box, Value value)
+{
+ geometry::set<0, 0>(box, geometry::get<0, 0>(box) - value);
+ geometry::set<0, 1>(box, geometry::get<0, 1>(box) - value);
+ geometry::set<1, 0>(box, geometry::get<1, 0>(box) + value);
+ geometry::set<1, 1>(box, geometry::get<1, 1>(box) + value);
+}
+
+// TODO: when this might be moved outside extensions it should of course
+// input/output a Geometry, instead of a WKT
+template <typename Geometry, typename Value>
+inline std::string inverse(std::string const& wkt, Value margin)
+{
+ Geometry geometry;
+ read_wkt(wkt, geometry);
+
+ geometry::correct(geometry);
+
+ geometry::model::box<typename point_type<Geometry>::type> env;
+ geometry::envelope(geometry, env);
+
+ // Make its envelope a bit larger
+ enlarge_box(env, margin);
+
+ Geometry env_as_polygon;
+ geometry::convert(env, env_as_polygon);
+
+ Geometry inversed_result;
+ geometry::difference(env_as_polygon, geometry, inversed_result);
+
+ std::ostringstream out;
+
+ out << geometry::wkt(inversed_result);
+ return out.str();
+}
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_INVERSE_HPP
diff --git a/boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp b/boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp
index 1616369da1..84f72aadcb 100644
--- a/boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp
+++ b/boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp
@@ -55,7 +55,7 @@ template <>
struct modify<false>
{
template <typename Ring, typename Point>
- static inline void push_back(Ring& ring, Point const& point)
+ static inline void push_back(Ring& /*ring*/, Point const& /*point*/)
{
}
diff --git a/boost/geometry/index/detail/rtree/pack_create.hpp b/boost/geometry/index/detail/rtree/pack_create.hpp
index e56ce076d2..d1491b8d47 100644
--- a/boost/geometry/index/detail/rtree/pack_create.hpp
+++ b/boost/geometry/index/detail/rtree/pack_create.hpp
@@ -200,6 +200,13 @@ private:
{}
template <typename Indexable>
+ explicit expandable_box(Indexable const& indexable)
+ : m_initialized(true)
+ {
+ detail::bounds(indexable, m_box);
+ }
+
+ template <typename Indexable>
void expand(Indexable const& indexable)
{
if ( !m_initialized )
@@ -260,9 +267,12 @@ private:
// reserve space for values
rtree::elements(l).reserve(values_count); // MAY THROW (A)
+
// calculate values box and copy values
- expandable_box<Box> elements_box;
- for ( ; first != last ; ++first )
+ // initialize the box explicitly to avoid GCC-4.4 uninitialized variable warnings with O2
+ expandable_box<Box> elements_box(translator(*(first->second)));
+ rtree::elements(l).push_back(*(first->second)); // MAY THROW (A?,C)
+ for ( ++first ; first != last ; ++first )
{
// NOTE: push_back() must be called at the end in order to support move_iterator.
// The iterator is dereferenced 2x (no temporary reference) to support
diff --git a/boost/geometry/index/rtree.hpp b/boost/geometry/index/rtree.hpp
index ea7fc74ed3..6d3704ff8c 100644
--- a/boost/geometry/index/rtree.hpp
+++ b/boost/geometry/index/rtree.hpp
@@ -1263,16 +1263,16 @@ public:
inline bounds_type bounds() const
{
bounds_type result;
- if ( !m_members.root )
+ // in order to suppress the uninitialized variable warnings
+ geometry::assign_inverse(result);
+
+ if ( m_members.root )
{
- geometry::assign_inverse(result);
- return result;
+ detail::rtree::visitors::children_box<value_type, options_type, translator_type, box_type, allocators_type>
+ box_v(result, m_members.translator());
+ detail::rtree::apply_visitor(box_v, *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::apply_visitor(box_v, *m_members.root);
-
return result;
}
diff --git a/boost/geometry/io/svg/svg_mapper.hpp b/boost/geometry/io/svg/svg_mapper.hpp
index c8e63d5ab7..e06f2acc24 100644
--- a/boost/geometry/io/svg/svg_mapper.hpp
+++ b/boost/geometry/io/svg/svg_mapper.hpp
@@ -2,10 +2,11 @@
// Copyright (c) 2009-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2016.
+// Modifications copyright (c) 2015-2016, 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.
@@ -90,26 +91,36 @@ struct svg_map<point_tag, Point>
}
};
-template <typename Box>
-struct svg_map<box_tag, Box>
+template <typename BoxSeg1, typename BoxSeg2>
+struct svg_map_box_seg
{
template <typename TransformStrategy>
static inline void apply(std::ostream& stream,
std::string const& style, int size,
- Box const& box, TransformStrategy const& strategy)
+ BoxSeg1 const& box_seg, TransformStrategy const& strategy)
{
- model::box<detail::svg::svg_point_type> ibox;
+ BoxSeg2 ibox_seg;
- // Fix bug in gcc compiler warning for possible uninitialation
+ // Fix bug in gcc compiler warning for possible uninitialization
#if defined(BOOST_GCC)
- geometry::assign_zero(ibox);
+ geometry::assign_zero(ibox_seg);
#endif
- geometry::transform(box, ibox, strategy);
+ geometry::transform(box_seg, ibox_seg, strategy);
- stream << geometry::svg(ibox, style, size) << std::endl;
+ stream << geometry::svg(ibox_seg, style, size) << std::endl;
}
};
+template <typename Box>
+struct svg_map<box_tag, Box>
+ : svg_map_box_seg<Box, model::box<detail::svg::svg_point_type> >
+{};
+
+template <typename Segment>
+struct svg_map<segment_tag, Segment>
+ : svg_map_box_seg<Segment, model::segment<detail::svg::svg_point_type> >
+{};
+
template <typename Range1, typename Range2>
struct svg_map_range
@@ -125,25 +136,6 @@ struct svg_map_range
}
};
-template <typename Segment>
-struct svg_map<segment_tag, Segment>
-{
- template <typename TransformStrategy>
- static inline void apply(std::ostream& stream,
- std::string const& style, int size,
- Segment const& segment, TransformStrategy const& strategy)
- {
- typedef segment_view<Segment> view_type;
- view_type range(segment);
- svg_map_range
- <
- view_type,
- model::linestring<detail::svg::svg_point_type>
- >::apply(stream, style, size, range, strategy);
- }
-};
-
-
template <typename Ring>
struct svg_map<ring_tag, Ring>
: svg_map_range<Ring, model::ring<detail::svg::svg_point_type> >
diff --git a/boost/geometry/io/svg/write_svg.hpp b/boost/geometry/io/svg/write_svg.hpp
index fba3cbebaf..4a518a0815 100644
--- a/boost/geometry/io/svg/write_svg.hpp
+++ b/boost/geometry/io/svg/write_svg.hpp
@@ -3,6 +3,11 @@
// Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
+// This file was modified by Oracle on 2016.
+// Modifications copyright (c) 2016, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -66,9 +71,9 @@ struct svg_box
typedef typename coordinate_type<Box>::type ct;
ct x = geometry::get<geometry::min_corner, 0>(box);
ct y = geometry::get<geometry::min_corner, 1>(box);
- ct width = max BOOST_PREVENT_MACRO_SUBSTITUTION(1,
+ ct width = max BOOST_PREVENT_MACRO_SUBSTITUTION (ct(1),
geometry::get<geometry::max_corner, 0>(box) - x);
- ct height = max BOOST_PREVENT_MACRO_SUBSTITUTION (1,
+ ct height = max BOOST_PREVENT_MACRO_SUBSTITUTION (ct(1),
geometry::get<geometry::max_corner, 1>(box) - y);
os << "<rect x=\"" << x << "\" y=\"" << y
@@ -77,6 +82,24 @@ struct svg_box
}
};
+template <typename Segment>
+struct svg_segment
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Segment const& segment, std::string const& style, int)
+ {
+ typedef typename coordinate_type<Segment>::type ct;
+ ct x1 = geometry::get<0, 0>(segment);
+ ct y1 = geometry::get<0, 1>(segment);
+ ct x2 = geometry::get<1, 0>(segment);
+ ct y2 = geometry::get<1, 1>(segment);
+
+ os << "<line x1=\"" << x1 << "\" y1=\"" << y1
+ << "\" x2=\"" << x2 << "\" y2=\"" << y2
+ << "\" style=\"" << style << "\"/>";
+ }
+};
/*!
\brief Stream ranges as SVG
@@ -204,6 +227,9 @@ struct svg
template <typename Point>
struct svg<point_tag, Point> : detail::svg::svg_point<Point> {};
+template <typename Segment>
+struct svg<segment_tag, Segment> : detail::svg::svg_segment<Segment> {};
+
template <typename Box>
struct svg<box_tag, Box> : detail::svg::svg_box<Box> {};
diff --git a/boost/geometry/io/svg/write_svg_multi.hpp b/boost/geometry/io/svg/write_svg_multi.hpp
index a794120c06..ff349ebd75 100644
--- a/boost/geometry/io/svg/write_svg_multi.hpp
+++ b/boost/geometry/io/svg/write_svg_multi.hpp
@@ -2,6 +2,11 @@
// Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2016.
+// Modifications copyright (c) 2016, Oracle and/or its affiliates.
+
+// Contributed and/or modified by 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.
@@ -53,6 +58,32 @@ struct svg_multi
namespace dispatch
{
+template <typename MultiPoint>
+struct svg<multi_point_tag, MultiPoint>
+ : detail::svg::svg_multi
+ <
+ MultiPoint,
+ detail::svg::svg_point
+ <
+ typename boost::range_value<MultiPoint>::type
+ >
+
+ >
+{};
+
+template <typename MultiLinestring>
+struct svg<multi_linestring_tag, MultiLinestring>
+ : detail::svg::svg_multi
+ <
+ MultiLinestring,
+ detail::svg::svg_range
+ <
+ typename boost::range_value<MultiLinestring>::type,
+ detail::svg::prefix_linestring
+ >
+
+ >
+{};
template <typename MultiPolygon>
struct svg<multi_polygon_tag, MultiPolygon>
diff --git a/boost/geometry/io/wkt/read.hpp b/boost/geometry/io/wkt/read.hpp
index a39c8f89d4..7924b70283 100644
--- a/boost/geometry/io/wkt/read.hpp
+++ b/boost/geometry/io/wkt/read.hpp
@@ -27,9 +27,12 @@
#include <boost/algorithm/string.hpp>
#include <boost/mpl/if.hpp>
-#include <boost/range.hpp>
-
-#include <boost/type_traits.hpp>
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/size.hpp>
+#include <boost/range/value_type.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/remove_reference.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/append.hpp>
diff --git a/boost/geometry/policies/robustness/get_rescale_policy.hpp b/boost/geometry/policies/robustness/get_rescale_policy.hpp
index e7bef1d2e1..daf32d3057 100644
--- a/boost/geometry/policies/robustness/get_rescale_policy.hpp
+++ b/boost/geometry/policies/robustness/get_rescale_policy.hpp
@@ -20,8 +20,9 @@
#include <cstddef>
-#include <boost/type_traits.hpp>
#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_floating_point.hpp>
+#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/tag_cast.hpp>
@@ -252,9 +253,15 @@ struct rescale_policy_type
false
#else
boost::is_floating_point
- <
- typename geometry::coordinate_type<Point>::type
- >::type::value
+ <
+ typename geometry::coordinate_type<Point>::type
+ >::type::value
+ &&
+ boost::is_same
+ <
+ typename geometry::coordinate_system<Point>::type,
+ geometry::cs::cartesian
+ >::value
#endif
>
{
diff --git a/boost/geometry/policies/robustness/rescale_policy.hpp b/boost/geometry/policies/robustness/rescale_policy.hpp
index 8f34bf3dee..b92f6e1ec7 100644
--- a/boost/geometry/policies/robustness/rescale_policy.hpp
+++ b/boost/geometry/policies/robustness/rescale_policy.hpp
@@ -18,8 +18,6 @@
#include <cstddef>
-#include <boost/type_traits.hpp>
-
#include <boost/geometry/policies/robustness/segment_ratio.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
diff --git a/boost/geometry/policies/robustness/robust_type.hpp b/boost/geometry/policies/robustness/robust_type.hpp
index 4cfb2c4d91..7342f905bf 100644
--- a/boost/geometry/policies/robustness/robust_type.hpp
+++ b/boost/geometry/policies/robustness/robust_type.hpp
@@ -13,8 +13,8 @@
#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_TYPE_HPP
-#include <boost/type_traits.hpp>
#include <boost/config.hpp>
+#include <boost/type_traits/is_floating_point.hpp>
namespace boost { namespace geometry
diff --git a/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp b/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp
index 968f9fecb9..6740b519e2 100644
--- a/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp
+++ b/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp
@@ -55,6 +55,10 @@ struct decide_covered_by
};
+// WARNING
+// This strategy is not suitable for boxes in non-cartesian CSes having edges
+// longer than 180deg because e.g. the SSF formula picks the side of the closer
+// longitude, so for long edges the side is the opposite.
template <typename Point, typename Box, typename Decide = decide_within>
struct point_in_box_by_side
{
@@ -93,58 +97,6 @@ struct point_in_box_by_side
} // namespace within
-#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
-
-
-namespace within { namespace services
-{
-
-template <typename Point, typename Box>
-struct default_strategy
- <
- point_tag, box_tag,
- point_tag, areal_tag,
- spherical_tag, spherical_tag,
- Point, Box
- >
-{
- typedef within::point_in_box_by_side
- <
- Point, Box, within::decide_within
- > type;
-};
-
-
-
-}} // namespace within::services
-
-
-namespace covered_by { namespace services
-{
-
-
-template <typename Point, typename Box>
-struct default_strategy
- <
- point_tag, box_tag,
- point_tag, areal_tag,
- spherical_tag, spherical_tag,
- Point, Box
- >
-{
- typedef within::point_in_box_by_side
- <
- Point, Box, within::decide_covered_by
- > type;
-};
-
-
-}} // namespace covered_by::services
-
-
-#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
-
-
}}} // namespace boost::geometry::strategy
diff --git a/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp b/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
index 641533fc6a..9e2ec2c4ff 100644
--- a/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
+++ b/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
@@ -3,8 +3,9 @@
// 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.
-// Modifications copyright (c) 2013, 2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2016.
+// Modifications copyright (c) 2013-2016 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -13,8 +14,6 @@
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP
#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP
@@ -35,15 +34,34 @@ namespace boost { namespace geometry
namespace strategy { namespace within
{
+// 1 deg or pi/180 rad
+template <typename Point,
+ typename CalculationType = typename coordinate_type<Point>::type>
+struct winding_small_angle
+{
+ typedef typename coordinate_system<Point>::type cs_t;
+ typedef math::detail::constants_on_spheroid
+ <
+ CalculationType,
+ typename cs_t::units
+ > constants;
+
+ static inline CalculationType apply()
+ {
+ return constants::half_period() / CalculationType(180);
+ }
+};
+
// Fix for https://svn.boost.org/trac/boost/ticket/9628
-// For floating point coordinates, the <1> coordinate of a point is compared
+// For floating point coordinates, the <D> coordinate of a point is compared
// with the segment's points using some EPS. If the coordinates are "equal"
// the sides are calculated. Therefore we can treat a segment as a long areal
// geometry having some width. There is a small ~triangular area somewhere
// between the segment's effective area and a segment's line used in sides
// calculation where the segment is on the one side of the line but on the
// other side of a segment (due to the width).
+// Below picture assuming D = 1, if D = 0 horiz<->vert, E<->N, RIGHT<->UP.
// For the s1 of a segment going NE the real side is RIGHT but the point may
// be detected as LEFT, like this:
// RIGHT
@@ -54,6 +72,9 @@ namespace strategy { namespace within
// _____7
// _____/
// _____/
+// 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 CSTag>
struct winding_side_equal
{
@@ -62,122 +83,228 @@ struct winding_side_equal
CSTag
>::type strategy_side_type;
- template <size_t D, typename Point, typename PointOfSegment>
+ template <typename Point, typename PointOfSegment>
static inline int apply(Point const& point,
PointOfSegment const& se,
int count)
{
- // Create a vertical segment intersecting the original segment's endpoint
- // equal to the point, with the derived direction (UP/DOWN).
- // Set only the 2 first coordinates, the other ones are ignored
+ typedef typename coordinate_type<PointOfSegment>::type scoord_t;
+ typedef typename coordinate_system<PointOfSegment>::type::units units_t;
+
+ if (math::equals(get<1>(point), get<1>(se)))
+ return 0;
+
+ // Create a horizontal segment intersecting the original segment's endpoint
+ // equal to the point, with the derived direction (E/W).
PointOfSegment ss1, ss2;
- set<1-D>(ss1, get<1-D>(se));
- set<1-D>(ss2, get<1-D>(se));
- if (count > 0) // UP
+ set<1>(ss1, get<1>(se));
+ set<0>(ss1, get<0>(se));
+ set<1>(ss2, get<1>(se));
+ scoord_t ss20 = get<0>(se);
+ if (count > 0)
{
- set<D>(ss1, 0);
- set<D>(ss2, 1);
+ ss20 += winding_small_angle<PointOfSegment>::apply();
}
- else // DOWN
+ else
{
- set<D>(ss1, 1);
- set<D>(ss2, 0);
+ ss20 -= winding_small_angle<PointOfSegment>::apply();
}
+ math::normalize_longitude<units_t>(ss20);
+ set<0>(ss2, ss20);
+
// Check the side using this vertical segment
return strategy_side_type::apply(ss1, ss2, point);
}
};
-
// The optimization for cartesian
template <>
struct winding_side_equal<cartesian_tag>
{
- template <size_t D, typename Point, typename PointOfSegment>
+ template <typename Point, typename PointOfSegment>
static inline int apply(Point const& point,
PointOfSegment const& se,
int count)
{
- return math::equals(get<1-D>(point), get<1-D>(se)) ?
+ // NOTE: for D=0 the signs would be reversed
+ return math::equals(get<1>(point), get<1>(se)) ?
0 :
- get<1-D>(point) < get<1-D>(se) ?
+ get<1>(point) < get<1>(se) ?
// assuming count is equal to 1 or -1
- count : // ( count > 0 ? 1 : -1) :
- -count; // ( count > 0 ? -1 : 1) ;
+ -count : // ( count > 0 ? -1 : 1) :
+ count; // ( count > 0 ? 1 : -1) ;
}
};
-template <typename CSTag>
-struct winding_side_between
+template <typename Point,
+ typename CalculationType,
+ typename CSTag = typename cs_tag<Point>::type>
+struct winding_check_touch
{
- typedef typename strategy::side::services::default_strategy
- <
- CSTag
- >::type strategy_side_type;
+ typedef CalculationType calc_t;
+ typedef typename coordinate_system<Point>::type::units units_t;
+ typedef math::detail::constants_on_spheroid<CalculationType, units_t> constants;
- template <size_t D, typename Point, typename PointOfSegment>
+ template <typename PointOfSegment, typename State>
static inline int apply(Point const& point,
- PointOfSegment const& s1, PointOfSegment const& s2,
- int count)
+ PointOfSegment const& seg1,
+ PointOfSegment const& seg2,
+ State& state,
+ bool& eq1,
+ bool& eq2)
{
- // Create a vertical segment intersecting the original segment's endpoint
- // equal to the point, with the derived direction (UP/DOWN).
- // Set only the 2 first coordinates, the other ones are ignored
- PointOfSegment ss1, ss2;
- set<1-D>(ss1, get<1-D>(s1));
- set<1-D>(ss2, get<1-D>(s1));
-
- if (count > 0) // UP
+ calc_t const pi = constants::half_period();
+ calc_t const pi2 = pi / calc_t(2);
+
+ calc_t const px = get<0>(point);
+ calc_t const s1x = get<0>(seg1);
+ calc_t const s2x = get<0>(seg2);
+ calc_t const py = get<1>(point);
+ calc_t const s1y = get<1>(seg1);
+ calc_t const s2y = 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 = math::equals(s1x, px);
+ bool eq2_strict = math::equals(s2x, px);
+
+ eq1 = eq1_strict // lon strictly equal to s1
+ || math::equals(s1y, pi2) || math::equals(s1y, -pi2); // s1 is pole
+ eq2 = eq2_strict // lon strictly equal to s2
+ || math::equals(s2y, pi2) || math::equals(s2y, -pi2); // s2 is pole
+
+ // segment overlapping pole
+ calc_t s1x_anti = s1x + constants::half_period();
+ math::normalize_longitude<units_t, calc_t>(s1x_anti);
+ bool antipodal = math::equals(s2x, s1x_anti);
+ if (antipodal)
{
- set<D>(ss1, 0);
- set<D>(ss2, 1);
+ eq1 = eq2 = eq1 || eq2;
+
+ // segment overlapping pole and point is pole
+ if (math::equals(py, pi2) || math::equals(py, -pi2))
+ {
+ eq1 = eq2 = true;
+ }
}
- else // DOWN
+
+ // Both equal p -> segment vertical
+ // The only thing which has to be done is check if point is ON segment
+ if (eq1 && eq2)
{
- set<D>(ss1, 1);
- set<D>(ss2, 0);
+ // segment endpoints on the same sides of the globe
+ if (! antipodal
+ // p's lat between segment endpoints' lats
+ ? (s1y <= py && s2y >= py) || (s2y <= py && s1y >= py)
+ // going through north or south pole?
+ : (pi - s1y - s2y <= pi
+ ? (eq1_strict && s1y <= py) || (eq2_strict && s2y <= py) // north
+ || math::equals(py, pi2) // point on north pole
+ : (eq1_strict && s1y >= py) || (eq2_strict && s2y >= py)) // south
+ || math::equals(py, -pi2) // point on south pole
+ )
+ {
+ state.m_touches = true;
+ }
+ return true;
}
+ return false;
+ }
+};
+// The optimization for cartesian
+template <typename Point, typename CalculationType>
+struct winding_check_touch<Point, CalculationType, cartesian_tag>
+{
+ typedef CalculationType calc_t;
- int const seg_side = strategy_side_type::apply(ss1, ss2, s2);
+ template <typename PointOfSegment, typename State>
+ static inline bool apply(Point const& point,
+ PointOfSegment const& seg1,
+ PointOfSegment const& seg2,
+ State& state,
+ bool& eq1,
+ bool& eq2)
+ {
+ calc_t const px = get<0>(point);
+ calc_t const s1x = get<0>(seg1);
+ calc_t const s2x = get<0>(seg2);
- if (seg_side != 0) // segment not vertical
+ eq1 = math::equals(s1x, px);
+ eq2 = math::equals(s2x, px);
+
+ // Both equal p -> segment vertical
+ // The only thing which has to be done is check if point is ON segment
+ if (eq1 && eq2)
{
- if (strategy_side_type::apply(ss1, ss2, point) == -seg_side) // point on the opposite side than s2
- {
- return -seg_side;
- }
- else
+ 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))
{
- set<1-D>(ss1, get<1-D>(s2));
- set<1-D>(ss2, get<1-D>(s2));
-
- if (strategy_side_type::apply(ss1, ss2, point) == seg_side) // point behind s2
- {
- return seg_side;
- }
+ state.m_touches = true;
}
+ return true;
}
-
- // segment is vertical or point is between p1 and p2
- return strategy_side_type::apply(s1, s2, point);
+ return false;
}
};
-// The specialization for cartesian
-template <>
-struct winding_side_between<cartesian_tag>
+
+// Called if point is not aligned with a vertical segment
+template <typename Point,
+ typename CalculationType,
+ typename CSTag = typename cs_tag<Point>::type>
+struct winding_calculate_count
{
- typedef strategy::side::services::default_strategy
- <
- cartesian_tag
- >::type strategy_side_type;
+ typedef CalculationType calc_t;
+ typedef typename coordinate_system<Point>::type::units units_t;
- template <size_t D, typename Point, typename PointOfSegment>
- static inline int apply(Point const& point,
- PointOfSegment const& s1, PointOfSegment const& s2,
- int /*count*/)
+ static inline bool greater(calc_t const& l, calc_t const& r)
+ {
+ calc_t diff = l - r;
+ math::normalize_longitude<units_t, calc_t>(diff);
+ return diff > calc_t(0);
+ }
+
+ static inline int apply(calc_t const& p,
+ calc_t const& s1, calc_t const& s2,
+ bool eq1, bool eq2)
+ {
+ // Probably could be optimized by avoiding normalization for some comparisons
+ // e.g. s1 > p could be calculated from p > s1
+
+ // 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
+
+ return
+ eq1 ? (greater(s2, p) ? 1 : -1) // Point on level s1, E/W depending on s2
+ : eq2 ? (greater(s1, p) ? -1 : 1) // idem
+ : greater(p, s1) && greater(s2, p) ? 2 // Point between s1 -> s2 --> E
+ : greater(p, s2) && greater(s1, p) ? -2 // Point between s2 -> s1 --> W
+ : 0;
+ }
+};
+// The optimization for cartesian
+template <typename Point, typename CalculationType>
+struct winding_calculate_count<Point, CalculationType, cartesian_tag>
+{
+ typedef CalculationType calc_t;
+
+ static inline int apply(calc_t const& p,
+ calc_t const& s1, calc_t const& s2,
+ bool eq1, bool eq2)
{
- return strategy_side_type::apply(s1, s2, point);
+ return
+ eq1 ? (s2 > p ? 1 : -1) // Point on level s1, E/W depending on s2
+ : eq2 ? (s1 > p ? -1 : 1) // idem
+ : s1 < p && s2 > p ? 2 // Point between s1 -> s2 --> E
+ : s2 < p && s1 > p ? -2 // Point between s2 -> s1 --> W
+ : 0;
}
};
@@ -234,6 +361,9 @@ class winding
public :
friend class winding;
+ template <typename P, typename CT, typename CST>
+ friend struct winding_check_touch;
+
inline counter()
: m_count(0)
, m_touches(false)
@@ -242,48 +372,21 @@ class winding
};
- template <size_t D>
- static inline int check_touch(Point const& point,
- PointOfSegment const& seg1, PointOfSegment const& seg2,
- counter& state)
- {
- calculation_type const p = get<D>(point);
- calculation_type const s1 = get<D>(seg1);
- calculation_type const s2 = get<D>(seg2);
- if ((s1 <= p && s2 >= p) || (s2 <= p && s1 >= p))
- {
- state.m_touches = true;
- }
- return 0;
- }
-
-
- template <size_t D>
static inline int check_segment(Point const& point,
PointOfSegment const& seg1, PointOfSegment const& seg2,
counter& state, bool& eq1, bool& eq2)
{
- calculation_type const p = get<D>(point);
- calculation_type const s1 = get<D>(seg1);
- calculation_type const s2 = get<D>(seg2);
-
- // Check if one of segment endpoints is at same level of point
- eq1 = math::equals(s1, p);
- eq2 = math::equals(s2, p);
-
- if (eq1 && eq2)
+ if (winding_check_touch<Point, calculation_type>
+ ::apply(point, seg1, seg2, state, eq1, eq2))
{
- // Both equal p -> segment is horizontal (or vertical for D=0)
- // The only thing which has to be done is check if point is ON segment
- return check_touch<1 - D>(point, seg1, seg2, state);
+ return 0;
}
- return
- eq1 ? (s2 > p ? 1 : -1) // Point on level s1, UP/DOWN depending on s2
- : eq2 ? (s1 > p ? -1 : 1) // idem
- : s1 < p && s2 > p ? 2 // Point between s1 -> s2 --> UP
- : s2 < p && s1 > p ? -2 // Point between s2 -> s1 --> DOWN
- : 0;
+ calculation_type const p = get<0>(point);
+ calculation_type const s1 = get<0>(seg1);
+ calculation_type const s2 = get<0>(seg2);
+ return winding_calculate_count<Point, calculation_type>
+ ::apply(p, s1, s2, eq1, eq2);
}
@@ -304,19 +407,18 @@ public :
bool eq2 = false;
boost::ignore_unused(eq2);
- int count = check_segment<1>(point, s1, s2, state, eq1, eq2);
+ int count = check_segment(point, s1, s2, state, eq1, eq2);
if (count != 0)
{
int side = 0;
if (count == 1 || count == -1)
{
- side = winding_side_equal<cs_t>
- ::template apply<1>(point, eq1 ? s1 : s2, count);
+ side = winding_side_equal<cs_t>::apply(point, eq1 ? s1 : s2, count);
}
else // count == 2 || count == -2
{
- side = winding_side_between<cs_t>
- ::template apply<1>(point, s1, s2, count);
+ // 1 left, -1 right
+ side = strategy_side_type::apply(s1, s2, point);
}
if (side == 0)
diff --git a/boost/geometry/strategies/cartesian/area_surveyor.hpp b/boost/geometry/strategies/cartesian/area_surveyor.hpp
index 74b63532c0..ba76f67946 100644
--- a/boost/geometry/strategies/cartesian/area_surveyor.hpp
+++ b/boost/geometry/strategies/cartesian/area_surveyor.hpp
@@ -4,6 +4,11 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// This file was modified by Oracle on 2016.
+// Modifications copyright (c) 2016, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -17,7 +22,7 @@
#include <boost/mpl/if.hpp>
-#include <boost/geometry/arithmetic/determinant.hpp>
+//#include <boost/geometry/arithmetic/determinant.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
@@ -98,8 +103,20 @@ public :
PointOfSegment const& p2,
summation& state)
{
+ // Below formulas are equivalent, however the two lower ones
+ // suffer less from accuracy loss for great values of coordinates.
+ // See: https://svn.boost.org/trac/boost/ticket/11928
+
// SUM += x2 * y1 - x1 * y2;
- state.sum += detail::determinant<return_type>(p2, p1);
+ // state.sum += detail::determinant<return_type>(p2, p1);
+
+ // SUM += (x2 - x1) * (y2 + y1)
+ //state.sum += (return_type(get<0>(p2)) - return_type(get<0>(p1)))
+ // * (return_type(get<1>(p2)) + return_type(get<1>(p1)));
+
+ // SUM += (x1 + x2) * (y1 - y2)
+ state.sum += (return_type(get<0>(p1)) + return_type(get<0>(p2)))
+ * (return_type(get<1>(p1)) - return_type(get<1>(p2)));
}
static inline return_type result(summation const& state)
diff --git a/boost/geometry/strategies/cartesian/box_in_box.hpp b/boost/geometry/strategies/cartesian/box_in_box.hpp
index 56aef9e4df..fe77de9e2d 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.
-// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2016.
+// Modifications copyright (c) 2016, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -25,6 +25,7 @@
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/within.hpp>
+#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
namespace boost { namespace geometry { namespace strategy
@@ -34,6 +35,8 @@ namespace boost { namespace geometry { namespace strategy
namespace within
{
+
+template <typename Geometry, std::size_t Dimension, typename CSTag>
struct box_within_range
{
template <typename BoxContainedValue, typename BoxContainingValue>
@@ -48,6 +51,7 @@ struct box_within_range
};
+template <typename Geometry, std::size_t Dimension, typename CSTag>
struct box_covered_by_range
{
template <typename BoxContainedValue, typename BoxContainingValue>
@@ -61,9 +65,84 @@ struct box_covered_by_range
};
+struct box_within_longitude_check
+{
+ template <typename CalcT>
+ static inline bool apply(CalcT const& diff_ed)
+ {
+ return diff_ed > CalcT(0);
+ }
+};
+
+struct box_covered_by_longitude_check
+{
+ template <typename CalcT>
+ static inline bool apply(CalcT const&)
+ {
+ return true;
+ }
+};
+
+template <typename Geometry,
+ typename InteriorCheck>
+struct box_longitude_range
+{
+ template <typename BoxContainedValue, typename BoxContainingValue>
+ static inline bool apply(BoxContainedValue const& bed_min,
+ BoxContainedValue const& bed_max,
+ BoxContainingValue const& bing_min,
+ BoxContainingValue const& bing_max)
+ {
+ typedef typename select_most_precise
+ <
+ BoxContainedValue,
+ BoxContainingValue
+ >::type calc_t;
+ typedef typename coordinate_system<Geometry>::type::units units_t;
+ typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
+
+ // min <= max <=> diff >= 0
+ calc_t const diff_ed = bed_max - bed_min;
+ calc_t const diff_ing = bing_max - bing_min;
+
+ // if containing covers the whole globe it contains all
+ if (diff_ing >= constants::period())
+ {
+ return true;
+ }
+
+ // if containing is smaller it cannot contain
+ // and check interior (within vs covered_by)
+ if (diff_ing < diff_ed || ! InteriorCheck::apply(diff_ed))
+ {
+ return false;
+ }
+
+ // calculate positive longitude translation with bing_min as origin
+ calc_t const diff_min = math::longitude_distance_unsigned<units_t>(bing_min, bed_min);
+
+ // max of contained translated into the containing origin must be lesser than max of containing
+ return bing_min + diff_min + diff_ed <= bing_max;
+ }
+};
+
+
+// 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_longitude_check>
+{};
+
+
+template <typename Geometry>
+struct box_covered_by_range<Geometry, 0, spherical_tag>
+ : box_longitude_range<Geometry, box_covered_by_longitude_check>
+{};
+
+
template
<
- typename SubStrategy,
+ template <typename, std::size_t, typename> class SubStrategy,
typename Box1,
typename Box2,
std::size_t Dimension,
@@ -74,8 +153,9 @@ struct relate_box_box_loop
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::apply(
+ if (! SubStrategy<Box1, Dimension, cs_tag_t>::apply(
get<min_corner, Dimension>(b_contained),
get<max_corner, Dimension>(b_contained),
get<min_corner, Dimension>(b_containing),
@@ -97,7 +177,7 @@ struct relate_box_box_loop
template
<
- typename SubStrategy,
+ template <typename, std::size_t, typename> class SubStrategy,
typename Box1,
typename Box2,
std::size_t DimensionCount
@@ -114,7 +194,7 @@ template
<
typename Box1,
typename Box2,
- typename SubStrategy = box_within_range
+ template <typename, std::size_t, typename> class SubStrategy = box_within_range
>
struct box_in_box
{
@@ -150,6 +230,19 @@ struct default_strategy
typedef within::box_in_box<BoxContained, BoxContaining> type;
};
+// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
+template <typename BoxContained, typename BoxContaining>
+struct default_strategy
+ <
+ box_tag, box_tag,
+ box_tag, areal_tag,
+ spherical_tag, spherical_tag,
+ BoxContained, BoxContaining
+ >
+{
+ typedef within::box_in_box<BoxContained, BoxContaining> type;
+};
+
}} // namespace within::services
@@ -172,6 +265,24 @@ struct default_strategy
> type;
};
+// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
+template <typename BoxContained, typename BoxContaining>
+struct default_strategy
+ <
+ box_tag, box_tag,
+ box_tag, areal_tag,
+ spherical_tag, spherical_tag,
+ BoxContained, BoxContaining
+ >
+{
+ typedef within::box_in_box
+ <
+ BoxContained, BoxContaining,
+ within::box_covered_by_range
+ > type;
+};
+
+
}} // namespace covered_by::services
diff --git a/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp b/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp
index 47763a9f30..d081173a3e 100644
--- a/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp
+++ b/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp
@@ -25,7 +25,7 @@
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/mpl/if.hpp>
#include <boost/numeric/conversion/cast.hpp>
-#include <boost/type_traits.hpp>
+#include <boost/type_traits/is_void.hpp>
#include <boost/geometry/arithmetic/determinant.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
diff --git a/boost/geometry/strategies/cartesian/distance_projected_point.hpp b/boost/geometry/strategies/cartesian/distance_projected_point.hpp
index dff4a77f6f..b7127c834d 100644
--- a/boost/geometry/strategies/cartesian/distance_projected_point.hpp
+++ b/boost/geometry/strategies/cartesian/distance_projected_point.hpp
@@ -22,7 +22,7 @@
#include <boost/concept_check.hpp>
#include <boost/mpl/if.hpp>
-#include <boost/type_traits.hpp>
+#include <boost/type_traits/is_void.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/point_type.hpp>
diff --git a/boost/geometry/strategies/cartesian/distance_projected_point_ax.hpp b/boost/geometry/strategies/cartesian/distance_projected_point_ax.hpp
index c4090044f4..7ff86c7cfa 100644
--- a/boost/geometry/strategies/cartesian/distance_projected_point_ax.hpp
+++ b/boost/geometry/strategies/cartesian/distance_projected_point_ax.hpp
@@ -24,8 +24,6 @@
#include <algorithm>
#include <boost/concept_check.hpp>
-#include <boost/mpl/if.hpp>
-#include <boost/type_traits.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/point_type.hpp>
diff --git a/boost/geometry/strategies/cartesian/distance_pythagoras.hpp b/boost/geometry/strategies/cartesian/distance_pythagoras.hpp
index 77bdc966a6..665426ecb0 100644
--- a/boost/geometry/strategies/cartesian/distance_pythagoras.hpp
+++ b/boost/geometry/strategies/cartesian/distance_pythagoras.hpp
@@ -15,9 +15,6 @@
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP
-#include <boost/mpl/if.hpp>
-#include <boost/type_traits.hpp>
-
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/strategies/distance.hpp>
@@ -26,8 +23,6 @@
#include <boost/geometry/util/calculation_type.hpp>
-
-
namespace boost { namespace geometry
{
diff --git a/boost/geometry/strategies/cartesian/point_in_box.hpp b/boost/geometry/strategies/cartesian/point_in_box.hpp
index bd2303cbc4..28ed8215e7 100644
--- a/boost/geometry/strategies/cartesian/point_in_box.hpp
+++ b/boost/geometry/strategies/cartesian/point_in_box.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015-2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -24,6 +24,7 @@
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/within.hpp>
+#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
namespace boost { namespace geometry { namespace strategy
@@ -33,6 +34,7 @@ namespace within
{
+template <typename Geometry, std::size_t Dimension, typename CSTag>
struct within_range
{
template <typename Value1, typename Value2>
@@ -43,6 +45,7 @@ struct within_range
};
+template <typename Geometry, std::size_t Dimension, typename CSTag>
struct covered_by_range
{
template <typename Value1, typename Value2>
@@ -53,9 +56,76 @@ struct covered_by_range
};
+// NOTE: the result would be the same if instead of structs defined below
+// the above xxx_range were used with the following arguments:
+// (min_value + diff_min, min_value, max_value)
+struct within_longitude_range
+{
+ template <typename CalcT>
+ static inline bool apply(CalcT const& diff_min, CalcT const& min_value, CalcT const& max_value)
+ {
+ CalcT const c0 = 0;
+ return diff_min > c0 && min_value + diff_min < max_value;
+ }
+};
+
+struct covered_by_longitude_range
+{
+ template <typename CalcT>
+ static inline bool apply(CalcT const& diff_min, CalcT const& min_value, CalcT const& max_value)
+ {
+ return min_value + diff_min <= max_value;
+ }
+};
+
+
+template <typename Geometry,
+ typename ResultCheck>
+struct longitude_range
+{
+ template <typename Value1, typename Value2>
+ static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value)
+ {
+ typedef typename select_most_precise
+ <
+ Value1, Value2
+ >::type calc_t;
+ typedef typename coordinate_system<Geometry>::type::units units_t;
+ typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
+
+ // min <= max <=> diff >= 0
+ calc_t const diff_ing = max_value - min_value;
+
+ // if containing covers the whole globe it contains all
+ if (diff_ing >= constants::period())
+ {
+ return true;
+ }
+
+ // calculate positive longitude translation with min_value as origin
+ calc_t const diff_min = math::longitude_distance_unsigned<units_t, calc_t>(min_value, value);
+
+ return ResultCheck::template apply<calc_t>(diff_min, min_value, max_value);
+ }
+};
+
+
+// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
+template <typename Geometry>
+struct within_range<Geometry, 0, spherical_tag>
+ : longitude_range<Geometry, within_longitude_range>
+{};
+
+
+template <typename Geometry>
+struct covered_by_range<Geometry, 0, spherical_tag>
+ : longitude_range<Geometry, covered_by_longitude_range>
+{};
+
+
template
<
- typename SubStrategy,
+ template <typename, std::size_t, typename> class SubStrategy,
typename Point,
typename Box,
std::size_t Dimension,
@@ -65,7 +135,9 @@ struct relate_point_box_loop
{
static inline bool apply(Point const& point, Box const& box)
{
- if (! SubStrategy::apply(get<Dimension>(point),
+ typedef typename tag_cast<typename cs_tag<Point>::type, spherical_tag>::type cs_tag_t;
+
+ if (! SubStrategy<Point, Dimension, cs_tag_t>::apply(get<Dimension>(point),
get<min_corner, Dimension>(box),
get<max_corner, Dimension>(box))
)
@@ -85,7 +157,7 @@ struct relate_point_box_loop
template
<
- typename SubStrategy,
+ template <typename, std::size_t, typename> class SubStrategy,
typename Point,
typename Box,
std::size_t DimensionCount
@@ -103,7 +175,7 @@ template
<
typename Point,
typename Box,
- typename SubStrategy = within_range
+ template <typename, std::size_t, typename> class SubStrategy = within_range
>
struct point_in_box
{
@@ -140,6 +212,19 @@ struct default_strategy
typedef within::point_in_box<Point, Box> type;
};
+// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
+template <typename Point, typename Box>
+struct default_strategy
+ <
+ point_tag, box_tag,
+ point_tag, areal_tag,
+ spherical_tag, spherical_tag,
+ Point, Box
+ >
+{
+ typedef within::point_in_box<Point, Box> type;
+};
+
}} // namespace within::services
@@ -164,6 +249,23 @@ struct default_strategy
> type;
};
+// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
+template <typename Point, typename Box>
+struct default_strategy
+ <
+ point_tag, box_tag,
+ point_tag, areal_tag,
+ spherical_tag, spherical_tag,
+ Point, Box
+ >
+{
+ typedef within::point_in_box
+ <
+ Point, Box,
+ within::covered_by_range
+ > type;
+};
+
}} // namespace covered_by::services
diff --git a/boost/geometry/strategies/cartesian/side_by_triangle.hpp b/boost/geometry/strategies/cartesian/side_by_triangle.hpp
index 77443d46a9..ba7749ba76 100644
--- a/boost/geometry/strategies/cartesian/side_by_triangle.hpp
+++ b/boost/geometry/strategies/cartesian/side_by_triangle.hpp
@@ -20,7 +20,8 @@
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
#include <boost/mpl/if.hpp>
-#include <boost/type_traits.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_void.hpp>
#include <boost/geometry/arithmetic/determinant.hpp>
#include <boost/geometry/core/access.hpp>
diff --git a/boost/geometry/strategies/geographic/distance_andoyer.hpp b/boost/geometry/strategies/geographic/distance_andoyer.hpp
index 64de8c1a41..1646727d09 100644
--- a/boost/geometry/strategies/geographic/distance_andoyer.hpp
+++ b/boost/geometry/strategies/geographic/distance_andoyer.hpp
@@ -1,9 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2007-2016 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014.
-// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2016.
+// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -20,6 +20,7 @@
#include <boost/geometry/core/radius.hpp>
#include <boost/geometry/core/srs.hpp>
+#include <boost/geometry/algorithms/detail/andoyer_inverse.hpp>
#include <boost/geometry/algorithms/detail/flattening.hpp>
#include <boost/geometry/strategies/distance.hpp>
@@ -50,6 +51,8 @@ are about the same as Vincenty. In my (Barend's) testcases the results didn't di
\see http://www.codeguru.com/Cpp/Cpp/algorithms/article.php/c5115 (implementation)
\see http://futureboy.homeip.net/frinksamp/navigation.frink (implementation)
\see http://www.voidware.com/earthdist.htm (implementation)
+\see http://www.dtic.mil/docs/citations/AD0627893
+\see http://www.dtic.mil/docs/citations/AD703541
*/
template
<
@@ -82,16 +85,17 @@ public :
: m_spheroid(spheroid)
{}
-
template <typename Point1, typename Point2>
inline typename calculation_type<Point1, Point2>::type
apply(Point1 const& point1, Point2 const& point2) const
{
- return calc<typename calculation_type<Point1, Point2>::type>
- (
- get_as_radian<0>(point1), get_as_radian<1>(point1),
- get_as_radian<0>(point2), get_as_radian<1>(point2)
- );
+ return geometry::detail::andoyer_inverse
+ <
+ typename calculation_type<Point1, Point2>::type,
+ true, false
+ >::apply(get_as_radian<0>(point1), get_as_radian<1>(point1),
+ get_as_radian<0>(point2), get_as_radian<1>(point2),
+ m_spheroid).distance;
}
inline Spheroid const& model() const
@@ -100,55 +104,6 @@ public :
}
private :
- template <typename CT, typename T>
- inline CT calc(T const& lon1,
- T const& lat1,
- T const& lon2,
- T const& lat2) const
- {
- CT const G = (lat1 - lat2) / 2.0;
- CT const lambda = (lon1 - lon2) / 2.0;
-
- if (geometry::math::equals(lambda, 0.0)
- && geometry::math::equals(G, 0.0))
- {
- return 0.0;
- }
-
- CT const F = (lat1 + lat2) / 2.0;
-
- CT const sinG2 = math::sqr(sin(G));
- CT const cosG2 = math::sqr(cos(G));
- CT const sinF2 = math::sqr(sin(F));
- CT const cosF2 = math::sqr(cos(F));
- CT const sinL2 = math::sqr(sin(lambda));
- CT const cosL2 = math::sqr(cos(lambda));
-
- CT const S = sinG2 * cosL2 + cosF2 * sinL2;
- CT const C = cosG2 * cosL2 + sinF2 * sinL2;
-
- CT const c0 = 0;
- CT const c1 = 1;
- CT const c2 = 2;
- CT const c3 = 3;
-
- if (geometry::math::equals(S, c0) || geometry::math::equals(C, c0))
- {
- return c0;
- }
-
- CT const radius_a = CT(get_radius<0>(m_spheroid));
- CT const flattening = geometry::detail::flattening<CT>(m_spheroid);
-
- CT const omega = atan(math::sqrt(S / C));
- CT const r3 = c3 * math::sqrt(S * C) / omega; // not sure if this is r or greek nu
- CT const D = c2 * omega * radius_a;
- CT const H1 = (r3 - c1) / (c2 * C);
- CT const H2 = (r3 + c1) / (c2 * S);
-
- return D * (c1 + flattening * (H1 * sinF2 * cosG2 - H2 * cosF2 * sinG2) );
- }
-
Spheroid m_spheroid;
};
diff --git a/boost/geometry/strategies/spherical/ssf.hpp b/boost/geometry/strategies/spherical/ssf.hpp
index 81f3205e90..c99e5835e2 100644
--- a/boost/geometry/strategies/spherical/ssf.hpp
+++ b/boost/geometry/strategies/spherical/ssf.hpp
@@ -2,6 +2,10 @@
// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2016.
+// Modifications copyright (c) 2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -9,8 +13,6 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SSF_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SSF_HPP
-#include <boost/mpl/if.hpp>
-#include <boost/type_traits.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/access.hpp>
@@ -61,9 +63,9 @@ int spherical_side_formula(T const& lambda1, T const& delta1,
+ (c1x * c2y - c1y * c2x) * sin(delta);
T zero = T();
- return dist > zero ? 1
- : dist < zero ? -1
- : 0;
+ return math::equals(dist, zero) ? 0
+ : dist > zero ? 1
+ : -1; // dist < zero
}
}
diff --git a/boost/geometry/util/calculation_type.hpp b/boost/geometry/util/calculation_type.hpp
index 2ac0de87d9..18eac4fbb7 100644
--- a/boost/geometry/util/calculation_type.hpp
+++ b/boost/geometry/util/calculation_type.hpp
@@ -13,7 +13,9 @@
#include <boost/config.hpp>
#include <boost/mpl/if.hpp>
-#include <boost/type_traits.hpp>
+#include <boost/type_traits/is_floating_point.hpp>
+#include <boost/type_traits/is_fundamental.hpp>
+#include <boost/type_traits/is_void.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
diff --git a/boost/geometry/util/combine_if.hpp b/boost/geometry/util/combine_if.hpp
index cfc3449267..5d94c34461 100644
--- a/boost/geometry/util/combine_if.hpp
+++ b/boost/geometry/util/combine_if.hpp
@@ -24,8 +24,6 @@
#include <boost/mpl/insert.hpp>
#include <boost/mpl/placeholders.hpp>
-#include <boost/type_traits.hpp>
-
namespace boost { namespace geometry
{
diff --git a/boost/geometry/util/math.hpp b/boost/geometry/util/math.hpp
index c193c8f3f1..234cfa1ed0 100644
--- a/boost/geometry/util/math.hpp
+++ b/boost/geometry/util/math.hpp
@@ -32,6 +32,8 @@
#include <boost/type_traits/is_fundamental.hpp>
#include <boost/type_traits/is_integral.hpp>
+#include <boost/geometry/core/cs.hpp>
+
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
@@ -601,6 +603,65 @@ inline T r2d()
}
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail {
+
+template <typename DegreeOrRadian>
+struct as_radian
+{
+ template <typename T>
+ static inline T apply(T const& value)
+ {
+ return value;
+ }
+};
+
+template <>
+struct as_radian<degree>
+{
+ template <typename T>
+ static inline T apply(T const& value)
+ {
+ return value * d2r<T>();
+ }
+};
+
+template <typename DegreeOrRadian>
+struct from_radian
+{
+ template <typename T>
+ static inline T apply(T const& value)
+ {
+ return value;
+ }
+};
+
+template <>
+struct from_radian<degree>
+{
+ template <typename T>
+ static inline T apply(T const& value)
+ {
+ return value * r2d<T>();
+ }
+};
+
+} // namespace detail
+#endif
+
+template <typename DegreeOrRadian, typename T>
+inline T as_radian(T const& value)
+{
+ return detail::as_radian<DegreeOrRadian>::apply(value);
+}
+
+template <typename DegreeOrRadian, typename T>
+inline T from_radian(T const& value)
+{
+ return detail::from_radian<DegreeOrRadian>::apply(value);
+}
+
+
/*!
\brief Calculates the haversine of an angle
\ingroup utility
diff --git a/boost/geometry/util/normalize_spheroidal_coordinates.hpp b/boost/geometry/util/normalize_spheroidal_coordinates.hpp
index 72dfa5a6f1..377051eef1 100644
--- a/boost/geometry/util/normalize_spheroidal_coordinates.hpp
+++ b/boost/geometry/util/normalize_spheroidal_coordinates.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2015, Oracle and/or its affiliates.
+// Copyright (c) 2015-2016, Oracle and/or its affiliates.
// Contributed and/or modified by 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
@@ -119,6 +120,27 @@ protected:
}
public:
+ static inline void apply(CoordinateType& longitude)
+ {
+ // normalize longitude
+ if (math::equals(math::abs(longitude), constants::half_period()))
+ {
+ longitude = constants::half_period();
+ }
+ else if (longitude > constants::half_period())
+ {
+ longitude = normalize_up(longitude);
+ if (math::equals(longitude, -constants::half_period()))
+ {
+ longitude = constants::half_period();
+ }
+ }
+ else if (longitude < -constants::half_period())
+ {
+ longitude = normalize_down(longitude);
+ }
+ }
+
static inline void apply(CoordinateType& longitude,
CoordinateType& latitude,
bool normalize_poles = true)
@@ -148,22 +170,7 @@ public:
#endif // BOOST_GEOMETRY_NORMALIZE_LATITUDE
// normalize longitude
- if (math::equals(math::abs(longitude), constants::half_period()))
- {
- longitude = constants::half_period();
- }
- else if (longitude > constants::half_period())
- {
- longitude = normalize_up(longitude);
- if (math::equals(longitude, -constants::half_period()))
- {
- longitude = constants::half_period();
- }
- }
- else if (longitude < -constants::half_period())
- {
- longitude = normalize_down(longitude);
- }
+ apply(longitude);
// finally normalize poles
if (normalize_poles)
@@ -210,6 +217,71 @@ inline void normalize_spheroidal_coordinates(CoordinateType& longitude,
}
+/*!
+\brief Short utility to normalize the longitude on a spheroid.
+ Note that in general both coordinates should be normalized at once.
+ This utility is suitable e.g. for normalization of the difference of longitudes.
+\tparam Units The units of the coordindate system in the spheroid
+\tparam CoordinateType The type of the coordinates
+\param longitude Longitude
+\ingroup utility
+*/
+template <typename Units, typename CoordinateType>
+inline void normalize_longitude(CoordinateType& longitude)
+{
+ detail::normalize_spheroidal_coordinates
+ <
+ Units, CoordinateType
+ >::apply(longitude);
+}
+
+
+/*!
+\brief Short utility to calculate difference between two longitudes
+ normalized in range (-180, 180].
+\tparam Units The units of the coordindate system in the spheroid
+\tparam CoordinateType The type of the coordinates
+\param longitude1 Longitude 1
+\param longitude2 Longitude 2
+\ingroup utility
+*/
+template <typename Units, typename CoordinateType>
+inline CoordinateType longitude_distance_signed(CoordinateType const& longitude1,
+ CoordinateType const& longitude2)
+{
+ CoordinateType diff = longitude2 - longitude1;
+ math::normalize_longitude<Units, CoordinateType>(diff);
+ return diff;
+}
+
+
+/*!
+\brief Short utility to calculate difference between two longitudes
+ normalized in range [0, 360).
+\tparam Units The units of the coordindate system in the spheroid
+\tparam CoordinateType The type of the coordinates
+\param longitude1 Longitude 1
+\param longitude2 Longitude 2
+\ingroup utility
+*/
+template <typename Units, typename CoordinateType>
+inline CoordinateType longitude_distance_unsigned(CoordinateType const& longitude1,
+ CoordinateType const& longitude2)
+{
+ typedef math::detail::constants_on_spheroid
+ <
+ CoordinateType, Units
+ > constants;
+
+ CoordinateType const c0 = 0;
+ CoordinateType diff = longitude_distance_signed<Units>(longitude1, longitude2);
+ if (diff < c0) // (-180, 180] -> [0, 360)
+ {
+ diff += constants::period();
+ }
+ return diff;
+}
+
} // namespace math
diff --git a/boost/geometry/util/parameter_type_of.hpp b/boost/geometry/util/parameter_type_of.hpp
index 3ed09ab9bb..731fb55a56 100644
--- a/boost/geometry/util/parameter_type_of.hpp
+++ b/boost/geometry/util/parameter_type_of.hpp
@@ -21,7 +21,7 @@
#include <boost/mpl/at.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/plus.hpp>
-#include <boost/type_traits.hpp>
+#include <boost/type_traits/remove_reference.hpp>
namespace boost { namespace geometry
diff --git a/boost/geometry/util/promote_floating_point.hpp b/boost/geometry/util/promote_floating_point.hpp
index 0c74cb8d6c..b84069db1b 100644
--- a/boost/geometry/util/promote_floating_point.hpp
+++ b/boost/geometry/util/promote_floating_point.hpp
@@ -16,7 +16,7 @@
#include <boost/mpl/if.hpp>
-#include <boost/type_traits.hpp>
+#include <boost/type_traits/is_integral.hpp>
namespace boost { namespace geometry
diff --git a/boost/geometry/util/range.hpp b/boost/geometry/util/range.hpp
index 0f480df58a..b10a008059 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.
-// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2016.
+// Modifications copyright (c) 2013-2016 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -15,14 +15,21 @@
#define BOOST_GEOMETRY_UTIL_RANGE_HPP
#include <algorithm>
+#include <iterator>
#include <boost/concept_check.hpp>
#include <boost/config.hpp>
+#include <boost/core/addressof.hpp>
#include <boost/range/concepts.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/empty.hpp>
+#include <boost/range/difference_type.hpp>
+#include <boost/range/iterator.hpp>
+#include <boost/range/rbegin.hpp>
+#include <boost/range/reference.hpp>
#include <boost/range/size.hpp>
+#include <boost/range/value_type.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/geometry/core/assert.hpp>
@@ -362,6 +369,50 @@ erase(Range & rng,
return erase(rng, first, last);
}
+// back_inserter
+
+template <class Container>
+class back_insert_iterator
+ : public std::iterator<std::output_iterator_tag, void, void, void, void>
+{
+public:
+ typedef Container container_type;
+
+ explicit back_insert_iterator(Container & c)
+ : container(boost::addressof(c))
+ {}
+
+ back_insert_iterator & operator=(typename Container::value_type const& value)
+ {
+ range::push_back(*container, value);
+ return *this;
+ }
+
+ back_insert_iterator & operator* ()
+ {
+ return *this;
+ }
+
+ back_insert_iterator & operator++ ()
+ {
+ return *this;
+ }
+
+ back_insert_iterator operator++(int)
+ {
+ return *this;
+ }
+
+private:
+ Container * container;
+};
+
+template <typename Range>
+inline back_insert_iterator<Range> back_inserter(Range & rng)
+{
+ return back_insert_iterator<Range>(rng);
+}
+
}}} // namespace boost::geometry::range
#endif // BOOST_GEOMETRY_UTIL_RANGE_HPP
diff --git a/boost/geometry/util/select_calculation_type.hpp b/boost/geometry/util/select_calculation_type.hpp
index 0e3faf229b..b6405831eb 100644
--- a/boost/geometry/util/select_calculation_type.hpp
+++ b/boost/geometry/util/select_calculation_type.hpp
@@ -21,7 +21,7 @@
#include <boost/mpl/if.hpp>
-#include <boost/type_traits.hpp>
+#include <boost/type_traits/is_void.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
diff --git a/boost/geometry/util/select_most_precise.hpp b/boost/geometry/util/select_most_precise.hpp
index b5b1388cf8..3169f5fa17 100644
--- a/boost/geometry/util/select_most_precise.hpp
+++ b/boost/geometry/util/select_most_precise.hpp
@@ -20,7 +20,8 @@
#define BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP
#include <boost/mpl/if.hpp>
-#include <boost/type_traits.hpp>
+#include <boost/type_traits/is_floating_point.hpp>
+#include <boost/type_traits/is_fundamental.hpp>
namespace boost { namespace geometry
diff --git a/boost/graph/adjacency_matrix.hpp b/boost/graph/adjacency_matrix.hpp
index b1078d977e..ade7351fb8 100644
--- a/boost/graph/adjacency_matrix.hpp
+++ b/boost/graph/adjacency_matrix.hpp
@@ -443,7 +443,7 @@ namespace boost {
// graph type. Instead, use directedS, which also provides the
// functionality required for a Bidirectional Graph (in_edges,
// in_degree, etc.).
- BOOST_STATIC_ASSERT(type_traits::ice_not<(is_same<Directed, bidirectionalS>::value)>::value);
+ BOOST_STATIC_ASSERT(!(is_same<Directed, bidirectionalS>::value));
typedef typename mpl::if_<is_directed,
bidirectional_tag, undirected_tag>::type
diff --git a/boost/hana.hpp b/boost/hana.hpp
new file mode 100644
index 0000000000..0739e5e05d
--- /dev/null
+++ b/boost/hana.hpp
@@ -0,0 +1,208 @@
+/*!
+@file
+Includes all the library components except the adapters for external
+libraries.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_HPP
+#define BOOST_HANA_HPP
+
+//! @defgroup group-concepts Concepts
+//! Concepts provided by the library.
+
+//! @defgroup group-datatypes Data types
+//! General purpose data types provided by the library.
+
+//! @defgroup group-functional Functional
+//! General purpose function objects.
+
+//! @defgroup group-core Core
+//! Core utilities of the library.
+
+//! @defgroup group-experimental Experimental features
+//! Experimental features that may or may not make it into the library.
+//! These features should not expected to be stable.
+
+//! @defgroup group-ext External adapters
+//! Adapters for external libraries.
+
+//! @defgroup group-config Configuration options
+//! Configurable options to tweak the global behavior of the library.
+
+//! @defgroup group-assertions Assertions
+//! Macros to perform different kinds of assertions.
+
+//! @defgroup group-details Details
+//! Implementation details. Do not rely on anything here, even if it is
+//! documented.
+
+// Include config.hpp first, so that warning messages about compiler support
+// appear as soon as possible.
+#include <boost/hana/config.hpp>
+
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+namespace boost {
+ //! Namespace containing everything in the library.
+ namespace hana {
+ //! Namespace containing C++14 user-defined literals provided by Hana.
+ namespace literals {}
+ }
+}
+#endif
+
+#include <boost/hana/accessors.hpp>
+#include <boost/hana/adapt_adt.hpp>
+#include <boost/hana/adapt_struct.hpp>
+#include <boost/hana/adjust.hpp>
+#include <boost/hana/adjust_if.hpp>
+#include <boost/hana/all.hpp>
+#include <boost/hana/all_of.hpp>
+#include <boost/hana/and.hpp>
+#include <boost/hana/any.hpp>
+#include <boost/hana/any_of.hpp>
+#include <boost/hana/ap.hpp>
+#include <boost/hana/append.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/at.hpp>
+#include <boost/hana/at_key.hpp>
+#include <boost/hana/back.hpp>
+#include <boost/hana/basic_tuple.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/cartesian_product.hpp>
+#include <boost/hana/chain.hpp>
+#include <boost/hana/comparing.hpp>
+#include <boost/hana/concat.hpp>
+#include <boost/hana/concept.hpp>
+#include <boost/hana/contains.hpp>
+#include <boost/hana/core.hpp>
+#include <boost/hana/count.hpp>
+#include <boost/hana/count_if.hpp>
+#include <boost/hana/cycle.hpp>
+#include <boost/hana/define_struct.hpp>
+#include <boost/hana/difference.hpp>
+#include <boost/hana/div.hpp>
+#include <boost/hana/drop_back.hpp>
+#include <boost/hana/drop_front.hpp>
+#include <boost/hana/drop_front_exactly.hpp>
+#include <boost/hana/drop_while.hpp>
+#include <boost/hana/duplicate.hpp>
+#include <boost/hana/empty.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/erase_key.hpp>
+#include <boost/hana/eval.hpp>
+#include <boost/hana/eval_if.hpp>
+#include <boost/hana/extend.hpp>
+#include <boost/hana/extract.hpp>
+#include <boost/hana/fill.hpp>
+#include <boost/hana/filter.hpp>
+#include <boost/hana/find.hpp>
+#include <boost/hana/find_if.hpp>
+#include <boost/hana/first.hpp>
+#include <boost/hana/flatten.hpp>
+#include <boost/hana/fold.hpp>
+#include <boost/hana/fold_left.hpp>
+#include <boost/hana/fold_right.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/front.hpp>
+#include <boost/hana/functional.hpp>
+#include <boost/hana/fuse.hpp>
+#include <boost/hana/greater.hpp>
+#include <boost/hana/greater_equal.hpp>
+#include <boost/hana/group.hpp>
+#include <boost/hana/if.hpp>
+#include <boost/hana/insert.hpp>
+#include <boost/hana/insert_range.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/intersection.hpp>
+#include <boost/hana/intersperse.hpp>
+#include <boost/hana/is_disjoint.hpp>
+#include <boost/hana/is_empty.hpp>
+#include <boost/hana/is_subset.hpp>
+#include <boost/hana/keys.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/less.hpp>
+#include <boost/hana/less_equal.hpp>
+#include <boost/hana/lexicographical_compare.hpp>
+#include <boost/hana/lift.hpp>
+#include <boost/hana/map.hpp>
+#include <boost/hana/max.hpp>
+#include <boost/hana/maximum.hpp>
+#include <boost/hana/members.hpp>
+#include <boost/hana/min.hpp>
+#include <boost/hana/minimum.hpp>
+#include <boost/hana/minus.hpp>
+#include <boost/hana/mod.hpp>
+#include <boost/hana/monadic_compose.hpp>
+#include <boost/hana/monadic_fold_left.hpp>
+#include <boost/hana/monadic_fold_right.hpp>
+#include <boost/hana/mult.hpp>
+#include <boost/hana/negate.hpp>
+#include <boost/hana/none.hpp>
+#include <boost/hana/none_of.hpp>
+#include <boost/hana/not.hpp>
+#include <boost/hana/not_equal.hpp>
+#include <boost/hana/one.hpp>
+#include <boost/hana/optional.hpp>
+#include <boost/hana/or.hpp>
+#include <boost/hana/ordering.hpp>
+#include <boost/hana/pair.hpp>
+#include <boost/hana/partition.hpp>
+#include <boost/hana/permutations.hpp>
+#include <boost/hana/plus.hpp>
+#include <boost/hana/power.hpp>
+#include <boost/hana/prefix.hpp>
+#include <boost/hana/prepend.hpp>
+#include <boost/hana/product.hpp>
+#include <boost/hana/range.hpp>
+#include <boost/hana/remove.hpp>
+#include <boost/hana/remove_at.hpp>
+#include <boost/hana/remove_if.hpp>
+#include <boost/hana/remove_range.hpp>
+#include <boost/hana/repeat.hpp>
+#include <boost/hana/replace.hpp>
+#include <boost/hana/replace_if.hpp>
+#include <boost/hana/replicate.hpp>
+#include <boost/hana/reverse.hpp>
+#include <boost/hana/reverse_fold.hpp>
+#include <boost/hana/scan_left.hpp>
+#include <boost/hana/scan_right.hpp>
+#include <boost/hana/second.hpp>
+#include <boost/hana/set.hpp>
+#include <boost/hana/size.hpp>
+#include <boost/hana/slice.hpp>
+#include <boost/hana/sort.hpp>
+#include <boost/hana/span.hpp>
+#include <boost/hana/string.hpp>
+#include <boost/hana/suffix.hpp>
+#include <boost/hana/sum.hpp>
+#include <boost/hana/symmetric_difference.hpp>
+#include <boost/hana/take_back.hpp>
+#include <boost/hana/take_front.hpp>
+#include <boost/hana/take_while.hpp>
+#include <boost/hana/tap.hpp>
+#include <boost/hana/then.hpp>
+#include <boost/hana/traits.hpp>
+#include <boost/hana/transform.hpp>
+#include <boost/hana/tuple.hpp>
+#include <boost/hana/type.hpp>
+#include <boost/hana/unfold_left.hpp>
+#include <boost/hana/unfold_right.hpp>
+#include <boost/hana/union.hpp>
+#include <boost/hana/unique.hpp>
+#include <boost/hana/unpack.hpp>
+#include <boost/hana/value.hpp>
+#include <boost/hana/version.hpp>
+#include <boost/hana/while.hpp>
+#include <boost/hana/zero.hpp>
+#include <boost/hana/zip.hpp>
+#include <boost/hana/zip_shortest.hpp>
+#include <boost/hana/zip_shortest_with.hpp>
+#include <boost/hana/zip_with.hpp>
+
+#endif // !BOOST_HANA_HPP
diff --git a/boost/hana/accessors.hpp b/boost/hana/accessors.hpp
new file mode 100644
index 0000000000..06cd46b59d
--- /dev/null
+++ b/boost/hana/accessors.hpp
@@ -0,0 +1,56 @@
+/*!
+@file
+Defines `boost::hana::accessors`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_ACCESSORS_HPP
+#define BOOST_HANA_ACCESSORS_HPP
+
+#include <boost/hana/fwd/accessors.hpp>
+
+#include <boost/hana/concept/struct.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename S>
+ struct accessors_t {
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Struct<S>::value,
+ "hana::accessors<S> requires 'S' to be a Struct");
+ #endif
+
+ constexpr decltype(auto) operator()() const {
+ using Accessors = BOOST_HANA_DISPATCH_IF(accessors_impl<S>,
+ hana::Struct<S>::value
+ );
+
+ return Accessors::apply();
+ }
+ };
+
+ template <typename S, bool condition>
+ struct accessors_impl<S, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+
+ namespace struct_detail {
+ template <typename ...>
+ struct is_valid { static constexpr bool value = true; };
+ }
+
+ template <typename S>
+ struct accessors_impl<S, when<
+ struct_detail::is_valid<typename S::hana_accessors_impl>::value
+ >>
+ : S::hana_accessors_impl
+ { };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_ACCESSORS_HPP
diff --git a/boost/hana/adapt_adt.hpp b/boost/hana/adapt_adt.hpp
new file mode 100644
index 0000000000..46d39eeefc
--- /dev/null
+++ b/boost/hana/adapt_adt.hpp
@@ -0,0 +1,17 @@
+/*!
+@file
+Defines the `BOOST_HANA_ADAPT_ADT` macro.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_ADAPT_ADT_HPP
+#define BOOST_HANA_ADAPT_ADT_HPP
+
+#include <boost/hana/fwd/adapt_adt.hpp>
+
+#include <boost/hana/detail/struct_macros.hpp>
+
+#endif // !BOOST_HANA_ADAPT_ADT_HPP
diff --git a/boost/hana/adapt_struct.hpp b/boost/hana/adapt_struct.hpp
new file mode 100644
index 0000000000..85aa2f7f53
--- /dev/null
+++ b/boost/hana/adapt_struct.hpp
@@ -0,0 +1,17 @@
+/*!
+@file
+Defines the `BOOST_HANA_ADAPT_STRUCT` macro.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_ADAPT_STRUCT_HPP
+#define BOOST_HANA_ADAPT_STRUCT_HPP
+
+#include <boost/hana/fwd/adapt_struct.hpp>
+
+#include <boost/hana/detail/struct_macros.hpp>
+
+#endif // !BOOST_HANA_ADAPT_STRUCT_HPP
diff --git a/boost/hana/adjust.hpp b/boost/hana/adjust.hpp
new file mode 100644
index 0000000000..c5e2c7d3f5
--- /dev/null
+++ b/boost/hana/adjust.hpp
@@ -0,0 +1,55 @@
+/*!
+@file
+Defines `boost::hana::adjust`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_ADJUST_HPP
+#define BOOST_HANA_ADJUST_HPP
+
+#include <boost/hana/fwd/adjust.hpp>
+
+#include <boost/hana/adjust_if.hpp>
+#include <boost/hana/concept/functor.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/equal.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Value, typename F>
+ constexpr auto adjust_t::operator()(Xs&& xs, Value&& value, F&& f) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Adjust = BOOST_HANA_DISPATCH_IF(adjust_impl<S>,
+ hana::Functor<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Functor<S>::value,
+ "hana::adjust(xs, value, f) requires 'xs' to be a Functor");
+ #endif
+
+ return Adjust::apply(static_cast<Xs&&>(xs),
+ static_cast<Value&&>(value),
+ static_cast<F&&>(f));
+ }
+ //! @endcond
+
+ template <typename Fun, bool condition>
+ struct adjust_impl<Fun, when<condition>> : default_ {
+ template <typename Xs, typename Value, typename F>
+ static constexpr auto apply(Xs&& xs, Value&& value, F&& f) {
+ return hana::adjust_if(
+ static_cast<Xs&&>(xs),
+ hana::equal.to(static_cast<Value&&>(value)),
+ static_cast<F&&>(f)
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_ADJUST_HPP
diff --git a/boost/hana/adjust_if.hpp b/boost/hana/adjust_if.hpp
new file mode 100644
index 0000000000..6c1e4786fd
--- /dev/null
+++ b/boost/hana/adjust_if.hpp
@@ -0,0 +1,78 @@
+/*!
+@file
+Defines `boost::hana::adjust_if`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_ADJUST_IF_HPP
+#define BOOST_HANA_ADJUST_IF_HPP
+
+#include <boost/hana/fwd/adjust_if.hpp>
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/functor.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/if.hpp>
+#include <boost/hana/transform.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Pred, typename F>
+ constexpr auto adjust_if_t::operator()(Xs&& xs, Pred const& pred, F const& f) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using AdjustIf = BOOST_HANA_DISPATCH_IF(adjust_if_impl<S>,
+ hana::Functor<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Functor<S>::value,
+ "hana::adjust_if(xs, pred, f) requires 'xs' to be a Functor");
+ #endif
+
+ return AdjustIf::apply(static_cast<Xs&&>(xs), pred, f);
+ }
+ //! @endcond
+
+ namespace detail {
+ template <typename Pred, typename F>
+ struct apply_if {
+ Pred const& pred;
+ F const& f;
+
+ template <typename X>
+ constexpr decltype(auto) helper(bool cond, X&& x) const
+ { return cond ? f(static_cast<X&&>(x)) : static_cast<X&&>(x); }
+
+ template <typename X>
+ constexpr decltype(auto) helper(hana::true_, X&& x) const
+ { return f(static_cast<X&&>(x)); }
+
+ template <typename X>
+ constexpr decltype(auto) helper(hana::false_, X&& x) const
+ { return static_cast<X&&>(x); }
+
+
+ template <typename X>
+ constexpr decltype(auto) operator()(X&& x) const {
+ auto cond = hana::if_(pred(x), hana::true_c, hana::false_c);
+ return this->helper(cond, static_cast<X&&>(x));
+ }
+ };
+ }
+
+ template <typename Fun, bool condition>
+ struct adjust_if_impl<Fun, when<condition>> : default_ {
+ template <typename Xs, typename Pred, typename F>
+ static constexpr auto apply(Xs&& xs, Pred const& pred, F const& f) {
+ return hana::transform(static_cast<Xs&&>(xs),
+ detail::apply_if<Pred, F>{pred, f});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_ADJUST_IF_HPP
diff --git a/boost/hana/all.hpp b/boost/hana/all.hpp
new file mode 100644
index 0000000000..84912928e9
--- /dev/null
+++ b/boost/hana/all.hpp
@@ -0,0 +1,48 @@
+/*!
+@file
+Defines `boost::hana::all`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_ALL_HPP
+#define BOOST_HANA_ALL_HPP
+
+#include <boost/hana/fwd/all.hpp>
+
+#include <boost/hana/all_of.hpp>
+#include <boost/hana/concept/searchable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/functional/id.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs>
+ constexpr auto all_t::operator()(Xs&& xs) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using All = BOOST_HANA_DISPATCH_IF(all_impl<S>,
+ hana::Searchable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Searchable<S>::value,
+ "hana::all(xs) requires 'xs' to be a Searchable");
+ #endif
+
+ return All::apply(static_cast<Xs&&>(xs));
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct all_impl<S, when<condition>> : default_ {
+ template <typename Xs>
+ static constexpr auto apply(Xs&& xs)
+ { return hana::all_of(static_cast<Xs&&>(xs), hana::id); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_ALL_HPP
diff --git a/boost/hana/all_of.hpp b/boost/hana/all_of.hpp
new file mode 100644
index 0000000000..ade2624d9e
--- /dev/null
+++ b/boost/hana/all_of.hpp
@@ -0,0 +1,51 @@
+/*!
+@file
+Defines `boost::hana::all_of`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_ALL_OF_HPP
+#define BOOST_HANA_ALL_OF_HPP
+
+#include <boost/hana/fwd/all_of.hpp>
+
+#include <boost/hana/any_of.hpp>
+#include <boost/hana/concept/searchable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/not.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Pred>
+ constexpr auto all_of_t::operator()(Xs&& xs, Pred&& pred) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using AllOf = BOOST_HANA_DISPATCH_IF(all_of_impl<S>,
+ hana::Searchable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Searchable<S>::value,
+ "hana::all_of(xs, pred) requires 'xs' to be a Searchable");
+ #endif
+
+ return AllOf::apply(static_cast<Xs&&>(xs), static_cast<Pred&&>(pred));
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct all_of_impl<S, when<condition>> : default_ {
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs&& xs, Pred&& pred) {
+ return hana::not_(hana::any_of(static_cast<Xs&&>(xs),
+ hana::compose(hana::not_, static_cast<Pred&&>(pred))));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_ALL_OF_HPP
diff --git a/boost/hana/and.hpp b/boost/hana/and.hpp
new file mode 100644
index 0000000000..a883ac9bad
--- /dev/null
+++ b/boost/hana/and.hpp
@@ -0,0 +1,58 @@
+/*!
+@file
+Defines `boost::hana::and_`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_AND_HPP
+#define BOOST_HANA_AND_HPP
+
+#include <boost/hana/fwd/and.hpp>
+
+#include <boost/hana/concept/logical.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/variadic/foldl1.hpp>
+#include <boost/hana/if.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename X, typename Y>
+ constexpr decltype(auto) and_t::operator()(X&& x, Y&& y) const {
+ using Bool = typename hana::tag_of<X>::type;
+ using And = BOOST_HANA_DISPATCH_IF(and_impl<Bool>,
+ hana::Logical<Bool>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Logical<Bool>::value,
+ "hana::and_(x, y) requires 'x' to be a Logical");
+ #endif
+
+ return And::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
+ }
+
+ template <typename X, typename ...Y>
+ constexpr decltype(auto) and_t::operator()(X&& x, Y&& ...y) const {
+ return detail::variadic::foldl1(
+ *this,
+ static_cast<X&&>(x),
+ static_cast<Y&&>(y)...
+ );
+ }
+ //! @endcond
+
+ template <typename L, bool condition>
+ struct and_impl<L, when<condition>> : default_ {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y) {
+ return hana::if_(x, static_cast<Y&&>(y), x);
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_AND_HPP
diff --git a/boost/hana/any.hpp b/boost/hana/any.hpp
new file mode 100644
index 0000000000..48670fb50b
--- /dev/null
+++ b/boost/hana/any.hpp
@@ -0,0 +1,48 @@
+/*!
+@file
+Defines `boost::hana::any`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_ANY_HPP
+#define BOOST_HANA_ANY_HPP
+
+#include <boost/hana/fwd/any.hpp>
+
+#include <boost/hana/any_of.hpp>
+#include <boost/hana/concept/searchable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/functional/id.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs>
+ constexpr auto any_t::operator()(Xs&& xs) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Any = BOOST_HANA_DISPATCH_IF(any_impl<S>,
+ hana::Searchable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Searchable<S>::value,
+ "hana::any(xs) requires 'xs' to be a Searchable");
+ #endif
+
+ return Any::apply(static_cast<Xs&&>(xs));
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct any_impl<S, when<condition>> : default_ {
+ template <typename Xs>
+ static constexpr auto apply(Xs&& xs)
+ { return hana::any_of(static_cast<Xs&&>(xs), hana::id); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_ANY_HPP
diff --git a/boost/hana/any_of.hpp b/boost/hana/any_of.hpp
new file mode 100644
index 0000000000..1dd1cde9be
--- /dev/null
+++ b/boost/hana/any_of.hpp
@@ -0,0 +1,190 @@
+/*!
+@file
+Defines `boost::hana::any_of`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_ANY_OF_HPP
+#define BOOST_HANA_ANY_OF_HPP
+
+#include <boost/hana/fwd/any_of.hpp>
+
+#include <boost/hana/accessors.hpp>
+#include <boost/hana/at.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/searchable.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/concept/struct.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/drop_front.hpp>
+#include <boost/hana/first.hpp>
+#include <boost/hana/front.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/if.hpp>
+#include <boost/hana/is_empty.hpp>
+#include <boost/hana/length.hpp>
+
+#include <cstddef>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Pred>
+ constexpr auto any_of_t::operator()(Xs&& xs, Pred&& pred) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using AnyOf = BOOST_HANA_DISPATCH_IF(any_of_impl<S>,
+ hana::Searchable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Searchable<S>::value,
+ "hana::any_of(xs, pred) requires 'xs' to be a Searchable");
+ #endif
+
+ return AnyOf::apply(static_cast<Xs&&>(xs), static_cast<Pred&&>(pred));
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct any_of_impl<S, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+
+ template <typename S>
+ struct any_of_impl<S, when<Sequence<S>::value>> {
+ //! @cond
+ template <std::size_t k, std::size_t Len>
+ struct any_of_helper {
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(bool prev_cond, Xs&& xs, Pred&& pred) {
+ auto cond = hana::if_(pred(hana::at_c<k>(xs)), hana::true_c,
+ hana::false_c);
+ return prev_cond ? hana::true_c
+ : any_of_impl::any_of_helper<k + 1, Len>::apply(cond,
+ static_cast<Xs&&>(xs),
+ static_cast<Pred&&>(pred));
+ }
+
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(hana::true_, Xs&&, Pred&&)
+ { return hana::true_c; }
+
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(hana::false_, Xs&& xs, Pred&& pred) {
+ auto cond = hana::if_(pred(hana::at_c<k>(xs)), hana::true_c,
+ hana::false_c);
+ return any_of_impl::any_of_helper<k + 1, Len>::apply(cond,
+ static_cast<Xs&&>(xs),
+ static_cast<Pred&&>(pred));
+ }
+ };
+
+ template <std::size_t Len>
+ struct any_of_helper<Len, Len> {
+ template <typename Cond, typename Xs, typename Pred>
+ static constexpr auto apply(Cond cond, Xs&&, Pred&&)
+ { return cond; }
+ };
+
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs&& xs, Pred&& pred) {
+ constexpr std::size_t len = decltype(hana::length(xs))::value;
+ return any_of_impl::any_of_helper<0, len>::apply(hana::false_c,
+ static_cast<Xs&&>(xs),
+ static_cast<Pred&&>(pred));
+ }
+ //! @endcond
+ };
+
+ template <typename It>
+ struct any_of_impl<It, when<
+ hana::Iterable<It>::value &&
+ !Sequence<It>::value
+ >> {
+ template <typename Xs, typename Pred>
+ static constexpr auto lazy_any_of_helper(hana::false_, bool prev_cond, Xs&& xs, Pred&& pred) {
+ auto cond = hana::if_(pred(hana::front(xs)), hana::true_c, hana::false_c);
+ decltype(auto) tail = hana::drop_front(static_cast<Xs&&>(xs));
+ constexpr bool done = decltype(hana::is_empty(tail))::value;
+ return prev_cond ? hana::true_c
+ : lazy_any_of_helper(hana::bool_c<done>, cond,
+ static_cast<decltype(tail)&&>(tail),
+ static_cast<Pred&&>(pred));
+ }
+
+ template <typename Xs, typename Pred>
+ static constexpr auto lazy_any_of_helper(hana::false_, hana::true_, Xs&&, Pred&&)
+ { return hana::true_c; }
+
+ template <typename Xs, typename Pred>
+ static constexpr auto lazy_any_of_helper(hana::false_, hana::false_, Xs&& xs, Pred&& pred) {
+ auto cond = hana::if_(pred(hana::front(xs)), hana::true_c, hana::false_c);
+ constexpr bool done = decltype(hana::is_empty(hana::drop_front(xs)))::value;
+ return lazy_any_of_helper(hana::bool_c<done>, cond,
+ hana::drop_front(static_cast<Xs&&>(xs)),
+ static_cast<Pred&&>(pred));
+ }
+
+ template <typename Cond, typename Xs, typename Pred>
+ static constexpr auto lazy_any_of_helper(hana::true_, Cond cond, Xs&&, Pred&&)
+ { return cond; }
+
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs&& xs, Pred&& pred) {
+ constexpr bool done = decltype(hana::is_empty(xs))::value;
+ return lazy_any_of_helper(hana::bool_c<done>, hana::false_c,
+ static_cast<Xs&&>(xs),
+ static_cast<Pred&&>(pred));
+ }
+ };
+
+ template <typename T, std::size_t N>
+ struct any_of_impl<T[N]> {
+ template <typename Xs, typename Pred>
+ static constexpr bool any_of_helper(bool cond, Xs&& xs, Pred&& pred) {
+ if (cond) return true;
+ for (std::size_t i = 1; i < N; ++i)
+ if (pred(static_cast<Xs&&>(xs)[i]))
+ return true;
+ return false;
+ }
+
+ // Since an array contains homogeneous data, if the predicate returns
+ // a compile-time logical at any index, it must do so at every index
+ // (because the type of the elements won't change)! In this case, we
+ // then only need to evaluate the predicate on the first element.
+ template <typename Xs, typename Pred>
+ static constexpr auto
+ any_of_helper(hana::true_, Xs&& /*xs*/, Pred&&)
+ { return hana::true_c; }
+
+ template <typename Xs, typename Pred>
+ static constexpr auto
+ any_of_helper(hana::false_, Xs&&, Pred&&)
+ { return hana::false_c; }
+
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs&& xs, Pred&& pred) {
+ auto cond = hana::if_(pred(static_cast<Xs&&>(xs)[0]), hana::true_c,
+ hana::false_c);
+ return any_of_helper(cond, static_cast<Xs&&>(xs),
+ static_cast<Pred&&>(pred));
+ }
+ };
+
+ template <typename S>
+ struct any_of_impl<S, when<hana::Struct<S>::value>> {
+ template <typename X, typename Pred>
+ static constexpr decltype(auto) apply(X const&, Pred&& pred) {
+ return hana::any_of(hana::accessors<S>(),
+ hana::compose(static_cast<Pred&&>(pred), hana::first));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_ANY_OF_HPP
diff --git a/boost/hana/ap.hpp b/boost/hana/ap.hpp
new file mode 100644
index 0000000000..a344244090
--- /dev/null
+++ b/boost/hana/ap.hpp
@@ -0,0 +1,78 @@
+/*!
+@file
+Defines `boost::hana::ap`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_AP_HPP
+#define BOOST_HANA_AP_HPP
+
+#include <boost/hana/fwd/ap.hpp>
+
+#include <boost/hana/chain.hpp>
+#include <boost/hana/concept/applicative.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/variadic/foldl1.hpp>
+#include <boost/hana/functional/curry.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/transform.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename A, bool condition>
+ struct ap_impl<A, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...args) = delete;
+ };
+
+ //! @cond
+ template <typename F, typename X>
+ constexpr decltype(auto) ap_t::operator()(F&& f, X&& x) const {
+ using Function = typename hana::tag_of<F>::type;
+ using Value = typename hana::tag_of<X>::type;
+ using Ap = BOOST_HANA_DISPATCH_IF(ap_impl<Function>,
+ hana::Applicative<Function>::value && hana::Applicative<Value>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Applicative<Function>::value,
+ "hana::ap(f, x) requires 'f' to be an Applicative");
+
+ static_assert(hana::Applicative<Value>::value,
+ "hana::ap(f, x) requires 'x' to be an Applicative");
+ #endif
+
+ return Ap::apply(static_cast<F&&>(f), static_cast<X&&>(x));
+ }
+
+ template <typename F, typename ...Xs>
+ constexpr decltype(auto) ap_t::operator()(F&& f, Xs&& ...xs) const {
+ static_assert(sizeof...(xs) >= 1,
+ "hana::ap must be called with at least two arguments");
+
+ return detail::variadic::foldl1(
+ *this,
+ hana::transform(static_cast<F&&>(f), hana::curry<sizeof...(xs)>),
+ static_cast<Xs&&>(xs)...
+ );
+ }
+ //! @endcond
+
+ template <typename S>
+ struct ap_impl<S, when<Sequence<S>::value>> {
+ template <typename F, typename X>
+ static constexpr decltype(auto) apply(F&& f, X&& x) {
+ return hana::chain(
+ static_cast<F&&>(f),
+ hana::partial(hana::transform, static_cast<X&&>(x))
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_AP_HPP
diff --git a/boost/hana/append.hpp b/boost/hana/append.hpp
new file mode 100644
index 0000000000..6c4cf4d02f
--- /dev/null
+++ b/boost/hana/append.hpp
@@ -0,0 +1,74 @@
+/*!
+@file
+Defines `boost::hana::append`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_APPEND_HPP
+#define BOOST_HANA_APPEND_HPP
+
+#include <boost/hana/fwd/append.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concat.hpp>
+#include <boost/hana/concept/monad_plus.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/lift.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename X>
+ constexpr auto append_t::operator()(Xs&& xs, X&& x) const {
+ using M = typename hana::tag_of<Xs>::type;
+ using Append = BOOST_HANA_DISPATCH_IF(append_impl<M>,
+ hana::MonadPlus<M>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::MonadPlus<M>::value,
+ "hana::append(xs, x) requires 'xs' to be a MonadPlus");
+ #endif
+
+ return Append::apply(static_cast<Xs&&>(xs), static_cast<X&&>(x));
+ }
+ //! @endcond
+
+ template <typename M, bool condition>
+ struct append_impl<M, when<condition>> : default_ {
+ template <typename Xs, typename X>
+ static constexpr auto apply(Xs&& xs, X&& x) {
+ return hana::concat(static_cast<Xs&&>(xs),
+ hana::lift<M>(static_cast<X&&>(x)));
+ }
+ };
+
+ template <typename S>
+ struct append_impl<S, when<Sequence<S>::value>> {
+ template <typename Xs, typename X, std::size_t ...i>
+ static constexpr auto append_helper(Xs&& xs, X&& x, std::index_sequence<i...>) {
+ return hana::make<S>(
+ hana::at_c<i>(static_cast<Xs&&>(xs))..., static_cast<X&&>(x)
+ );
+ }
+
+ template <typename Xs, typename X>
+ static constexpr auto apply(Xs&& xs, X&& x) {
+ constexpr std::size_t N = decltype(hana::length(xs))::value;
+ return append_helper(static_cast<Xs&&>(xs), static_cast<X&&>(x),
+ std::make_index_sequence<N>{});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_APPEND_HPP
diff --git a/boost/hana/assert.hpp b/boost/hana/assert.hpp
new file mode 100644
index 0000000000..c529770474
--- /dev/null
+++ b/boost/hana/assert.hpp
@@ -0,0 +1,306 @@
+/*!
+@file
+Defines macros to perform different kinds of assertions.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_ASSERT_HPP
+#define BOOST_HANA_ASSERT_HPP
+
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/preprocessor.hpp>
+#include <boost/hana/if.hpp>
+#include <boost/hana/value.hpp>
+
+#include <cstdio>
+#include <cstdlib>
+
+
+#if defined(BOOST_HANA_DOXYGEN_INVOKED)
+ //! @ingroup group-assertions
+ //! Expands to a runtime assertion.
+ //!
+ //! Given a condition known at runtime, this macro expands to a runtime
+ //! assertion similar to the `assert` macro. The provided condition must
+ //! be explicitly convertible to a `bool`, and it must not be a model of
+ //! the `Constant` concept. If the condition is a `Constant`, a static
+ //! assertion will be triggered, asking you to use the
+ //! `BOOST_HANA_CONSTANT_ASSERT` macro instead.
+ //!
+ //! @note
+ //! This macro may only be used at function scope.
+# define BOOST_HANA_RUNTIME_ASSERT(condition) unspecified
+
+ //! @ingroup group-assertions
+ //! Equivalent to `BOOST_HANA_RUNTIME_ASSERT`, but allows providing a
+ //! custom failure message.
+ //!
+ //! @warning
+ //! Conditions that contain multiple comma-separated elements should be
+ //! parenthesized.
+# define BOOST_HANA_RUNTIME_ASSERT_MSG(condition, message) unspecified
+
+ //! @ingroup group-assertions
+ //! Compile-time assertion for `Constant`s.
+ //!
+ //! Given a condition known at compile-time in the form of a `Constant`,
+ //! this macro expands to a compile-time assertion similar to a `static_assert`.
+ //! The provided condition must be a model of the `Constant` concept, in
+ //! which case its value is retrieved using `hana::value` and then converted
+ //! to a `bool`. If the condition is not a `Constant`, a static assertion
+ //! will be triggered, asking you to use the `BOOST_HANA_RUNTIME_ASSERT`
+ //! macro instead.
+ //!
+ //! This macro may be used at global/namespace scope and function scope
+ //! only; it may not be used at class scope. Note that the condition may
+ //! never be evaluated at runtime. Hence, any side effect may not take
+ //! place (but you shouldn't rely on side effects inside assertions anyway).
+# define BOOST_HANA_CONSTANT_ASSERT(condition) unspecified
+
+ //! @ingroup group-assertions
+ //! Equivalent to `BOOST_HANA_CONSTANT_ASSERT`, but allows providing a
+ //! custom failure message.
+ //!
+ //! @warning
+ //! Conditions that contain multiple comma-separated elements should be
+ //! parenthesized.
+# define BOOST_HANA_CONSTANT_ASSERT_MSG(condition, message) unspecified
+
+ //! @ingroup group-assertions
+ //! Expands to the strongest form of assertion possible for the given
+ //! condition.
+ //!
+ //! Given a condition, `BOOST_HANA_ASSERT` expands either to a compile-time
+ //! or to a runtime assertion, depending on whether the value of the
+ //! condition is known at compile-time or at runtime. Compile-time
+ //! assertions are always preferred over runtime assertions. If the
+ //! condition is a model of the `Constant` concept, its value (retrievable
+ //! with `hana::value`) is assumed to be explicitly convertible to `bool`,
+ //! and a compile-time assertion is performed on it. Otherwise, the
+ //! condition itself is assumed to be explicitly convertible to `bool`,
+ //! and a runtime assertion is performed on it.
+ //!
+ //! If the assertion can be carried out at compile-time, the condition
+ //! is not guaranteed to be evaluated at runtime at all (but it may).
+ //! Hence, in general, you shouldn't rely on side effects that take place
+ //! inside an assertion.
+ //!
+ //! @note
+ //! This macro may only be used at function scope.
+# define BOOST_HANA_ASSERT(condition) unspecified
+
+ //! @ingroup group-assertions
+ //! Equivalent to `BOOST_HANA_ASSERT`, but allows providing a custom
+ //! failure message.
+ //!
+ //! @warning
+ //! Conditions that contain multiple comma-separated elements should be
+ //! parenthesized.
+# define BOOST_HANA_ASSERT_MSG(condition, message) unspecified
+
+ //! @ingroup group-assertions
+ //! Expands to a static assertion or a runtime assertion, depending on
+ //! whether `constexpr` lambdas are supported.
+ //!
+ //! This macro is used to assert on a condition that would be a constant
+ //! expression if constexpr lambdas were supported. Right now, constexpr
+ //! lambdas are not supported, and this is always a runtime assertion.
+ //! Specifically, this is equivalent to `BOOST_HANA_RUNTIME_ASSERT`.
+# define BOOST_HANA_CONSTEXPR_ASSERT(condition) unspecified
+
+ //! @ingroup group-assertions
+ //! Equivalent to `BOOST_HANA_CONSTEXPR_ASSERT`, but allows providing a
+ //! custom failure message.
+# define BOOST_HANA_CONSTEXPR_ASSERT_MSG(condition, message) unspecified
+
+#elif defined(BOOST_HANA_CONFIG_DISABLE_ASSERTIONS)
+
+# define BOOST_HANA_CONSTANT_ASSERT(...) /* nothing */
+# define BOOST_HANA_CONSTANT_ASSERT_MSG(condition, message) /* nothing */
+
+# define BOOST_HANA_RUNTIME_ASSERT(...) /* nothing */
+# define BOOST_HANA_RUNTIME_ASSERT_MSG(condition, message) /* nothing */
+
+# define BOOST_HANA_ASSERT(...) /* nothing */
+# define BOOST_HANA_ASSERT_MSG(condition, message) /* nothing */
+
+# define BOOST_HANA_CONSTEXPR_ASSERT(...) /* nothing */
+# define BOOST_HANA_CONSTEXPR_ASSERT_MSG(condition, message) /* nothing */
+
+#else
+
+//////////////////////////////////////////////////////////////////////////////
+// BOOST_HANA_RUNTIME_ASSERT and BOOST_HANA_RUNTIME_ASSERT_MSG
+//////////////////////////////////////////////////////////////////////////////
+# define BOOST_HANA_RUNTIME_ASSERT_MSG(condition, message) \
+ BOOST_HANA_RUNTIME_CHECK_MSG(condition, message) \
+/**/
+
+# define BOOST_HANA_RUNTIME_ASSERT(...) \
+ BOOST_HANA_RUNTIME_CHECK(__VA_ARGS__) \
+/**/
+
+//////////////////////////////////////////////////////////////////////////////
+// BOOST_HANA_CONSTANT_ASSERT and BOOST_HANA_CONSTANT_ASSERT_MSG
+//////////////////////////////////////////////////////////////////////////////
+# define BOOST_HANA_CONSTANT_ASSERT_MSG(condition, message) \
+ BOOST_HANA_CONSTANT_CHECK_MSG(condition, message) \
+/**/
+
+# define BOOST_HANA_CONSTANT_ASSERT(...) \
+ BOOST_HANA_CONSTANT_CHECK(__VA_ARGS__) \
+/**/
+
+//////////////////////////////////////////////////////////////////////////////
+// BOOST_HANA_ASSERT and BOOST_HANA_ASSERT_MSG
+//////////////////////////////////////////////////////////////////////////////
+# define BOOST_HANA_ASSERT_MSG(condition, message) \
+ BOOST_HANA_CHECK_MSG(condition, message) \
+/**/
+
+# define BOOST_HANA_ASSERT(...) \
+ BOOST_HANA_CHECK(__VA_ARGS__) \
+/**/
+
+//////////////////////////////////////////////////////////////////////////////
+// BOOST_HANA_CONSTEXPR_ASSERT and BOOST_HANA_CONSTEXPR_ASSERT_MSG
+//////////////////////////////////////////////////////////////////////////////
+# define BOOST_HANA_CONSTEXPR_ASSERT_MSG(condition, message) \
+ BOOST_HANA_CONSTEXPR_CHECK_MSG(condition, message) \
+/**/
+
+# define BOOST_HANA_CONSTEXPR_ASSERT(...) \
+ BOOST_HANA_CONSTEXPR_CHECK(__VA_ARGS__) \
+/**/
+
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// BOOST_HANA_RUNTIME_CHECK and BOOST_HANA_RUNTIME_CHECK_MSG
+//////////////////////////////////////////////////////////////////////////////
+
+//! @ingroup group-assertions
+//! Equivalent to `BOOST_HANA_RUNTIME_ASSERT_MSG`, but not influenced by the
+//! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
+# define BOOST_HANA_RUNTIME_CHECK_MSG(condition, message) \
+ do { \
+ auto __hana_tmp = condition; \
+ static_assert(!::boost::hana::Constant<decltype(__hana_tmp)>::value,\
+ "the expression (" # condition ") yields a Constant; " \
+ "use BOOST_HANA_CONSTANT_ASSERT instead"); \
+ \
+ if (!static_cast<bool>(__hana_tmp)) { \
+ ::std::fprintf(stderr, "Assertion failed: " \
+ "(%s), function %s, file %s, line %i.\n", \
+ message, __func__, __FILE__, __LINE__); \
+ ::std::abort(); \
+ } \
+ } while (false); \
+ static_assert(true, "force trailing semicolon") \
+/**/
+
+//! @ingroup group-assertions
+//! Equivalent to `BOOST_HANA_RUNTIME_ASSERT`, but not influenced by the
+//! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
+# define BOOST_HANA_RUNTIME_CHECK(...) \
+ BOOST_HANA_RUNTIME_CHECK_MSG( \
+ (__VA_ARGS__), \
+ BOOST_HANA_PP_STRINGIZE(__VA_ARGS__) \
+ ) \
+/**/
+
+//////////////////////////////////////////////////////////////////////////////
+// BOOST_HANA_CONSTANT_CHECK and BOOST_HANA_CONSTANT_CHECK_MSG
+//////////////////////////////////////////////////////////////////////////////
+
+//! @ingroup group-assertions
+//! Equivalent to `BOOST_HANA_CONSTANT_ASSERT_MSG`, but not influenced by the
+//! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
+# define BOOST_HANA_CONSTANT_CHECK_MSG(condition, message) \
+ auto BOOST_HANA_PP_CONCAT(__hana_tmp_, __LINE__) = condition; \
+ static_assert(::boost::hana::Constant< \
+ decltype(BOOST_HANA_PP_CONCAT(__hana_tmp_, __LINE__)) \
+ >::value, \
+ "the expression " # condition " does not yield a Constant; " \
+ "use BOOST_HANA_RUNTIME_ASSERT instead"); \
+ static_assert(::boost::hana::value< \
+ decltype(BOOST_HANA_PP_CONCAT(__hana_tmp_, __LINE__)) \
+ >(), message); \
+ static_assert(true, "force trailing semicolon") \
+/**/
+
+//! @ingroup group-assertions
+//! Equivalent to `BOOST_HANA_CONSTANT_ASSERT`, but not influenced by the
+//! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
+# define BOOST_HANA_CONSTANT_CHECK(...) \
+ BOOST_HANA_CONSTANT_CHECK_MSG( \
+ (__VA_ARGS__), \
+ BOOST_HANA_PP_STRINGIZE(__VA_ARGS__) \
+ ) \
+/**/
+
+//////////////////////////////////////////////////////////////////////////////
+// BOOST_HANA_CHECK and BOOST_HANA_CHECK_MSG
+//////////////////////////////////////////////////////////////////////////////
+
+//! @ingroup group-assertions
+//! Equivalent to `BOOST_HANA_ASSERT_MSG`, but not influenced by the
+//! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
+# define BOOST_HANA_CHECK_MSG(condition, message) \
+ do { \
+ auto __hana_tmp = condition; \
+ ::boost::hana::if_(::boost::hana::bool_c< \
+ ::boost::hana::Constant<decltype(__hana_tmp)>::value>, \
+ [](auto expr) { \
+ static_assert(::boost::hana::value<decltype(expr)>(), \
+ message); \
+ }, \
+ [](auto expr) { \
+ if (!static_cast<bool>(expr)) { \
+ ::std::fprintf(stderr, "Assertion failed: " \
+ "(%s), function %s, file %s, line %i.\n", \
+ message, __func__, __FILE__, __LINE__); \
+ ::std::abort(); \
+ } \
+ } \
+ )(__hana_tmp); \
+ } while (false); \
+ static_assert(true, "force trailing semicolon") \
+/**/
+
+//! @ingroup group-assertions
+//! Equivalent to `BOOST_HANA__ASSERT`, but not influenced by the
+//! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
+# define BOOST_HANA_CHECK(...) \
+ BOOST_HANA_CHECK_MSG( \
+ (__VA_ARGS__), \
+ BOOST_HANA_PP_STRINGIZE(__VA_ARGS__) \
+ ) \
+/**/
+
+//////////////////////////////////////////////////////////////////////////////
+// BOOST_HANA_CONSTEXPR_CHECK and BOOST_HANA_CONSTEXPR_CHECK_MSG
+//////////////////////////////////////////////////////////////////////////////
+
+//! @ingroup group-assertions
+//! Equivalent to `BOOST_HANA_CONSTEXPR_ASSERT_MSG`, but not influenced by the
+//! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
+# define BOOST_HANA_CONSTEXPR_CHECK_MSG(condition, message) \
+ BOOST_HANA_RUNTIME_CHECK_MSG(condition, message) \
+/**/
+
+//! @ingroup group-assertions
+//! Equivalent to `BOOST_HANA_CONSTEXPR_ASSERT`, but not influenced by the
+//! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
+# define BOOST_HANA_CONSTEXPR_CHECK(...) \
+ BOOST_HANA_CONSTEXPR_CHECK_MSG( \
+ (__VA_ARGS__), \
+ BOOST_HANA_PP_STRINGIZE(__VA_ARGS__) \
+ ) \
+/**/
+
+#endif // !BOOST_HANA_ASSERT_HPP
diff --git a/boost/hana/at.hpp b/boost/hana/at.hpp
new file mode 100644
index 0000000000..dc208323b1
--- /dev/null
+++ b/boost/hana/at.hpp
@@ -0,0 +1,57 @@
+/*!
+@file
+Defines `boost::hana::at` and `boost::hana::at_c`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_AT_HPP
+#define BOOST_HANA_AT_HPP
+
+#include <boost/hana/fwd/at.hpp>
+
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/concept/iterable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/integral_constant.hpp>
+
+#include <cstddef>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename N>
+ constexpr decltype(auto) at_t::operator()(Xs&& xs, N const& n) const {
+ using It = typename hana::tag_of<Xs>::type;
+ using At = BOOST_HANA_DISPATCH_IF(at_impl<It>,
+ hana::Iterable<It>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Iterable<It>::value,
+ "hana::at(xs, n) requires 'xs' to be an Iterable");
+
+ static_assert(hana::IntegralConstant<N>::value,
+ "hana::at(xs, n) requires 'n' to be an IntegralConstant");
+ #endif
+
+ return At::apply(static_cast<Xs&&>(xs), n);
+ }
+ //! @endcond
+
+ template <typename It, bool condition>
+ struct at_impl<It, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+
+ template <std::size_t n, typename Xs>
+ constexpr decltype(auto) at_c(Xs&& xs) {
+ return hana::at(static_cast<Xs&&>(xs), hana::size_c<n>);
+ }
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_AT_HPP
diff --git a/boost/hana/at_key.hpp b/boost/hana/at_key.hpp
new file mode 100644
index 0000000000..af8d5a603a
--- /dev/null
+++ b/boost/hana/at_key.hpp
@@ -0,0 +1,121 @@
+/*!
+@file
+Defines `boost::hana::at_key`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_AT_KEY_HPP
+#define BOOST_HANA_AT_KEY_HPP
+
+#include <boost/hana/fwd/at_key.hpp>
+
+#include <boost/hana/accessors.hpp>
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/searchable.hpp>
+#include <boost/hana/concept/struct.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/decay.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/find.hpp>
+#include <boost/hana/find_if.hpp>
+#include <boost/hana/first.hpp>
+#include <boost/hana/functional/on.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/optional.hpp>
+#include <boost/hana/second.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Key>
+ constexpr decltype(auto) at_key_t::operator()(Xs&& xs, Key const& key) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using AtKey = BOOST_HANA_DISPATCH_IF(at_key_impl<S>,
+ hana::Searchable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Searchable<S>::value,
+ "hana::at_key(xs, key) requires 'xs' to be Searchable");
+ #endif
+
+ return AtKey::apply(static_cast<Xs&&>(xs), key);
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct at_key_impl<S, when<condition>> : default_ {
+ template <typename Xs, typename Key>
+ static constexpr auto apply(Xs&& xs, Key const& key) {
+ return hana::find(static_cast<Xs&&>(xs), key).value();
+ }
+ };
+
+ namespace at_key_detail {
+ template <typename T>
+ struct equal_to {
+ T const& t;
+ template <typename U>
+ constexpr auto operator()(U const& u) const {
+ return hana::equal(t, u);
+ }
+ };
+
+ //! @todo This causes an awful duplication of code with `find_if`.
+ template <typename Xs, typename Pred, std::size_t i, std::size_t N, bool Done>
+ struct advance_until;
+
+ template <typename Xs, typename Pred, std::size_t i, std::size_t N>
+ struct advance_until<Xs, Pred, i, N, false>
+ : advance_until<Xs, Pred, i + 1, N, static_cast<bool>(detail::decay<decltype(
+ std::declval<Pred>()(hana::at_c<i>(std::declval<Xs>()))
+ )>::type::value)>
+ { };
+
+ template <typename Xs, typename Pred, std::size_t N>
+ struct advance_until<Xs, Pred, N, N, false> {
+ template <typename Ys>
+ static constexpr auto apply(Ys&&) = delete;
+ };
+
+ template <typename Xs, typename Pred, std::size_t i, std::size_t N>
+ struct advance_until<Xs, Pred, i, N, true> {
+ template <typename Ys>
+ static constexpr decltype(auto) apply(Ys&& ys) {
+ return hana::at_c<i - 1>(static_cast<Ys&&>(ys));
+ }
+ };
+ }
+
+ template <typename S>
+ struct at_key_impl<S, when<hana::Sequence<S>::value>> {
+ template <typename Xs, typename Key>
+ static constexpr decltype(auto) apply(Xs&& xs, Key const&) {
+ constexpr std::size_t N = decltype(hana::length(xs))::value;
+ using Pred = at_key_detail::equal_to<Key>;
+ return at_key_detail::advance_until<Xs&&, Pred, 0, N, false>::apply(
+ static_cast<Xs&&>(xs)
+ );
+ }
+ };
+
+ template <typename S>
+ struct at_key_impl<S, when<hana::Struct<S>::value>> {
+ template <typename X, typename Key>
+ static constexpr decltype(auto) apply(X&& x, Key const& key) {
+ auto accessor = hana::second(*hana::find_if(hana::accessors<S>(),
+ hana::equal.to(key) ^hana::on^ hana::first
+ ));
+ return accessor(static_cast<X&&>(x));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_AT_KEY_HPP
diff --git a/boost/hana/back.hpp b/boost/hana/back.hpp
new file mode 100644
index 0000000000..76efcf7717
--- /dev/null
+++ b/boost/hana/back.hpp
@@ -0,0 +1,53 @@
+/*!
+@file
+Defines `boost::hana::back`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_BACK_HPP
+#define BOOST_HANA_BACK_HPP
+
+#include <boost/hana/fwd/back.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/iterable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/length.hpp>
+
+#include <cstddef>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs>
+ constexpr decltype(auto) back_t::operator()(Xs&& xs) const {
+ using It = typename hana::tag_of<Xs>::type;
+ using Back = BOOST_HANA_DISPATCH_IF(back_impl<It>,
+ hana::Iterable<It>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Iterable<It>::value,
+ "hana::back(xs) requires 'xs' to be an Iterable");
+ #endif
+
+ return Back::apply(static_cast<Xs&&>(xs));
+ }
+ //! @endcond
+
+ template <typename It, bool condition>
+ struct back_impl<It, when<condition>> : default_ {
+ template <typename Xs>
+ static constexpr decltype(auto) apply(Xs&& xs) {
+ constexpr std::size_t len = decltype(hana::length(xs))::value;
+ static_assert(len > 0, "hana::back(xs) requires 'xs' to be non-empty");
+ return hana::at_c<len - 1>(static_cast<Xs&&>(xs));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_BACK_HPP
diff --git a/boost/hana/basic_tuple.hpp b/boost/hana/basic_tuple.hpp
new file mode 100644
index 0000000000..685011e10c
--- /dev/null
+++ b/boost/hana/basic_tuple.hpp
@@ -0,0 +1,299 @@
+/*!
+@file
+Defines `boost::hana::basic_tuple`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_BASIC_TUPLE_HPP
+#define BOOST_HANA_BASIC_TUPLE_HPP
+
+#include <boost/hana/fwd/basic_tuple.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/decay.hpp>
+#include <boost/hana/detail/intrinsics.hpp>
+#include <boost/hana/fwd/at.hpp>
+#include <boost/hana/fwd/bool.hpp>
+#include <boost/hana/fwd/concept/sequence.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+#include <boost/hana/fwd/core/tag_of.hpp>
+#include <boost/hana/fwd/drop_front.hpp>
+#include <boost/hana/fwd/is_empty.hpp>
+#include <boost/hana/fwd/transform.hpp>
+#include <boost/hana/fwd/unpack.hpp>
+
+#if 0 //! @todo Until we strip down headers, this includes too much
+#include <boost/hana/fwd/integral_constant.hpp>
+#include <boost/hana/fwd/length.hpp>
+#endif
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace detail {
+ //////////////////////////////////////////////////////////////////////
+ // elt<n, Xn>
+ //
+ // `elt` stands for `tuple_element`; the name is compressed to reduce
+ // symbol lengths.
+ //
+ // Wrapper holding the actual elements of a tuple. It takes care of
+ // optimizing the storage for empty types.
+ //
+ // When available, we use compiler intrinsics to reduce the number
+ // of instantiations.
+ //////////////////////////////////////////////////////////////////////
+ template <std::size_t n, typename Xn, bool =
+ BOOST_HANA_TT_IS_EMPTY(Xn) && !BOOST_HANA_TT_IS_FINAL(Xn)
+ >
+ struct elt;
+
+ // Specialize storage for empty types
+ template <std::size_t n, typename Xn>
+ struct elt<n, Xn, true> : Xn {
+ constexpr elt() = default;
+
+ template <typename Yn>
+ explicit constexpr elt(Yn&& yn)
+ : Xn(static_cast<Yn&&>(yn))
+ { }
+ };
+
+ // Specialize storage for non-empty types
+ template <std::size_t n, typename Xn>
+ struct elt<n, Xn, false> {
+ constexpr elt() = default;
+
+ template <typename Yn>
+ explicit constexpr elt(Yn&& yn)
+ : data_(static_cast<Yn&&>(yn))
+ { }
+
+ Xn data_;
+ };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // get_impl
+ //////////////////////////////////////////////////////////////////////////
+ template <std::size_t n, typename Xn>
+ constexpr Xn const& get_impl(detail::elt<n, Xn, true> const& xn)
+ { return xn; }
+
+ template <std::size_t n, typename Xn>
+ constexpr Xn& get_impl(detail::elt<n, Xn, true>& xn)
+ { return xn; }
+
+ template <std::size_t n, typename Xn>
+ constexpr Xn&& get_impl(detail::elt<n, Xn, true>&& xn)
+ { return static_cast<Xn&&>(xn); }
+
+
+ template <std::size_t n, typename Xn>
+ constexpr Xn const& get_impl(detail::elt<n, Xn, false> const& xn)
+ { return xn.data_; }
+
+ template <std::size_t n, typename Xn>
+ constexpr Xn& get_impl(detail::elt<n, Xn, false>& xn)
+ { return xn.data_; }
+
+ template <std::size_t n, typename Xn>
+ constexpr Xn&& get_impl(detail::elt<n, Xn, false>&& xn)
+ { return static_cast<Xn&&>(xn.data_); }
+
+ namespace detail {
+ //////////////////////////////////////////////////////////////////////
+ // basic_tuple_impl<n, Xn>
+ //////////////////////////////////////////////////////////////////////
+ struct from_other { };
+
+ template <typename Indices, typename ...Xn>
+ struct basic_tuple_impl;
+
+ template <std::size_t ...n, typename ...Xn>
+ struct basic_tuple_impl<std::index_sequence<n...>, Xn...>
+ : detail::elt<n, Xn>...
+ {
+ static constexpr std::size_t size_ = sizeof...(Xn);
+
+ constexpr basic_tuple_impl() = default;
+
+ template <typename Other>
+ explicit constexpr basic_tuple_impl(detail::from_other, Other&& other)
+ : detail::elt<n, Xn>(get_impl<n>(static_cast<Other&&>(other)))...
+ { }
+
+ template <typename ...Yn>
+ explicit constexpr basic_tuple_impl(Yn&& ...yn)
+ : detail::elt<n, Xn>(static_cast<Yn&&>(yn))...
+ { }
+ };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // basic_tuple
+ //////////////////////////////////////////////////////////////////////////
+ //! @cond
+ template <typename ...Xn>
+ struct basic_tuple final
+ : detail::basic_tuple_impl<std::make_index_sequence<sizeof...(Xn)>, Xn...>
+ {
+ using Base = detail::basic_tuple_impl<std::make_index_sequence<sizeof...(Xn)>, Xn...>;
+
+ constexpr basic_tuple() = default;
+
+ // copy constructor
+ template <typename Other, typename = typename std::enable_if<
+ std::is_same<typename std::decay<Other>::type, basic_tuple>::value
+ >::type>
+ constexpr basic_tuple(Other&& other)
+ : Base(detail::from_other{}, static_cast<Other&&>(other))
+ { }
+
+ template <typename ...Yn>
+ explicit constexpr basic_tuple(Yn&& ...yn)
+ : Base(static_cast<Yn&&>(yn)...)
+ { }
+ };
+ //! @endcond
+
+ template <typename ...Xn>
+ struct tag_of<basic_tuple<Xn...>> {
+ using type = basic_tuple_tag;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Foldable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct unpack_impl<basic_tuple_tag> {
+ template <std::size_t ...i, typename ...Xn, typename F>
+ static constexpr decltype(auto)
+ apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...> const& xs, F&& f) {
+ return static_cast<F&&>(f)(
+ get_impl<i>(static_cast<detail::elt<i, Xn> const&>(xs))...
+ );
+ }
+
+ template <std::size_t ...i, typename ...Xn, typename F>
+ static constexpr decltype(auto)
+ apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>& xs, F&& f) {
+ return static_cast<F&&>(f)(
+ get_impl<i>(static_cast<detail::elt<i, Xn>&>(xs))...
+ );
+ }
+
+ template <std::size_t ...i, typename ...Xn, typename F>
+ static constexpr decltype(auto)
+ apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>&& xs, F&& f) {
+ return static_cast<F&&>(f)(
+ get_impl<i>(static_cast<detail::elt<i, Xn>&&>(xs))...
+ );
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Functor
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct transform_impl<basic_tuple_tag> {
+ template <std::size_t ...i, typename ...Xn, typename F>
+ static constexpr auto
+ apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...> const& xs, F const& f) {
+ return hana::make_basic_tuple(
+ f(get_impl<i>(static_cast<detail::elt<i, Xn> const&>(xs)))...
+ );
+ }
+
+ template <std::size_t ...i, typename ...Xn, typename F>
+ static constexpr auto
+ apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>& xs, F const& f) {
+ return hana::make_basic_tuple(
+ f(get_impl<i>(static_cast<detail::elt<i, Xn>&>(xs)))...
+ );
+ }
+
+ template <std::size_t ...i, typename ...Xn, typename F>
+ static constexpr auto
+ apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>&& xs, F const& f) {
+ return hana::make_basic_tuple(
+ f(get_impl<i>(static_cast<detail::elt<i, Xn>&&>(xs)))...
+ );
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Iterable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct at_impl<basic_tuple_tag> {
+ template <typename Xs, typename N>
+ static constexpr decltype(auto) apply(Xs&& xs, N const&) {
+ constexpr std::size_t index = N::value;
+ return hana::get_impl<index>(static_cast<Xs&&>(xs));
+ }
+ };
+
+ template <>
+ struct drop_front_impl<basic_tuple_tag> {
+ template <std::size_t N, typename Xs, std::size_t ...i>
+ static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence<i...>) {
+ return hana::make_basic_tuple(hana::get_impl<i+N>(static_cast<Xs&&>(xs))...);
+ }
+
+ template <typename Xs, typename N>
+ 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
+ >{});
+ }
+ };
+
+ template <>
+ struct is_empty_impl<basic_tuple_tag> {
+ template <typename ...Xs>
+ static constexpr auto apply(basic_tuple<Xs...> const&)
+ { return hana::bool_c<sizeof...(Xs) == 0>; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Sequence
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct Sequence<basic_tuple_tag> {
+ static constexpr bool value = true;
+ };
+
+ template <>
+ struct make_impl<basic_tuple_tag> {
+ template <typename ...Xn>
+ static constexpr basic_tuple<typename detail::decay<Xn>::type...>
+ apply(Xn&& ...xn) {
+ return basic_tuple<typename detail::decay<Xn>::type...>{
+ static_cast<Xn&&>(xn)...
+ };
+ }
+ };
+
+#if 0
+ //////////////////////////////////////////////////////////////////////////
+ // length
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct length_impl<basic_tuple_tag> {
+ template <typename ...Xn>
+ static constexpr auto apply(basic_tuple<Xn...> const&) {
+ return hana::size_c<sizeof...(Xn)>;
+ }
+ };
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_BASIC_TUPLE_HPP
diff --git a/boost/hana/bool.hpp b/boost/hana/bool.hpp
new file mode 100644
index 0000000000..e69654dd85
--- /dev/null
+++ b/boost/hana/bool.hpp
@@ -0,0 +1,264 @@
+/*!
+@file
+Defines the `Logical` and `Comparable` models of `boost::hana::integral_constant`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_BOOL_HPP
+#define BOOST_HANA_BOOL_HPP
+
+#include <boost/hana/fwd/bool.hpp>
+
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/detail/operators/arithmetic.hpp>
+#include <boost/hana/detail/operators/comparable.hpp>
+#include <boost/hana/detail/operators/logical.hpp>
+#include <boost/hana/detail/operators/orderable.hpp>
+#include <boost/hana/eval.hpp>
+#include <boost/hana/fwd/core/tag_of.hpp>
+#include <boost/hana/fwd/eval_if.hpp>
+#include <boost/hana/fwd/if.hpp>
+#include <boost/hana/fwd/value.hpp>
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //////////////////////////////////////////////////////////////////////////
+ // integral_constant
+ //////////////////////////////////////////////////////////////////////////
+ //! @cond
+ namespace ic_detail {
+ template <typename T, T N, typename = std::make_integer_sequence<T, N>>
+ struct go;
+
+ template <typename T, T N, T ...i>
+ struct go<T, N, std::integer_sequence<T, i...>> {
+ using swallow = T[];
+
+ template <typename F>
+ static constexpr void with_index(F&& f)
+ { (void)swallow{T{}, ((void)f(integral_constant<T, i>{}), i)...}; }
+
+ template <typename F>
+ static constexpr void without_index(F&& f)
+ { (void)swallow{T{}, ((void)f(), i)...}; }
+ };
+
+ template <typename T, T v>
+ template <typename F>
+ constexpr void with_index_t<T, v>::operator()(F&& f) const
+ { go<T, ((void)sizeof(&f), v)>::with_index(static_cast<F&&>(f)); }
+
+ template <typename T, T v>
+ template <typename F>
+ constexpr void times_t<T, v>::operator()(F&& f) const
+ { go<T, ((void)sizeof(&f), v)>::without_index(static_cast<F&&>(f)); }
+
+ // avoid link-time error
+ template <typename T, T v>
+ constexpr with_index_t<T, v> times_t<T, v>::with_index;
+ }
+
+ // avoid link-time error
+ template <typename T, T v>
+ constexpr ic_detail::times_t<T, v> integral_constant<T, v>::times;
+
+ template <typename T, T v>
+ struct tag_of<integral_constant<T, v>> {
+ using type = integral_constant_tag<T>;
+ };
+ //! @endcond
+
+ //////////////////////////////////////////////////////////////////////////
+ // Operators
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <typename T>
+ struct comparable_operators<integral_constant_tag<T>> {
+ static constexpr bool value = true;
+ };
+ template <typename T>
+ struct orderable_operators<integral_constant_tag<T>> {
+ static constexpr bool value = true;
+ };
+ template <typename T>
+ struct arithmetic_operators<integral_constant_tag<T>> {
+ static constexpr bool value = true;
+ };
+ template <typename T>
+ struct logical_operators<integral_constant_tag<T>> {
+ static constexpr bool value = true;
+ };
+ }
+
+#define BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(op) \
+ template <typename U, U u, typename V, V v> \
+ constexpr integral_constant<decltype(u op v), (u op v)> \
+ operator op(integral_constant<U, u>, integral_constant<V, v>) \
+ { return {}; } \
+ /**/
+
+#define BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP(op) \
+ template <typename U, U u> \
+ constexpr integral_constant<decltype(op u), (op u)> \
+ operator op(integral_constant<U, u>) \
+ { return {}; } \
+ /**/
+
+ // Arithmetic
+ BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP(+)
+
+ // Bitwise
+ BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP(~)
+ BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(&)
+ BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(|)
+ BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(^)
+ BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(<<)
+ BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(>>)
+
+#undef BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP
+#undef BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // User-defined literal
+ //////////////////////////////////////////////////////////////////////////
+ namespace ic_detail {
+
+ constexpr int to_int(char c) {
+ int result = 0;
+
+ if (c >= 'A' && c <= 'F') {
+ result = static_cast<int>(c) - static_cast<int>('A') + 10;
+ }
+ else if (c >= 'a' && c <= 'f') {
+ result = static_cast<int>(c) - static_cast<int>('a') + 10;
+ }
+ else {
+ result = static_cast<int>(c) - static_cast<int>('0');
+ }
+
+ return result;
+ }
+
+ template<std::size_t N>
+ constexpr long long parse(const char (&arr)[N]) {
+ long long base = 10;
+ std::size_t offset = 0;
+
+ if (N > 2) {
+ bool starts_with_zero = arr[0] == '0';
+ bool is_hex = starts_with_zero && arr[1] == 'x';
+ bool is_binary = starts_with_zero && arr[1] == 'b';
+
+ if (is_hex) {
+ //0xDEADBEEF (hexadecimal)
+ base = 16;
+ offset = 2;
+ }
+ else if (is_binary) {
+ //0b101011101 (binary)
+ base = 2;
+ offset = 2;
+ }
+ else if (starts_with_zero) {
+ //012345 (octal)
+ base = 8;
+ offset = 1;
+ }
+ }
+
+ long long number = 0;
+ long long multiplier = 1;
+
+ for (std::size_t i = 0; i < N - offset; ++i) {
+ char c = arr[N - 1 - i];
+ number += to_int(c) * multiplier;
+ multiplier *= base;
+ }
+
+ return number;
+ }
+ }
+
+ namespace literals {
+ template <char ...c>
+ constexpr auto operator"" _c()
+ { return llong_c<ic_detail::parse<sizeof...(c)>({c...})>; }
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model of Constant/IntegralConstant
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T>
+ struct IntegralConstant<integral_constant_tag<T>> {
+ static constexpr bool value = true;
+ };
+
+ template <typename T, typename C>
+ struct to_impl<integral_constant_tag<T>, C, when<hana::IntegralConstant<C>::value>>
+ : embedding<is_embedded<typename C::value_type, T>::value>
+ {
+ template <typename N>
+ static constexpr auto apply(N const&)
+ { return integral_constant<T, N::value>{}; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Optimizations
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T>
+ struct eval_if_impl<integral_constant_tag<T>> {
+ template <typename Cond, typename Then, typename Else>
+ static constexpr decltype(auto)
+ apply(Cond const&, Then&& t, Else&& e) {
+ return eval_if_impl::apply(hana::bool_c<static_cast<bool>(Cond::value)>,
+ static_cast<Then&&>(t), static_cast<Else&&>(e));
+ }
+
+ template <typename Then, typename Else>
+ static constexpr decltype(auto)
+ apply(hana::true_ const&, Then&& t, Else&&)
+ { return hana::eval(static_cast<Then&&>(t)); }
+
+ template <typename Then, typename Else>
+ static constexpr decltype(auto)
+ apply(hana::false_ const&, Then&&, Else&& e)
+ { return hana::eval(static_cast<Else&&>(e)); }
+ };
+
+ template <typename T>
+ struct if_impl<integral_constant_tag<T>> {
+ template <typename Cond, typename Then, typename Else>
+ static constexpr decltype(auto)
+ apply(Cond const&, Then&& t, Else&& e) {
+ return if_impl::apply(hana::bool_c<static_cast<bool>(Cond::value)>,
+ static_cast<Then&&>(t), static_cast<Else&&>(e));
+ }
+
+ //! @todo We could return `Then` instead of `auto` to sometimes save
+ //! a copy, but that would break some code that would return a
+ //! reference to a `type` object. I think the code that would be
+ //! broken should be changed, but more thought needs to be given.
+ template <typename Then, typename Else>
+ static constexpr auto
+ apply(hana::true_ const&, Then&& t, Else&&)
+ { return static_cast<Then&&>(t); }
+
+ template <typename Then, typename Else>
+ static constexpr auto
+ apply(hana::false_ const&, Then&&, Else&& e)
+ { return static_cast<Else&&>(e); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_BOOL_HPP
diff --git a/boost/hana/cartesian_product.hpp b/boost/hana/cartesian_product.hpp
new file mode 100644
index 0000000000..2303aa1332
--- /dev/null
+++ b/boost/hana/cartesian_product.hpp
@@ -0,0 +1,113 @@
+/*!
+@file
+Defines `boost::hana::cartesian_product`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CARTESIAN_PRODUCT_HPP
+#define BOOST_HANA_CARTESIAN_PRODUCT_HPP
+
+#include <boost/hana/fwd/cartesian_product.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/detail/array.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/unpack.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs>
+ constexpr auto cartesian_product_t::operator()(Xs&& xs) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using CartesianProduct = BOOST_HANA_DISPATCH_IF(
+ cartesian_product_impl<S>,
+ hana::Sequence<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::cartesian_product(xs) requires 'xs' to be a Sequence");
+ #endif
+
+ return CartesianProduct::apply(static_cast<Xs&&>(xs));
+ }
+ //! @endcond
+
+ namespace detail {
+ template <std::size_t ...Lengths>
+ struct cartesian_product_indices {
+ static constexpr std::size_t total_length() {
+ std::size_t lengths[] = {Lengths...};
+ std::size_t r = 1;
+ for (std::size_t len: lengths)
+ r *= len;
+ return r;
+ }
+
+ static constexpr std::size_t length = total_length();
+
+ static constexpr auto indices_of(std::size_t i) {
+ constexpr std::size_t lengths[] = {Lengths...};
+ constexpr std::size_t n = sizeof...(Lengths);
+ detail::array<std::size_t, n> result{};
+ for (std::size_t j = n; j--;) {
+ result[j] = i % lengths[j];
+ i /= lengths[j];
+ }
+ return result;
+ }
+
+ template <typename S, std::size_t n, std::size_t ...k, typename ...Xs>
+ static constexpr auto
+ product_element(std::index_sequence<k...>, Xs&& ...xs) {
+ constexpr auto indices = indices_of(n);
+ return hana::make<S>(hana::at_c<indices[k]>(xs)...);
+ }
+
+ template <typename S, std::size_t ...n, typename ...Xs>
+ static constexpr auto
+ create_product(std::index_sequence<n...>, Xs&& ...xs) {
+ return hana::make<S>(product_element<S, n>(
+ std::make_index_sequence<sizeof...(Xs)>{}, xs...
+ )...);
+ }
+ };
+ }
+
+ // Credits: implementation adapted from http://github.com/alexk7/hel.
+ template <typename S, bool condition>
+ struct cartesian_product_impl<S, when<condition>> : default_ {
+ template <typename Xs>
+ static constexpr auto apply(Xs&& xs) {
+ return hana::unpack(static_cast<Xs&&>(xs), cartesian_product_impl{});
+ }
+
+ template <typename ...Xs>
+ constexpr auto operator()(Xs&& ...xs) const {
+ using indices = detail::cartesian_product_indices<
+ decltype(hana::length(xs))::value...
+ >;
+ return indices::template create_product<S>(
+ std::make_index_sequence<indices::length>{},
+ static_cast<Xs&&>(xs)...);
+ }
+
+ constexpr auto operator()() const {
+ return hana::make<S>();
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CARTESIAN_PRODUCT_HPP
diff --git a/boost/hana/chain.hpp b/boost/hana/chain.hpp
new file mode 100644
index 0000000000..da9de375f2
--- /dev/null
+++ b/boost/hana/chain.hpp
@@ -0,0 +1,50 @@
+/*!
+@file
+Defines `boost::hana::chain`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CHAIN_HPP
+#define BOOST_HANA_CHAIN_HPP
+
+#include <boost/hana/fwd/chain.hpp>
+
+#include <boost/hana/concept/monad.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/flatten.hpp>
+#include <boost/hana/transform.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename F>
+ constexpr decltype(auto) chain_t::operator()(Xs&& xs, F&& f) const {
+ using M = typename hana::tag_of<Xs>::type;
+ using Chain = BOOST_HANA_DISPATCH_IF(chain_impl<M>,
+ hana::Monad<M>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Monad<M>::value,
+ "hana::chain(xs, f) requires 'xs' to be a Monad");
+ #endif
+
+ return Chain::apply(static_cast<Xs&&>(xs), static_cast<F&&>(f));
+ }
+ //! @endcond
+
+ template <typename M, bool condition>
+ struct chain_impl<M, when<condition>> : default_ {
+ template <typename Xs, typename F>
+ static constexpr auto apply(Xs&& xs, F&& f) {
+ return hana::flatten(hana::transform(static_cast<Xs&&>(xs),
+ static_cast<F&&>(f)));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CHAIN_HPP
diff --git a/boost/hana/comparing.hpp b/boost/hana/comparing.hpp
new file mode 100644
index 0000000000..7b8bf28407
--- /dev/null
+++ b/boost/hana/comparing.hpp
@@ -0,0 +1,45 @@
+/*!
+@file
+Defines `boost::hana::comparing`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_COMPARING_HPP
+#define BOOST_HANA_COMPARING_HPP
+
+#include <boost/hana/fwd/comparing.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/equal.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace detail {
+ template <typename F>
+ struct equal_by {
+ F f;
+
+ template <typename X, typename Y>
+ constexpr auto operator()(X&& x, Y&& y) const&
+ { return hana::equal(f(static_cast<X&&>(x)), f(static_cast<Y&&>(y))); }
+
+ template <typename X, typename Y>
+ constexpr auto operator()(X&& x, Y&& y) &
+ { return hana::equal(f(static_cast<X&&>(x)), f(static_cast<Y&&>(y))); }
+ };
+ }
+
+ //! @cond
+ template <typename F>
+ constexpr auto comparing_t::operator()(F&& f) const {
+ return detail::equal_by<typename std::decay<F>::type>{static_cast<F&&>(f)};
+ }
+ //! @endcond
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_COMPARING_HPP
diff --git a/boost/hana/concat.hpp b/boost/hana/concat.hpp
new file mode 100644
index 0000000000..8f079992b5
--- /dev/null
+++ b/boost/hana/concat.hpp
@@ -0,0 +1,80 @@
+/*!
+@file
+Defines `boost::hana::concat`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCAT_HPP
+#define BOOST_HANA_CONCAT_HPP
+
+#include <boost/hana/fwd/concat.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/monad_plus.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/length.hpp>
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Ys>
+ constexpr auto concat_t::operator()(Xs&& xs, Ys&& ys) const {
+ using M = typename hana::tag_of<Xs>::type;
+ using Concat = BOOST_HANA_DISPATCH_IF(concat_impl<M>,
+ hana::MonadPlus<M>::value &&
+ std::is_same<typename hana::tag_of<Ys>::type, M>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(std::is_same<typename hana::tag_of<Ys>::type, M>::value,
+ "hana::concat(xs, ys) requires 'xs' and 'ys' to have the same tag");
+
+ static_assert(hana::MonadPlus<M>::value,
+ "hana::concat(xs, ys) requires 'xs' and 'ys' to be MonadPlus");
+ #endif
+
+ return Concat::apply(static_cast<Xs&&>(xs), static_cast<Ys&&>(ys));
+ }
+ //! @endcond
+
+ template <typename M, bool condition>
+ struct concat_impl<M, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+
+ template <typename S>
+ struct concat_impl<S, when<Sequence<S>::value>> {
+ template <typename Xs, typename Ys, std::size_t ...xi, std::size_t ...yi>
+ static constexpr auto
+ concat_helper(Xs&& xs, Ys&& ys, std::index_sequence<xi...>,
+ std::index_sequence<yi...>)
+ {
+ return hana::make<S>(
+ hana::at_c<xi>(static_cast<Xs&&>(xs))...,
+ hana::at_c<yi>(static_cast<Ys&&>(ys))...
+ );
+ }
+
+ template <typename Xs, typename Ys>
+ static constexpr auto apply(Xs&& xs, Ys&& ys) {
+ constexpr std::size_t xi = decltype(hana::length(xs))::value;
+ constexpr std::size_t yi = decltype(hana::length(ys))::value;
+ return concat_helper(static_cast<Xs&&>(xs), static_cast<Ys&&>(ys),
+ std::make_index_sequence<xi>{},
+ std::make_index_sequence<yi>{});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCAT_HPP
diff --git a/boost/hana/concept.hpp b/boost/hana/concept.hpp
new file mode 100644
index 0000000000..c8decf9925
--- /dev/null
+++ b/boost/hana/concept.hpp
@@ -0,0 +1,35 @@
+/*!
+@file
+Master header for the `boost/hana/concept/` subdirectory.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_HPP
+#define BOOST_HANA_CONCEPT_HPP
+
+#include <boost/hana/concept/applicative.hpp>
+#include <boost/hana/concept/comonad.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/euclidean_ring.hpp>
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/concept/functor.hpp>
+#include <boost/hana/concept/group.hpp>
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/concept/iterable.hpp>
+#include <boost/hana/concept/logical.hpp>
+#include <boost/hana/concept/metafunction.hpp>
+#include <boost/hana/concept/monad.hpp>
+#include <boost/hana/concept/monad_plus.hpp>
+#include <boost/hana/concept/monoid.hpp>
+#include <boost/hana/concept/orderable.hpp>
+#include <boost/hana/concept/product.hpp>
+#include <boost/hana/concept/ring.hpp>
+#include <boost/hana/concept/searchable.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/concept/struct.hpp>
+
+#endif // !BOOST_HANA_CONCEPT_HPP
diff --git a/boost/hana/concept/applicative.hpp b/boost/hana/concept/applicative.hpp
new file mode 100644
index 0000000000..28c3af4242
--- /dev/null
+++ b/boost/hana/concept/applicative.hpp
@@ -0,0 +1,31 @@
+/*!
+@file
+Defines `boost::hana::Applicative`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_APPLICATIVE_HPP
+#define BOOST_HANA_CONCEPT_APPLICATIVE_HPP
+
+#include <boost/hana/fwd/concept/applicative.hpp>
+
+#include <boost/hana/ap.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/lift.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename A>
+ struct Applicative {
+ using Tag = typename tag_of<A>::type;
+ static constexpr bool value = !is_default<ap_impl<Tag>>::value &&
+ !is_default<lift_impl<Tag>>::value;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_APPLICATIVE_HPP
diff --git a/boost/hana/concept/comonad.hpp b/boost/hana/concept/comonad.hpp
new file mode 100644
index 0000000000..4aff1ab648
--- /dev/null
+++ b/boost/hana/concept/comonad.hpp
@@ -0,0 +1,33 @@
+/*!
+@file
+Defines `boost::hana::Comonad`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_COMONAD_HPP
+#define BOOST_HANA_CONCEPT_COMONAD_HPP
+
+#include <boost/hana/fwd/concept/comonad.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/duplicate.hpp>
+#include <boost/hana/extend.hpp>
+#include <boost/hana/extract.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename W>
+ struct Comonad {
+ using Tag = typename tag_of<W>::type;
+ static constexpr bool value = !is_default<extract_impl<Tag>>::value &&
+ (!is_default<duplicate_impl<Tag>>::value ||
+ !is_default<extend_impl<Tag>>::value);
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_COMONAD_HPP
diff --git a/boost/hana/concept/comparable.hpp b/boost/hana/concept/comparable.hpp
new file mode 100644
index 0000000000..a38e5c6747
--- /dev/null
+++ b/boost/hana/concept/comparable.hpp
@@ -0,0 +1,29 @@
+/*!
+@file
+Defines `boost::hana::Comparable`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_COMPARABLE_HPP
+#define BOOST_HANA_CONCEPT_COMPARABLE_HPP
+
+#include <boost/hana/fwd/concept/comparable.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/equal.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename T>
+ struct Comparable {
+ using Tag = typename tag_of<T>::type;
+ static constexpr bool value = !is_default<equal_impl<Tag, Tag>>::value;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_COMPARABLE_HPP
diff --git a/boost/hana/concept/constant.hpp b/boost/hana/concept/constant.hpp
new file mode 100644
index 0000000000..1c85a20739
--- /dev/null
+++ b/boost/hana/concept/constant.hpp
@@ -0,0 +1,29 @@
+/*!
+@file
+Defines `boost::hana::Constant`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_CONSTANT_HPP
+#define BOOST_HANA_CONCEPT_CONSTANT_HPP
+
+#include <boost/hana/fwd/concept/constant.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/value.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename C>
+ struct Constant {
+ using Tag = typename tag_of<C>::type;
+ static constexpr bool value = !is_default<value_impl<Tag>>::value;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_CONSTANT_HPP
diff --git a/boost/hana/concept/euclidean_ring.hpp b/boost/hana/concept/euclidean_ring.hpp
new file mode 100644
index 0000000000..19ee1abcd5
--- /dev/null
+++ b/boost/hana/concept/euclidean_ring.hpp
@@ -0,0 +1,31 @@
+/*!
+@file
+Defines `boost::hana::EuclideanRing`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_EUCLIDEAN_RING_HPP
+#define BOOST_HANA_CONCEPT_EUCLIDEAN_RING_HPP
+
+#include <boost/hana/fwd/concept/euclidean_ring.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/div.hpp>
+#include <boost/hana/mod.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename R>
+ struct EuclideanRing {
+ using Tag = typename tag_of<R>::type;
+ static constexpr bool value = !is_default<mod_impl<Tag, Tag>>::value &&
+ !is_default<div_impl<Tag, Tag>>::value;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_EUCLIDEAN_RING_HPP
diff --git a/boost/hana/concept/foldable.hpp b/boost/hana/concept/foldable.hpp
new file mode 100644
index 0000000000..7737a74ce0
--- /dev/null
+++ b/boost/hana/concept/foldable.hpp
@@ -0,0 +1,31 @@
+/*!
+@file
+Defines `boost::hana::Foldable`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_FOLDABLE_HPP
+#define BOOST_HANA_CONCEPT_FOLDABLE_HPP
+
+#include <boost/hana/fwd/concept/foldable.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/fold_left.hpp>
+#include <boost/hana/unpack.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename T>
+ struct Foldable {
+ using Tag = typename tag_of<T>::type;
+ static constexpr bool value = !is_default<fold_left_impl<Tag>>::value ||
+ !is_default<unpack_impl<Tag>>::value;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_FOLDABLE_HPP
diff --git a/boost/hana/concept/functor.hpp b/boost/hana/concept/functor.hpp
new file mode 100644
index 0000000000..308abae56f
--- /dev/null
+++ b/boost/hana/concept/functor.hpp
@@ -0,0 +1,31 @@
+/*!
+@file
+Defines `boost::hana::Functor`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_FUNCTOR_HPP
+#define BOOST_HANA_CONCEPT_FUNCTOR_HPP
+
+#include <boost/hana/fwd/concept/functor.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/adjust_if.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/transform.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename F>
+ struct Functor {
+ using Tag = typename tag_of<F>::type;
+ static constexpr bool value = !is_default<transform_impl<Tag>>::value ||
+ !is_default<adjust_if_impl<Tag>>::value;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_FUNCTOR_HPP
diff --git a/boost/hana/concept/group.hpp b/boost/hana/concept/group.hpp
new file mode 100644
index 0000000000..025537110a
--- /dev/null
+++ b/boost/hana/concept/group.hpp
@@ -0,0 +1,31 @@
+/*!
+@file
+Defines `boost::hana::Group`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_GROUP_HPP
+#define BOOST_HANA_CONCEPT_GROUP_HPP
+
+#include <boost/hana/fwd/concept/group.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/minus.hpp>
+#include <boost/hana/negate.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename G>
+ struct Group {
+ using Tag = typename tag_of<G>::type;
+ static constexpr bool value = !is_default<negate_impl<Tag>>::value ||
+ !is_default<minus_impl<Tag, Tag>>::value;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_GROUP_HPP
diff --git a/boost/hana/concept/hashable.hpp b/boost/hana/concept/hashable.hpp
new file mode 100644
index 0000000000..9fc282fb71
--- /dev/null
+++ b/boost/hana/concept/hashable.hpp
@@ -0,0 +1,30 @@
+/*!
+@file
+Defines `boost::hana::Hashable`.
+
+@copyright Louis Dionne 2016
+@copyright Jason Rice 2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_HASHABLE_HPP
+#define BOOST_HANA_CONCEPT_HASHABLE_HPP
+
+#include <boost/hana/fwd/concept/hashable.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/hash.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename T>
+ struct Hashable {
+ using Tag = typename tag_of<T>::type;
+ static constexpr bool value = !is_default<hash_impl<Tag>>::value;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_HASHABLE_HPP
diff --git a/boost/hana/concept/integral_constant.hpp b/boost/hana/concept/integral_constant.hpp
new file mode 100644
index 0000000000..6e36551001
--- /dev/null
+++ b/boost/hana/concept/integral_constant.hpp
@@ -0,0 +1,40 @@
+/*!
+@file
+Defines `boost::hana::IntegralConstant`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_INTEGRAL_CONSTANT_HPP
+#define BOOST_HANA_CONCEPT_INTEGRAL_CONSTANT_HPP
+
+#include <boost/hana/fwd/concept/integral_constant.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/tag_of.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace detail {
+ template <typename C, typename Tag = typename tag_of<C>::type>
+ struct integral_constant_dispatch {
+ static constexpr bool value = hana::IntegralConstant<Tag>::value;
+ };
+
+ template <typename C>
+ struct integral_constant_dispatch<C, C> {
+ static constexpr bool value = false;
+ };
+ }
+
+ //! @cond
+ template <typename C>
+ struct IntegralConstant
+ : detail::integral_constant_dispatch<C>
+ { };
+ //! @endcond
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_INTEGRAL_CONSTANT_HPP
diff --git a/boost/hana/concept/iterable.hpp b/boost/hana/concept/iterable.hpp
new file mode 100644
index 0000000000..78c1914077
--- /dev/null
+++ b/boost/hana/concept/iterable.hpp
@@ -0,0 +1,33 @@
+/*!
+@file
+Defines `boost::hana::Iterable`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_ITERABLE_HPP
+#define BOOST_HANA_CONCEPT_ITERABLE_HPP
+
+#include <boost/hana/fwd/concept/iterable.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/at.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/drop_front.hpp>
+#include <boost/hana/is_empty.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename It>
+ struct Iterable {
+ using Tag = typename tag_of<It>::type;
+ static constexpr bool value = !is_default<at_impl<Tag>>::value &&
+ !is_default<drop_front_impl<Tag>>::value &&
+ !is_default<is_empty_impl<Tag>>::value;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_ITERABLE_HPP
diff --git a/boost/hana/concept/logical.hpp b/boost/hana/concept/logical.hpp
new file mode 100644
index 0000000000..74c0fb3a51
--- /dev/null
+++ b/boost/hana/concept/logical.hpp
@@ -0,0 +1,33 @@
+/*!
+@file
+Defines `boost::hana::Logical`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_LOGICAL_HPP
+#define BOOST_HANA_CONCEPT_LOGICAL_HPP
+
+#include <boost/hana/fwd/concept/logical.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/eval_if.hpp>
+#include <boost/hana/not.hpp>
+#include <boost/hana/while.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename L>
+ struct Logical {
+ using Tag = typename tag_of<L>::type;
+ static constexpr bool value = !is_default<eval_if_impl<Tag>>::value &&
+ !is_default<not_impl<Tag>>::value &&
+ !is_default<while_impl<Tag>>::value;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_LOGICAL_HPP
diff --git a/boost/hana/concept/metafunction.hpp b/boost/hana/concept/metafunction.hpp
new file mode 100644
index 0000000000..ed6d53ad87
--- /dev/null
+++ b/boost/hana/concept/metafunction.hpp
@@ -0,0 +1,38 @@
+/*!
+@file
+Defines `boost::hana::Metafunction`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_METAFUNCTION_HPP
+#define BOOST_HANA_CONCEPT_METAFUNCTION_HPP
+
+#include <boost/hana/fwd/concept/metafunction.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/tag_of.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace detail {
+ template <typename F, typename Tag = typename tag_of<F>::type>
+ struct metafunction_dispatch {
+ static constexpr bool value = Metafunction<Tag>::value;
+ };
+
+ template <typename F>
+ struct metafunction_dispatch<F, F> {
+ static constexpr bool value = false;
+ };
+ }
+
+ template <typename F>
+ struct Metafunction
+ : detail::metafunction_dispatch<F>
+ { };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_METAFUNCTION_HPP
diff --git a/boost/hana/concept/monad.hpp b/boost/hana/concept/monad.hpp
new file mode 100644
index 0000000000..ba1c33021f
--- /dev/null
+++ b/boost/hana/concept/monad.hpp
@@ -0,0 +1,31 @@
+/*!
+@file
+Defines `boost::hana::Monad`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_MONAD_HPP
+#define BOOST_HANA_CONCEPT_MONAD_HPP
+
+#include <boost/hana/fwd/concept/monad.hpp>
+
+#include <boost/hana/chain.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/flatten.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename M>
+ struct Monad {
+ using Tag = typename tag_of<M>::type;
+ static constexpr bool value = !is_default<flatten_impl<Tag>>::value ||
+ !is_default<chain_impl<Tag>>::value;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_MONAD_HPP
diff --git a/boost/hana/concept/monad_plus.hpp b/boost/hana/concept/monad_plus.hpp
new file mode 100644
index 0000000000..22c67ca255
--- /dev/null
+++ b/boost/hana/concept/monad_plus.hpp
@@ -0,0 +1,31 @@
+/*!
+@file
+Defines `boost::hana::MonadPlus`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_MONAD_PLUS_HPP
+#define BOOST_HANA_CONCEPT_MONAD_PLUS_HPP
+
+#include <boost/hana/fwd/concept/monad_plus.hpp>
+
+#include <boost/hana/concat.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/empty.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename M>
+ struct MonadPlus {
+ using Tag = typename tag_of<M>::type;
+ static constexpr bool value = !is_default<concat_impl<Tag>>::value &&
+ !is_default<empty_impl<Tag>>::value;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_MONAD_PLUS_HPP
diff --git a/boost/hana/concept/monoid.hpp b/boost/hana/concept/monoid.hpp
new file mode 100644
index 0000000000..df84bb23e6
--- /dev/null
+++ b/boost/hana/concept/monoid.hpp
@@ -0,0 +1,31 @@
+/*!
+@file
+Defines `boost::hana::Monoid`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_MONOID_HPP
+#define BOOST_HANA_CONCEPT_MONOID_HPP
+
+#include <boost/hana/fwd/concept/monoid.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/plus.hpp>
+#include <boost/hana/zero.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename M>
+ struct Monoid {
+ using Tag = typename tag_of<M>::type;
+ static constexpr bool value = !is_default<zero_impl<Tag>>::value &&
+ !is_default<plus_impl<Tag, Tag>>::value;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_MONOID_HPP
diff --git a/boost/hana/concept/orderable.hpp b/boost/hana/concept/orderable.hpp
new file mode 100644
index 0000000000..5461332cd4
--- /dev/null
+++ b/boost/hana/concept/orderable.hpp
@@ -0,0 +1,29 @@
+/*!
+@file
+Defines `boost::hana::Orderable`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_ORDERABLE_HPP
+#define BOOST_HANA_CONCEPT_ORDERABLE_HPP
+
+#include <boost/hana/fwd/concept/orderable.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/less.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename Ord>
+ struct Orderable {
+ using Tag = typename tag_of<Ord>::type;
+ static constexpr bool value = !is_default<less_impl<Tag, Tag>>::value;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_ORDERABLE_HPP
diff --git a/boost/hana/concept/product.hpp b/boost/hana/concept/product.hpp
new file mode 100644
index 0000000000..1a77777b29
--- /dev/null
+++ b/boost/hana/concept/product.hpp
@@ -0,0 +1,31 @@
+/*!
+@file
+Defines `boost::hana::Product`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_PRODUCT_HPP
+#define BOOST_HANA_CONCEPT_PRODUCT_HPP
+
+#include <boost/hana/fwd/concept/product.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/first.hpp>
+#include <boost/hana/second.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename P>
+ struct Product {
+ using Tag = typename tag_of<P>::type;
+ static constexpr bool value = !is_default<first_impl<Tag>>::value &&
+ !is_default<second_impl<Tag>>::value;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_PRODUCT_HPP
diff --git a/boost/hana/concept/ring.hpp b/boost/hana/concept/ring.hpp
new file mode 100644
index 0000000000..3cc309e68a
--- /dev/null
+++ b/boost/hana/concept/ring.hpp
@@ -0,0 +1,31 @@
+/*!
+@file
+Defines `boost::hana::Ring`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_RING_HPP
+#define BOOST_HANA_CONCEPT_RING_HPP
+
+#include <boost/hana/fwd/concept/ring.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/mult.hpp>
+#include <boost/hana/one.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename R>
+ struct Ring {
+ using Tag = typename tag_of<R>::type;
+ static constexpr bool value = !is_default<one_impl<Tag>>::value &&
+ !is_default<mult_impl<Tag, Tag>>::value;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_RING_HPP
diff --git a/boost/hana/concept/searchable.hpp b/boost/hana/concept/searchable.hpp
new file mode 100644
index 0000000000..923b57dfcf
--- /dev/null
+++ b/boost/hana/concept/searchable.hpp
@@ -0,0 +1,31 @@
+/*!
+@file
+Defines `boost::hana::Searchable`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_SEARCHABLE_HPP
+#define BOOST_HANA_CONCEPT_SEARCHABLE_HPP
+
+#include <boost/hana/fwd/concept/searchable.hpp>
+
+#include <boost/hana/any_of.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/find_if.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename S>
+ struct Searchable {
+ using Tag = typename tag_of<S>::type;
+ static constexpr bool value = !is_default<any_of_impl<Tag>>::value &&
+ !is_default<find_if_impl<Tag>>::value;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_SEARCHABLE_HPP
diff --git a/boost/hana/concept/sequence.hpp b/boost/hana/concept/sequence.hpp
new file mode 100644
index 0000000000..b2c6cda50c
--- /dev/null
+++ b/boost/hana/concept/sequence.hpp
@@ -0,0 +1,41 @@
+/*!
+@file
+Defines `boost::hana::Sequence`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_SEQUENCE_HPP
+#define BOOST_HANA_CONCEPT_SEQUENCE_HPP
+
+#include <boost/hana/fwd/concept/sequence.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace detail {
+ template <typename S, typename Tag = typename hana::tag_of<S>::type>
+ struct sequence_dispatch {
+ static constexpr bool value = hana::Sequence<Tag>::value;
+ };
+
+ template <typename S>
+ struct sequence_dispatch<S, S> {
+ static constexpr bool value = false;
+ };
+ }
+
+ //! @cond
+ template <typename S, bool condition>
+ struct Sequence<S, when<condition>>
+ : detail::sequence_dispatch<S>
+ { };
+ //! @endcond
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_SEQUENCE_HPP
diff --git a/boost/hana/concept/struct.hpp b/boost/hana/concept/struct.hpp
new file mode 100644
index 0000000000..709d0cccea
--- /dev/null
+++ b/boost/hana/concept/struct.hpp
@@ -0,0 +1,29 @@
+/*!
+@file
+Defines `boost::hana::Struct`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONCEPT_STRUCT_HPP
+#define BOOST_HANA_CONCEPT_STRUCT_HPP
+
+#include <boost/hana/fwd/concept/struct.hpp>
+
+#include <boost/hana/accessors.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename S>
+ struct Struct {
+ using Tag = typename tag_of<S>::type;
+ static constexpr bool value = !is_default<accessors_impl<Tag>>::value;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONCEPT_STRUCT_HPP
diff --git a/boost/hana/config.hpp b/boost/hana/config.hpp
new file mode 100644
index 0000000000..fd1939c09e
--- /dev/null
+++ b/boost/hana/config.hpp
@@ -0,0 +1,215 @@
+/*!
+@file
+Defines configuration macros used throughout the library.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONFIG_HPP
+#define BOOST_HANA_CONFIG_HPP
+
+#include <boost/hana/version.hpp>
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Detect the compiler
+//////////////////////////////////////////////////////////////////////////////
+
+#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.")
+
+#elif defined(__clang__) && defined(_MSC_VER) // Clang-cl (Clang for Windows)
+
+# define BOOST_HANA_CONFIG_CLANG BOOST_HANA_CONFIG_VERSION( \
+ __clang_major__, __clang_minor__, __clang_patchlevel__)
+
+# if BOOST_HANA_CONFIG_CLANG < BOOST_HANA_CONFIG_VERSION(3, 5, 0)
+# warning "Versions of Clang prior to 3.5.0 are not supported by Hana."
+# endif
+
+# if _MSC_VER < 1900
+# warning "Clang-cl is only supported with the -fms-compatibility-version parameter set to 19 and above."
+# endif
+
+#elif defined(__clang__) && defined(__apple_build_version__) // Apple's Clang
+
+# 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."
+# endif
+
+#elif defined(__clang__) // genuine Clang
+
+# define BOOST_HANA_CONFIG_CLANG BOOST_HANA_CONFIG_VERSION( \
+ __clang_major__, __clang_minor__, __clang_patchlevel__)
+
+# if BOOST_HANA_CONFIG_CLANG < BOOST_HANA_CONFIG_VERSION(3, 5, 0)
+# warning "Versions of Clang prior to 3.5.0 are not supported by Hana."
+# endif
+
+#elif defined(__GNUC__) // GCC
+
+# define BOOST_HANA_CONFIG_GCC BOOST_HANA_CONFIG_VERSION( \
+ __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
+
+# if BOOST_HANA_CONFIG_GCC < BOOST_HANA_CONFIG_VERSION(6, 0, 0)
+# warning "Versions of GCC prior to 6.0.0 are not supported by Hana."
+# endif
+
+#else
+
+# warning "Your compiler is not officially supported by Hana or it was not detected properly."
+
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// Check the compiler for general C++14 capabilities
+//////////////////////////////////////////////////////////////////////////////
+#if (__cplusplus < 201400)
+# warning "Your compiler doesn't provide C++14 or higher capabilities. Try adding the compiler flag '-std=c++14' or '-std=c++1y'."
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// Detect the standard library
+//////////////////////////////////////////////////////////////////////////////
+
+// We include this header, which normally defines the proper detection macros.
+// At least, libc++ and libstdc++ do.
+#include <cstddef>
+
+#if defined(_LIBCPP_VERSION)
+
+# define BOOST_HANA_CONFIG_LIBCPP BOOST_HANA_CONFIG_VERSION( \
+ ((_LIBCPP_VERSION) / 1000) % 10, 0, (_LIBCPP_VERSION) % 1000)
+
+# if BOOST_HANA_CONFIG_LIBCPP < BOOST_HANA_CONFIG_VERSION(1, 0, 101)
+# warning "Versions of libc++ prior to the one shipped with Clang 3.5.0 are not supported by Hana."
+# endif
+
+#elif defined(__GLIBCXX__)
+
+// We do not define a macro to keep track of libstdc++'s version, because
+// we have no scalable way of associating a value of __GLIBCXX__ to the
+// corresponding GCC release. Instead, we just check that the release date
+// of the libstdc++ in use is recent enough, which should indicate that it
+// was released with a GCC >= 5.1, which in turn indicates good enough C++14
+// support.
+# if __GLIBCXX__ < 20150422 // --> the libstdc++ shipped with GCC 5.1.0
+# warning "Versions of libstdc++ prior to the one shipped with GCC 5.1.0 are not supported by Hana for lack of full C++14 support."
+# endif
+
+# define BOOST_HANA_CONFIG_LIBSTDCXX
+
+#elif defined(_MSC_VER)
+
+# define BOOST_HANA_CONFIG_LIBMSVCCXX
+
+#else
+
+# warning "Your standard library is not officially supported by Hana or it was not detected properly."
+
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Caveats and other compiler-dependent options
+//////////////////////////////////////////////////////////////////////////////
+
+// BOOST_HANA_CONFIG_HAS_CONSTEXPR_LAMBDA enables some constructs requiring
+// `constexpr` lambdas, which are not in the language (yet).
+// Currently always disabled.
+//
+// BOOST_HANA_CONSTEXPR_LAMBDA expands to `constexpr` if constexpr lambdas
+// are supported and to nothing otherwise.
+#if 0
+# define BOOST_HANA_CONFIG_HAS_CONSTEXPR_LAMBDA
+# define BOOST_HANA_CONSTEXPR_LAMBDA constexpr
+#else
+# define BOOST_HANA_CONSTEXPR_LAMBDA /* nothing */
+#endif
+
+// The std::tuple adapter is broken on libc++ prior to the one shipped
+// with Clang 3.7.0.
+#if defined(BOOST_HANA_CONFIG_LIBCPP) && \
+ BOOST_HANA_CONFIG_LIBCPP < BOOST_HANA_CONFIG_VERSION(1, 0, 101)
+# define BOOST_HANA_CONFIG_HAS_NO_STD_TUPLE_ADAPTER
+#endif
+
+// There's a bug in std::tuple_cat in libc++ right now.
+// See http://llvm.org/bugs/show_bug.cgi?id=22806.
+#if defined(BOOST_HANA_CONFIG_LIBCPP)
+# define BOOST_HANA_CONFIG_LIBCPP_HAS_BUG_22806
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// Namespace macros
+//////////////////////////////////////////////////////////////////////////////
+#define BOOST_HANA_NAMESPACE_BEGIN namespace boost { namespace hana {
+
+#define BOOST_HANA_NAMESPACE_END }}
+
+//////////////////////////////////////////////////////////////////////////////
+// Library features and options that can be tweaked by users
+//////////////////////////////////////////////////////////////////////////////
+
+#if defined(BOOST_HANA_DOXYGEN_INVOKED) || \
+ (defined(NDEBUG) && !defined(BOOST_HANA_CONFIG_DISABLE_ASSERTIONS))
+ //! @ingroup group-config
+ //! Disables the `BOOST_HANA_*_ASSERT` macro & friends.
+ //!
+ //! When this macro is defined, the `BOOST_HANA_*_ASSERT` macro & friends
+ //! are disabled, i.e. they expand to nothing.
+ //!
+ //! This macro is defined automatically when `NDEBUG` is defined. It can
+ //! also be defined by users before including this header or defined on
+ //! the command line.
+# define BOOST_HANA_CONFIG_DISABLE_ASSERTIONS
+#endif
+
+#if defined(BOOST_HANA_DOXYGEN_INVOKED)
+ //! @ingroup group-config
+ //! Disables concept checks in interface methods.
+ //!
+ //! When this macro is not defined (the default), tag-dispatched methods
+ //! will make sure the arguments they are passed are models of the proper
+ //! concept(s). This can be very helpful in catching programming errors,
+ //! but it is also slightly less compile-time efficient. You should
+ //! probably always leave the checks enabled (and hence never define this
+ //! macro), except perhaps in translation units that are compiled very
+ //! often but whose code using Hana is modified very rarely.
+# define BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+#endif
+
+#if defined(BOOST_HANA_DOXYGEN_INVOKED)
+ //! @ingroup group-config
+ //! Enables usage of the "string literal operator template" GNU extension.
+ //!
+ //! That operator is not part of the language yet, but it is supported by
+ //! both Clang and GCC. This operator allows Hana to provide the nice `_s`
+ //! user-defined literal for creating compile-time strings.
+ //!
+ //! When this macro is not defined, the GNU extension will be not used
+ //! by Hana. Because this is a non-standard extension, the macro is not
+ //! defined by default.
+# define BOOST_HANA_CONFIG_ENABLE_STRING_UDL
+#endif
+
+#if defined(BOOST_HANA_DOXYGEN_INVOKED)
+ //! @ingroup group-config
+ //! Enables additional assertions and sanity checks to be done by Hana.
+ //!
+ //! When this macro is defined (it is __not defined__ by default),
+ //! additional sanity checks may be done by Hana. These checks may
+ //! be costly to perform, either in terms of compilation time or in
+ //! terms of execution time. These checks may help debugging an
+ //! application during its initial development, but they should not
+ //! be enabled as part of the normal configuration.
+# define BOOST_HANA_CONFIG_ENABLE_DEBUG_MODE
+#endif
+
+#endif // !BOOST_HANA_CONFIG_HPP
diff --git a/boost/hana/contains.hpp b/boost/hana/contains.hpp
new file mode 100644
index 0000000000..8b8599d8f3
--- /dev/null
+++ b/boost/hana/contains.hpp
@@ -0,0 +1,51 @@
+/*!
+@file
+Defines `boost::hana::contains` and `boost::hana::in`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CONTAINS_HPP
+#define BOOST_HANA_CONTAINS_HPP
+
+#include <boost/hana/fwd/contains.hpp>
+
+#include <boost/hana/any_of.hpp>
+#include <boost/hana/concept/searchable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/equal.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Key>
+ constexpr auto contains_t::operator()(Xs&& xs, Key&& key) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Contains = BOOST_HANA_DISPATCH_IF(contains_impl<S>,
+ hana::Searchable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Searchable<S>::value,
+ "hana::contains(xs, key) requires 'xs' to be a Searchable");
+ #endif
+
+ return Contains::apply(static_cast<Xs&&>(xs),
+ static_cast<Key&&>(key));
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct contains_impl<S, when<condition>> : default_ {
+ template <typename Xs, typename X>
+ static constexpr auto apply(Xs&& xs, X&& x) {
+ return hana::any_of(static_cast<Xs&&>(xs),
+ hana::equal.to(static_cast<X&&>(x)));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CONTAINS_HPP
diff --git a/boost/hana/core.hpp b/boost/hana/core.hpp
new file mode 100644
index 0000000000..d028ff15ed
--- /dev/null
+++ b/boost/hana/core.hpp
@@ -0,0 +1,22 @@
+/*!
+@file
+Defines the @ref group-core module.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CORE_HPP
+#define BOOST_HANA_CORE_HPP
+
+#include <boost/hana/core/common.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/is_a.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/core/when.hpp>
+
+#endif // !BOOST_HANA_CORE_HPP
diff --git a/boost/hana/core/common.hpp b/boost/hana/core/common.hpp
new file mode 100644
index 0000000000..471110ac68
--- /dev/null
+++ b/boost/hana/core/common.hpp
@@ -0,0 +1,109 @@
+/*!
+@file
+Defines `boost::hana::common` and `boost::hana::common_t`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CORE_COMMON_HPP
+#define BOOST_HANA_CORE_COMMON_HPP
+
+#include <boost/hana/fwd/core/common.hpp>
+
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/detail/canonical_constant.hpp>
+#include <boost/hana/detail/std_common_type.hpp>
+#include <boost/hana/detail/void_t.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //////////////////////////////////////////////////////////////////////////
+ // common
+ //////////////////////////////////////////////////////////////////////////
+ //! @cond
+ template <typename T, typename U, typename>
+ struct common : common<T, U, when<true>> { };
+ //! @endcond
+
+ template <typename T, typename U, bool condition>
+ struct common<T, U, when<condition>>
+ : detail::std_common_type<T, U>
+ { };
+
+ template <typename T>
+ struct common<T, T> {
+ using type = T;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // has_common
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T, typename U, typename>
+ struct has_common : std::false_type { };
+
+ template <typename T, typename U>
+ struct has_common<T, U, detail::void_t<typename common<T, U>::type>>
+ : std::true_type
+ { };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Provided common data types for Constants
+ //////////////////////////////////////////////////////////////////////////
+ namespace constant_detail {
+ //! @todo
+ //! This is an awful hack to avoid having
+ //! @code
+ //! common<integral_constant_tag<int>, integral_constant_tag<long>>
+ //! ==
+ //! CanonicalConstant<long>
+ //! @endcode
+ template <typename A, typename B, typename C>
+ struct which {
+ using type = detail::CanonicalConstant<C>;
+ };
+
+ template <template <typename ...> class A, typename T, typename U, typename C>
+ struct which<A<T>, A<U>, C> {
+ using type = A<C>;
+ };
+ }
+
+ template <typename A, typename B>
+ struct common<A, B, when<
+ hana::Constant<A>::value &&
+ hana::Constant<B>::value &&
+ has_common<typename A::value_type, typename B::value_type>::value
+ >> {
+ using type = typename constant_detail::which<
+ A, B,
+ typename common<typename A::value_type,
+ typename B::value_type>::type
+ >::type;
+ };
+
+ template <typename A, typename B>
+ struct common<A, B, when<
+ hana::Constant<A>::value &&
+ !hana::Constant<B>::value &&
+ has_common<typename A::value_type, B>::value
+ >> {
+ using type = typename common<typename A::value_type, B>::type;
+ };
+
+ template <typename A, typename B>
+ struct common<A, B, when<
+ !hana::Constant<A>::value &&
+ hana::Constant<B>::value &&
+ has_common<A, typename B::value_type>::value
+ >> {
+ using type = typename common<A, typename B::value_type>::type;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CORE_COMMON_HPP
diff --git a/boost/hana/core/default.hpp b/boost/hana/core/default.hpp
new file mode 100644
index 0000000000..a03ffbb79a
--- /dev/null
+++ b/boost/hana/core/default.hpp
@@ -0,0 +1,32 @@
+/*!
+@file
+Defines `boost::hana::default_` and `boost::hana::is_default`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CORE_DEFAULT_HPP
+#define BOOST_HANA_CORE_DEFAULT_HPP
+
+#include <boost/hana/fwd/core/default.hpp>
+
+#include <boost/hana/config.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename Method, typename>
+ struct is_default : std::false_type { };
+
+ template <typename Method>
+ struct is_default<Method, decltype((void)
+ static_cast<default_>(*(Method*)0)
+ )>
+ : std::true_type
+ { };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CORE_DEFAULT_HPP
diff --git a/boost/hana/core/dispatch.hpp b/boost/hana/core/dispatch.hpp
new file mode 100644
index 0000000000..455766ad41
--- /dev/null
+++ b/boost/hana/core/dispatch.hpp
@@ -0,0 +1,18 @@
+/*!
+@file
+Includes all the headers needed to setup tag-dispatching.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CORE_DISPATCH_HPP
+#define BOOST_HANA_CORE_DISPATCH_HPP
+
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/detail/dispatch_if.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/when.hpp>
+
+#endif // !BOOST_HANA_CORE_DISPATCH_HPP
diff --git a/boost/hana/core/is_a.hpp b/boost/hana/core/is_a.hpp
new file mode 100644
index 0000000000..91cf45121a
--- /dev/null
+++ b/boost/hana/core/is_a.hpp
@@ -0,0 +1,41 @@
+/*!
+@file
+Defines `boost::hana::is_a` and `boost::hana::is_an`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CORE_IS_A_HPP
+#define BOOST_HANA_CORE_IS_A_HPP
+
+#include <boost/hana/fwd/core/is_a.hpp>
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/tag_of.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //////////////////////////////////////////////////////////////////////////
+ // is_a
+ //////////////////////////////////////////////////////////////////////////
+ template <typename DataType, typename T>
+ struct is_a_t<DataType, T>
+ : integral_constant<bool,
+ std::is_same<DataType, typename hana::tag_of<T>::type>::value
+ >
+ { };
+
+ template <typename DataType>
+ struct is_a_t<DataType> {
+ template <typename T>
+ constexpr auto operator()(T const&) const
+ { return hana::is_a<DataType, T>; }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CORE_IS_A_HPP
diff --git a/boost/hana/core/make.hpp b/boost/hana/core/make.hpp
new file mode 100644
index 0000000000..a4856a2ad5
--- /dev/null
+++ b/boost/hana/core/make.hpp
@@ -0,0 +1,45 @@
+/*!
+@file
+Defines `boost::hana::make`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CORE_MAKE_HPP
+#define BOOST_HANA_CORE_MAKE_HPP
+
+#include <boost/hana/fwd/core/make.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Datatype, typename>
+ struct make_impl : make_impl<Datatype, when<true>> { };
+ //! @endcond
+
+ template <typename Datatype, bool condition>
+ struct make_impl<Datatype, when<condition>> : default_ {
+ template <typename ...X>
+ static constexpr auto make_helper(int, X&& ...x)
+ -> decltype(Datatype(static_cast<X&&>(x)...))
+ { return Datatype(static_cast<X&&>(x)...); }
+
+ template <typename ...X>
+ static constexpr auto make_helper(long, X&& ...) {
+ static_assert((sizeof...(X), false),
+ "there exists no constructor for the given data type");
+ }
+
+ template <typename ...X>
+ static constexpr decltype(auto) apply(X&& ...x)
+ { return make_helper(int{}, static_cast<X&&>(x)...); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CORE_MAKE_HPP
diff --git a/boost/hana/core/tag_of.hpp b/boost/hana/core/tag_of.hpp
new file mode 100644
index 0000000000..5e469a3f90
--- /dev/null
+++ b/boost/hana/core/tag_of.hpp
@@ -0,0 +1,49 @@
+/*!
+@file
+Defines `boost::hana::tag_of` and `boost::hana::tag_of_t`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CORE_TAG_OF_HPP
+#define BOOST_HANA_CORE_TAG_OF_HPP
+
+#include <boost/hana/fwd/core/tag_of.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename T, typename>
+ struct tag_of : tag_of<T, when<true>> { };
+ //! @endcond
+
+ namespace core_detail {
+ template <typename ...>
+ struct is_valid { static constexpr bool value = true; };
+ }
+
+ template <typename T, bool condition>
+ struct tag_of<T, when<condition>> {
+ using type = T;
+ };
+
+ template <typename T>
+ struct tag_of<T, when<
+ core_detail::is_valid<typename T::hana_tag>::value
+ >> {
+ using type = typename T::hana_tag;
+ };
+
+ template <typename T> struct tag_of<T const> : tag_of<T> { };
+ template <typename T> struct tag_of<T volatile> : tag_of<T> { };
+ template <typename T> struct tag_of<T const volatile> : tag_of<T> { };
+ template <typename T> struct tag_of<T&> : tag_of<T> { };
+ template <typename T> struct tag_of<T&&> : tag_of<T> { };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CORE_TAG_OF_HPP
diff --git a/boost/hana/core/to.hpp b/boost/hana/core/to.hpp
new file mode 100644
index 0000000000..502c438f5c
--- /dev/null
+++ b/boost/hana/core/to.hpp
@@ -0,0 +1,194 @@
+/*!
+@file
+Defines `boost::hana::to` and related utilities.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CORE_TO_HPP
+#define BOOST_HANA_CORE_TO_HPP
+
+#include <boost/hana/fwd/core/to.hpp>
+
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/common.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/detail/wrong.hpp>
+#include <boost/hana/unpack.hpp>
+#include <boost/hana/value.hpp>
+
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //////////////////////////////////////////////////////////////////////////
+ // to
+ //////////////////////////////////////////////////////////////////////////
+ //! @cond
+ template <typename To, typename From, typename>
+ struct to_impl : to_impl<To, From, when<true>> { };
+ //! @endcond
+
+ namespace convert_detail {
+ struct no_conversion { };
+
+ template <typename ...>
+ struct is_valid { static constexpr bool value = true; };
+ }
+
+ template <typename To, typename From, bool condition>
+ struct to_impl<To, From, when<condition>> : convert_detail::no_conversion {
+ template <typename X>
+ static constexpr auto apply(X const&) {
+ static_assert(detail::wrong<to_impl<To, From>, X>{},
+ "no conversion is available between the provided types");
+ }
+ };
+
+ template <typename To, typename From>
+ struct to_impl<To, From, when<convert_detail::is_valid<
+ decltype(static_cast<To>(std::declval<From>()))
+ >::value>> {
+ template <typename X>
+ static constexpr To apply(X&& x)
+ { return static_cast<To>(static_cast<X&&>(x)); }
+ };
+
+ template <typename To>
+ struct to_impl<To, To> : embedding<> {
+ template <typename X>
+ static constexpr X apply(X&& x)
+ { return static_cast<X&&>(x); }
+ };
+
+ //! @cond
+ template <typename To>
+ template <typename X>
+ constexpr decltype(auto) to_t<To>::operator()(X&& x) const {
+ using From = typename hana::tag_of<X>::type;
+ return to_impl<To, From>::apply(static_cast<X&&>(x));
+ }
+ //! @endcond
+
+#define BOOST_HANA_DEFINE_EMBEDDING_IMPL(TO, FROM) \
+ template <> \
+ struct to_impl<TO, FROM> : embedding<> \
+ { static constexpr TO apply(FROM x) { return x; } } \
+/**/
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(long double, double);
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(long double, float);
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(double , float);
+
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long long, signed long);
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long long, signed int);
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long long, signed short);
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long long, signed char);
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long , signed int);
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long , signed short);
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long , signed char);
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed int , signed short);
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed int , signed char);
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed short , signed char);
+
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned long);
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned int);
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned short);
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned char);
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long , unsigned int);
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long , unsigned short);
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long , unsigned char);
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned int , unsigned short);
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned int , unsigned char);
+ BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned short , unsigned char);
+#undef BOOST_HANA_DEFINE_EMBEDDING_IMPL
+
+ namespace detail {
+ template <typename T>
+ struct copy_char_signedness {
+ using type = typename std::conditional<std::is_signed<char>::value,
+ std::make_signed<T>, std::make_unsigned<T>
+ >::type::type;
+ };
+ }
+
+ // If `char` is signed, we define an embedding from `char` to any signed
+ // integral type. Otherwise, we define one from `char` to any unsigned
+ // integral type.
+#define BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(TO) \
+ template <> \
+ struct to_impl<detail::copy_char_signedness<TO>::type, char> \
+ : embedding<> \
+ { \
+ static constexpr detail::copy_char_signedness<TO>::type \
+ apply(char x) \
+ { return x; } \
+ } \
+/**/
+ BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(long long);
+ BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(long);
+ BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(int);
+ BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(short);
+#undef BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL
+
+ template <typename T>
+ struct to_impl<T*, decltype(nullptr)> : embedding<> {
+ static constexpr T* apply(decltype(nullptr)) { return nullptr; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // is_convertible
+ //////////////////////////////////////////////////////////////////////////
+ template <typename From, typename To, typename>
+ struct is_convertible : std::true_type { };
+
+ template <typename From, typename To>
+ struct is_convertible<From, To, decltype((void)
+ static_cast<convert_detail::no_conversion>(*(to_impl<To, From>*)0)
+ )> : std::false_type { };
+
+ //////////////////////////////////////////////////////////////////////////
+ // is_embedded
+ //////////////////////////////////////////////////////////////////////////
+ template <typename From, typename To, typename>
+ struct is_embedded : std::false_type { };
+
+ template <typename From, typename To>
+ struct is_embedded<From, To, decltype((void)
+ static_cast<embedding<true>>(*(to_impl<To, From>*)0)
+ )> : std::true_type { };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Conversion for Constants
+ //////////////////////////////////////////////////////////////////////////
+ template <typename To, typename From>
+ struct to_impl<To, From, when<
+ hana::Constant<From>::value &&
+ is_convertible<typename From::value_type, To>::value
+ >> : embedding<is_embedded<typename From::value_type, To>::value> {
+ template <typename X>
+ static constexpr decltype(auto) apply(X const&)
+ { return hana::to<To>(hana::value<X>()); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Foldable -> Sequence
+ //////////////////////////////////////////////////////////////////////////
+ template <typename S, typename F>
+ struct to_impl<S, F, when<
+ hana::Sequence<S>::value &&
+ hana::Foldable<F>::value
+ >> : embedding<Sequence<F>::value> {
+ template <typename Xs>
+ static constexpr decltype(auto) apply(Xs&& xs)
+ { return hana::unpack(static_cast<Xs&&>(xs), hana::make<S>); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CORE_TO_HPP
diff --git a/boost/hana/core/when.hpp b/boost/hana/core/when.hpp
new file mode 100644
index 0000000000..06cb823a7c
--- /dev/null
+++ b/boost/hana/core/when.hpp
@@ -0,0 +1,15 @@
+/*!
+@file
+Defines `boost::hana::when` and `boost::hana::when_valid`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CORE_WHEN_HPP
+#define BOOST_HANA_CORE_WHEN_HPP
+
+#include <boost/hana/fwd/core/when.hpp>
+
+#endif // !BOOST_HANA_CORE_WHEN_HPP
diff --git a/boost/hana/count.hpp b/boost/hana/count.hpp
new file mode 100644
index 0000000000..cbdd218a46
--- /dev/null
+++ b/boost/hana/count.hpp
@@ -0,0 +1,50 @@
+/*!
+@file
+Defines `boost::hana::count`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_COUNT_HPP
+#define BOOST_HANA_COUNT_HPP
+
+#include <boost/hana/fwd/count.hpp>
+
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/count_if.hpp>
+#include <boost/hana/equal.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Value>
+ constexpr auto count_t::operator()(Xs&& xs, Value&& value) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Count = BOOST_HANA_DISPATCH_IF(count_impl<S>,
+ hana::Foldable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Foldable<S>::value,
+ "hana::count(xs, value) requires 'xs' to be Foldable");
+ #endif
+
+ return Count::apply(static_cast<Xs&&>(xs), static_cast<Value&&>(value));
+ }
+ //! @endcond
+
+ template <typename T, bool condition>
+ struct count_impl<T, when<condition>> : default_ {
+ template <typename Xs, typename Value>
+ static constexpr auto apply(Xs&& xs, Value&& value) {
+ return hana::count_if(static_cast<Xs&&>(xs),
+ hana::equal.to(static_cast<Value&&>(value)));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_COUNT_HPP
diff --git a/boost/hana/count_if.hpp b/boost/hana/count_if.hpp
new file mode 100644
index 0000000000..fca164b687
--- /dev/null
+++ b/boost/hana/count_if.hpp
@@ -0,0 +1,92 @@
+/*!
+@file
+Defines `boost::hana::count_if`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_COUNT_IF_HPP
+#define BOOST_HANA_COUNT_IF_HPP
+
+#include <boost/hana/fwd/count_if.hpp>
+
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/algorithm.hpp>
+#include <boost/hana/detail/fast_and.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/unpack.hpp>
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Pred>
+ constexpr auto count_if_t::operator()(Xs&& xs, Pred&& pred) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using CountIf = BOOST_HANA_DISPATCH_IF(count_if_impl<S>,
+ hana::Foldable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Foldable<S>::value,
+ "hana::count_if(xs, pred) requires 'xs' to be Foldable");
+ #endif
+
+ return CountIf::apply(static_cast<Xs&&>(xs),
+ static_cast<Pred&&>(pred));
+ }
+ //! @endcond
+
+ namespace detail {
+ template <typename Pred>
+ struct count_pred {
+ Pred pred;
+ template <typename ...Xs, typename = typename std::enable_if<
+ detail::fast_and<
+ Constant<decltype((*pred)(std::declval<Xs&&>()))>::value...
+ >::value
+ >::type>
+ constexpr auto operator()(Xs&& ...xs) const {
+ constexpr bool results[] = {false, // <-- avoid empty array
+ static_cast<bool>(hana::value<decltype((*pred)(static_cast<Xs&&>(xs)))>())...
+ };
+ constexpr std::size_t total = detail::count(
+ results, results + sizeof(results), true
+ );
+ return hana::size_c<total>;
+ }
+
+ template <typename ...Xs, typename = void, typename = typename std::enable_if<
+ !detail::fast_and<
+ Constant<decltype((*pred)(std::declval<Xs&&>()))>::value...
+ >::value
+ >::type>
+ constexpr auto operator()(Xs&& ...xs) const {
+ std::size_t total = 0;
+ using Swallow = std::size_t[];
+ (void)Swallow{0, ((*pred)(static_cast<Xs&&>(xs)) ? ++total : 0)...};
+ return total;
+ }
+ };
+ }
+
+ template <typename T, bool condition>
+ struct count_if_impl<T, when<condition>> : default_ {
+ template <typename Xs, typename Pred>
+ static constexpr decltype(auto) apply(Xs&& xs, Pred&& pred) {
+ // We use a pointer instead of a reference to avoid a Clang ICE.
+ return hana::unpack(static_cast<Xs&&>(xs),
+ detail::count_pred<decltype(&pred)>{&pred}
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_COUNT_IF_HPP
diff --git a/boost/hana/cycle.hpp b/boost/hana/cycle.hpp
new file mode 100644
index 0000000000..b3a2dcd849
--- /dev/null
+++ b/boost/hana/cycle.hpp
@@ -0,0 +1,127 @@
+/*!
+@file
+Defines `boost::hana::cycle`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_CYCLE_HPP
+#define BOOST_HANA_CYCLE_HPP
+
+#include <boost/hana/fwd/cycle.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concat.hpp>
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/concept/monad_plus.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/detail/array.hpp>
+#include <boost/hana/empty.hpp>
+#include <boost/hana/length.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename N>
+ constexpr auto cycle_t::operator()(Xs&& xs, N const& n) const {
+ using M = typename hana::tag_of<Xs>::type;
+ using Cycle = BOOST_HANA_DISPATCH_IF(cycle_impl<M>,
+ hana::MonadPlus<M>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::MonadPlus<M>::value,
+ "hana::cycle(xs, n) requires 'xs' to be a MonadPlus");
+
+ static_assert(hana::IntegralConstant<N>::value,
+ "hana::cycle(xs, n) requires 'n' to be an IntegralConstant");
+ #endif
+
+ static_assert(N::value >= 0,
+ "hana::cycle(xs, n) requires 'n' to be non-negative");
+
+ return Cycle::apply(static_cast<Xs&&>(xs), n);
+ }
+ //! @endcond
+
+ namespace detail {
+ template <typename M, std::size_t n, bool = n % 2 == 0>
+ struct cycle_helper;
+
+ template <typename M>
+ struct cycle_helper<M, 0, true> {
+ template <typename Xs>
+ static constexpr auto apply(Xs const&)
+ { return hana::empty<M>(); }
+ };
+
+ template <typename M, std::size_t n>
+ struct cycle_helper<M, n, true> {
+ template <typename Xs>
+ static constexpr auto apply(Xs const& xs)
+ { return cycle_helper<M, n/2>::apply(hana::concat(xs, xs)); }
+ };
+
+ template <typename M, std::size_t n>
+ struct cycle_helper<M, n, false> {
+ template <typename Xs>
+ static constexpr auto apply(Xs const& xs)
+ { return hana::concat(xs, cycle_helper<M, n-1>::apply(xs)); }
+ };
+ }
+
+ template <typename M, bool condition>
+ struct cycle_impl<M, when<condition>> : default_ {
+ template <typename Xs, typename N>
+ static constexpr auto apply(Xs const& xs, N const&) {
+ constexpr std::size_t n = N::value;
+ return detail::cycle_helper<M, n>::apply(xs);
+ }
+ };
+
+ namespace detail {
+ template <std::size_t N, std::size_t Len>
+ struct cycle_indices {
+ static constexpr auto compute_value() {
+ detail::array<std::size_t, N * Len> indices{};
+ // Avoid (incorrect) Clang warning about remainder by zero
+ // in the loop below.
+ std::size_t len = Len;
+ for (std::size_t i = 0; i < N * Len; ++i)
+ indices[i] = i % len;
+ return indices;
+ }
+
+ static constexpr auto value = compute_value();
+ };
+ }
+
+ template <typename S>
+ struct cycle_impl<S, when<Sequence<S>::value>> {
+ template <typename Indices, typename Xs, std::size_t ...i>
+ static constexpr auto cycle_helper(Xs&& xs, std::index_sequence<i...>) {
+ constexpr auto indices = Indices::value;
+ (void)indices; // workaround GCC warning when sizeof...(i) == 0
+ return hana::make<S>(hana::at_c<indices[i]>(xs)...);
+ }
+
+ template <typename Xs, typename N>
+ static constexpr auto apply(Xs&& xs, N const&) {
+ constexpr std::size_t n = N::value;
+ constexpr std::size_t len = decltype(hana::length(xs))::value;
+ using Indices = detail::cycle_indices<n, len>;
+ return cycle_helper<Indices>(static_cast<Xs&&>(xs),
+ std::make_index_sequence<n * len>{});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_CYCLE_HPP
diff --git a/boost/hana/define_struct.hpp b/boost/hana/define_struct.hpp
new file mode 100644
index 0000000000..9ba80596a1
--- /dev/null
+++ b/boost/hana/define_struct.hpp
@@ -0,0 +1,17 @@
+/*!
+@file
+Defines the `BOOST_HANA_DEFINE_STRUCT` macro.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DEFINE_STRUCT_HPP
+#define BOOST_HANA_DEFINE_STRUCT_HPP
+
+#include <boost/hana/fwd/define_struct.hpp>
+
+#include <boost/hana/detail/struct_macros.hpp>
+
+#endif // !BOOST_HANA_DEFINE_STRUCT_HPP
diff --git a/boost/hana/detail/algorithm.hpp b/boost/hana/detail/algorithm.hpp
new file mode 100644
index 0000000000..d398659e2c
--- /dev/null
+++ b/boost/hana/detail/algorithm.hpp
@@ -0,0 +1,184 @@
+/*!
+@file
+Defines several `constexpr` algorithms.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_ALGORITHM_HPP
+#define BOOST_HANA_DETAIL_ALGORITHM_HPP
+
+#include <boost/hana/functional/placeholder.hpp>
+
+#include <boost/hana/config.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <typename T>
+ constexpr void swap(T& x, T& y) {
+ auto tmp = x;
+ x = y;
+ y = std::move(tmp);
+ }
+
+ template <typename BidirIter>
+ constexpr void reverse(BidirIter first, BidirIter last) {
+ while (first != last) {
+ if (first == --last)
+ break;
+ detail::swap(*first, *last);
+ ++first;
+ }
+ }
+
+ template <typename BidirIter, typename BinaryPred>
+ constexpr bool next_permutation(BidirIter first, BidirIter last,
+ BinaryPred pred)
+ {
+ BidirIter i = last;
+ if (first == last || first == --i)
+ return false;
+ while (true) {
+ BidirIter ip1 = i;
+ if (pred(*--i, *ip1)) {
+ BidirIter j = last;
+ while (!pred(*i, *--j))
+ ;
+ detail::swap(*i, *j);
+ detail::reverse(ip1, last);
+ return true;
+ }
+ if (i == first) {
+ detail::reverse(first, last);
+ return false;
+ }
+ }
+ }
+
+ template <typename BidirIter>
+ constexpr bool next_permutation(BidirIter first, BidirIter last)
+ { return detail::next_permutation(first, last, hana::_ < hana::_); }
+
+
+ template <typename InputIter1, typename InputIter2, typename BinaryPred>
+ constexpr bool lexicographical_compare(InputIter1 first1, InputIter1 last1,
+ InputIter2 first2, InputIter2 last2,
+ BinaryPred pred)
+ {
+ for (; first2 != last2; ++first1, ++first2) {
+ if (first1 == last1 || pred(*first1, *first2))
+ return true;
+ else if (pred(*first2, *first1))
+ return false;
+ }
+ return false;
+ }
+
+ template <typename InputIter1, typename InputIter2>
+ constexpr bool lexicographical_compare(InputIter1 first1, InputIter1 last1,
+ InputIter2 first2, InputIter2 last2)
+ { return detail::lexicographical_compare(first1, last1, first2, last2, hana::_ < hana::_); }
+
+
+ template <typename InputIter1, typename InputIter2, typename BinaryPred>
+ constexpr bool equal(InputIter1 first1, InputIter1 last1,
+ InputIter2 first2, InputIter2 last2,
+ BinaryPred pred)
+ {
+ for (; first1 != last1 && first2 != last2; ++first1, ++first2)
+ if (!pred(*first1, *first2))
+ return false;
+ return first1 == last1 && first2 == last2;
+ }
+
+ template <typename InputIter1, typename InputIter2>
+ constexpr bool equal(InputIter1 first1, InputIter1 last1,
+ InputIter2 first2, InputIter2 last2)
+ { return detail::equal(first1, last1, first2, last2, hana::_ == hana::_); }
+
+
+ template <typename BidirIter, typename BinaryPred>
+ constexpr void sort(BidirIter first, BidirIter last, BinaryPred pred) {
+ if (first == last) return;
+
+ BidirIter i = first;
+ for (++i; i != last; ++i) {
+ BidirIter j = i;
+ auto t = *j;
+ for (BidirIter k = i; k != first && pred(t, *--k); --j)
+ *j = *k;
+ *j = t;
+ }
+ }
+
+ template <typename BidirIter>
+ constexpr void sort(BidirIter first, BidirIter last)
+ { detail::sort(first, last, hana::_ < hana::_); }
+
+
+ template <typename InputIter, typename T>
+ constexpr InputIter find(InputIter first, InputIter last, T const& value) {
+ for (; first != last; ++first)
+ if (*first == value)
+ return first;
+ return last;
+ }
+
+ template <typename InputIter, typename UnaryPred>
+ constexpr InputIter find_if(InputIter first, InputIter last, UnaryPred pred) {
+ for (; first != last; ++first)
+ if (pred(*first))
+ return first;
+ return last;
+ }
+
+ template <typename ForwardIter, typename T>
+ constexpr void iota(ForwardIter first, ForwardIter last, T value) {
+ while (first != last) {
+ *first++ = value;
+ ++value;
+ }
+ }
+
+ template <typename InputIt, typename T>
+ constexpr std::size_t
+ count(InputIt first, InputIt last, T const& value) {
+ std::size_t n = 0;
+ for (; first != last; ++first)
+ if (*first == value)
+ ++n;
+ return n;
+ }
+
+ template <typename InputIt, typename T, typename F>
+ constexpr T accumulate(InputIt first, InputIt last, T init, F f) {
+ for (; first != last; ++first)
+ init = f(init, *first);
+ return init;
+ }
+
+ template <typename InputIt, typename T>
+ constexpr T accumulate(InputIt first, InputIt last, T init) {
+ return detail::accumulate(first, last, init, hana::_ + hana::_);
+ }
+
+ template <typename ForwardIt>
+ constexpr ForwardIt min_element(ForwardIt first, ForwardIt last) {
+ if (first == last)
+ return last;
+
+ ForwardIt smallest = first;
+ ++first;
+ for (; first != last; ++first)
+ if (*first < *smallest)
+ smallest = first;
+ return smallest;
+ }
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_ALGORITHM_HPP
diff --git a/boost/hana/detail/any_of.hpp b/boost/hana/detail/any_of.hpp
new file mode 100644
index 0000000000..89c0d6a544
--- /dev/null
+++ b/boost/hana/detail/any_of.hpp
@@ -0,0 +1,46 @@
+/*!
+@file
+Defines `boost::hana::detail::any_of`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_ANY_OF_HPP
+#define BOOST_HANA_DETAIL_ANY_OF_HPP
+
+#include <boost/hana/config.hpp>
+
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ std::false_type expand(...);
+
+ template <template <typename ...> class Predicate, typename ...T>
+ decltype(expand(
+ typename std::enable_if<!Predicate<T>::value, void*>::type{}...
+ )) any_of_impl(int);
+
+ template <template <typename ...> class Predicate, typename ...T>
+ std::true_type any_of_impl(...);
+
+ //! @ingroup group-details
+ //! Returns whether the `Predicate` is satisfied by any of the `T...`.
+ //!
+ //! This metafunction will short-circuit the evaluation at the first
+ //! type satisfying the predicate, if such a type exists.
+ //!
+ //!
+ //! @note
+ //! The implementation technique used here was originally shown to
+ //! me by Eric Fiselier. All credits where due.
+ template <template <typename ...> class Predicate, typename ...T>
+ struct any_of
+ : decltype(any_of_impl<Predicate, T...>(int{}))
+ { };
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_ANY_OF_HPP
diff --git a/boost/hana/detail/array.hpp b/boost/hana/detail/array.hpp
new file mode 100644
index 0000000000..eaf031da51
--- /dev/null
+++ b/boost/hana/detail/array.hpp
@@ -0,0 +1,105 @@
+/*!
+@file
+Defines `boost::hana::detail::array`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_ARRAY_HPP
+#define BOOST_HANA_DETAIL_ARRAY_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/algorithm.hpp>
+#include <boost/hana/functional/placeholder.hpp>
+
+#include <cstddef>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <typename N>
+ constexpr N factorial(N n) {
+ N result = 1;
+ while (n != 0)
+ result *= n--;
+ return result;
+ }
+
+ //! @ingroup group-details
+ //! A minimal `std::array` with better `constexpr` support.
+ //!
+ //! We also provide some algorithms from the `constexpr/algorithm.hpp`
+ //! header as member functions to make them easier to use in constexpr
+ //! contexts, since a `constexpr` `array` can't be mutated in place.
+ template <typename T, std::size_t Size>
+ struct array {
+ T elems_[Size > 0 ? Size : 1];
+
+ constexpr T& operator[](std::size_t n)
+ { return elems_[n]; }
+
+ constexpr T const& operator[](std::size_t n) const
+ { return elems_[n]; }
+
+ constexpr std::size_t size() const noexcept
+ { return Size; }
+
+ constexpr T* begin() noexcept { return elems_; }
+ constexpr T const* begin() const noexcept { return elems_; }
+ constexpr T* end() noexcept { return elems_ + Size; }
+ constexpr T const* end() const noexcept { return elems_ + Size; }
+
+ // Algorithms from constexpr/algorithm.hpp
+ constexpr array reverse() const {
+ array result = *this;
+ detail::reverse(result.begin(), result.end());
+ return result;
+ }
+
+ template <typename BinaryPred>
+ constexpr auto permutations(BinaryPred pred) const {
+ array<array<T, Size>, detail::factorial(Size)> result{};
+ auto out = result.begin();
+ array copy = *this;
+
+ do *out++ = copy;
+ while (detail::next_permutation(copy.begin(), copy.end(), pred));
+
+ return result;
+ }
+
+ constexpr auto permutations() const
+ { return this->permutations(hana::_ < hana::_); }
+
+
+ template <typename BinaryPred>
+ constexpr auto sort(BinaryPred pred) const {
+ array result = *this;
+ detail::sort(result.begin(), result.end(), pred);
+ return result;
+ }
+
+ constexpr auto sort() const
+ { return this->sort(hana::_ < hana::_); }
+
+ template <typename U>
+ constexpr auto iota(U value) const {
+ array result = *this;
+ detail::iota(result.begin(), result.end(), value);
+ return result;
+ }
+ };
+
+ template <typename T, std::size_t M, typename U, std::size_t N>
+ constexpr bool operator==(array<T, M> a, array<U, N> b)
+ { return M == N && detail::equal(a.begin(), a.end(), b.begin(), b.end()); }
+
+ template <typename T, std::size_t M, typename U, std::size_t N>
+ constexpr bool operator<(array<T, M> a, array<U, N> b) {
+ return M < N || detail::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
+ }
+
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_ARRAY_HPP
diff --git a/boost/hana/detail/canonical_constant.hpp b/boost/hana/detail/canonical_constant.hpp
new file mode 100644
index 0000000000..0435ca0b42
--- /dev/null
+++ b/boost/hana/detail/canonical_constant.hpp
@@ -0,0 +1,80 @@
+/*!
+@file
+Defines `boost::hana::detail::CanonicalConstant`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_CANONICAL_CONSTANT_HPP
+#define BOOST_HANA_DETAIL_CANONICAL_CONSTANT_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ //! @ingroup group-details
+ //! Tag representing a canonical `Constant`.
+ //!
+ //! This is an implementation detail used to provide many models for
+ //! stuff like `Monoid`, `Group`, etc. To create a `CanonicalConstant`,
+ //! simply create an object with a nested `hana_tag` equal to the proper
+ //! specialization of `CanonicalConstant<T>`, and then also provide a
+ //! `constexpr` static member `::%value` holding the value of the constant.
+ template <typename T>
+ struct CanonicalConstant {
+ using value_type = T;
+ };
+} BOOST_HANA_NAMESPACE_END
+
+
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/when.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //////////////////////////////////////////////////////////////////////////
+ // Constant
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T>
+ struct value_impl<detail::CanonicalConstant<T>> {
+ template <typename X>
+ static constexpr decltype(auto) apply()
+ { return X::value; }
+ };
+
+ namespace detail {
+ template <typename T, typename X>
+ struct canonical_constant {
+ static constexpr auto value = hana::to<T>(hana::value<X>());
+ using hana_tag = detail::CanonicalConstant<T>;
+ };
+ }
+
+ template <typename T, typename C>
+ struct to_impl<detail::CanonicalConstant<T>, C, when<
+ hana::Constant<C>::value &&
+ is_convertible<typename C::value_type, T>::value
+ >>
+ : embedding<is_embedded<typename C::value_type, T>::value>
+ {
+ template <typename X>
+ static constexpr detail::canonical_constant<T, X> apply(X const&)
+ { return {}; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // IntegralConstant (when value_type is integral)
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T>
+ struct IntegralConstant<detail::CanonicalConstant<T>> {
+ static constexpr bool value = std::is_integral<T>::value;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_CANONICAL_CONSTANT_HPP
diff --git a/boost/hana/detail/concepts.hpp b/boost/hana/detail/concepts.hpp
new file mode 100644
index 0000000000..a3095f5377
--- /dev/null
+++ b/boost/hana/detail/concepts.hpp
@@ -0,0 +1,76 @@
+/*!
+@file
+Defines concepts from the Standard library.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_CONCEPTS_HPP
+#define BOOST_HANA_DETAIL_CONCEPTS_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/std_common_type.hpp>
+#include <boost/hana/detail/void_t.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ //////////////////////////////////////////////////////////////////////////
+ // EqualityComparable
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T, typename U = T, typename = void>
+ struct EqualityComparable : std::false_type { };
+
+ template <typename T>
+ struct EqualityComparable<T, T, detail::void_t<
+ decltype(static_cast<T&&>(*(T*)0) == static_cast<T&&>(*(T*)0) ? 0:0),
+ decltype(static_cast<T&&>(*(T*)0) != static_cast<T&&>(*(T*)0) ? 0:0)
+ >> : std::true_type { };
+
+ template <typename T, typename U>
+ struct EqualityComparable<T, U, typename std::enable_if<
+ !std::is_same<T, U>{}, detail::void_t<
+ decltype(static_cast<T&&>(*(T*)0) == static_cast<U&&>(*(U*)0) ? 0:0),
+ decltype(static_cast<U&&>(*(U*)0) == static_cast<T&&>(*(T*)0) ? 0:0),
+ decltype(static_cast<T&&>(*(T*)0) != static_cast<U&&>(*(U*)0) ? 0:0),
+ decltype(static_cast<U&&>(*(U*)0) != static_cast<T&&>(*(T*)0) ? 0:0),
+ typename detail::std_common_type<T, U>::type
+ >>::type> : std::integral_constant<bool,
+ EqualityComparable<T>::value &&
+ EqualityComparable<U>::value &&
+ EqualityComparable<typename detail::std_common_type<T, U>::type>::value
+ > { };
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // LessThanComparable
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T, typename U = T, typename = void>
+ struct LessThanComparable : std::false_type { };
+
+ template <typename T>
+ struct LessThanComparable<T, T, detail::void_t<
+ decltype(static_cast<T&&>(*(T*)0) < static_cast<T&&>(*(T*)0) ? 0:0)
+ >> : std::true_type { };
+
+ template <typename T, typename U>
+ struct LessThanComparable<T, U, std::enable_if_t<
+ !std::is_same<T, U>::value,
+ detail::void_t<
+ decltype(static_cast<T&&>(*(T*)0) < static_cast<U&&>(*(U*)0) ? 0:0),
+ decltype(static_cast<U&&>(*(U*)0) < static_cast<T&&>(*(T*)0) ? 0:0),
+ typename detail::std_common_type<T, U>::type
+ >
+ >>
+ : std::integral_constant<bool,
+ LessThanComparable<T>::value &&
+ LessThanComparable<U>::value &&
+ LessThanComparable<typename detail::std_common_type<T, U>::type>::value
+ >
+ { };
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_CONCEPTS_HPP
diff --git a/boost/hana/detail/create.hpp b/boost/hana/detail/create.hpp
new file mode 100644
index 0000000000..e98537eb44
--- /dev/null
+++ b/boost/hana/detail/create.hpp
@@ -0,0 +1,33 @@
+/*!
+@file
+Defines `boost::hana::detail::create`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_CREATE_HPP
+#define BOOST_HANA_DETAIL_CREATE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/decay.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ //! @ingroup group-details
+ //! Implementation of the generic `std::make_xxx` pattern for arbitrary
+ //! `xxx`s.
+ template <template <typename ...> class T>
+ struct create {
+ template <typename ...X>
+ constexpr T<typename detail::decay<X>::type...>
+ operator()(X&& ...x) const {
+ return T<typename detail::decay<X>::type...>{
+ static_cast<X&&>(x)...
+ };
+ }
+ };
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_CREATE_HPP
diff --git a/boost/hana/detail/decay.hpp b/boost/hana/detail/decay.hpp
new file mode 100644
index 0000000000..014981c677
--- /dev/null
+++ b/boost/hana/detail/decay.hpp
@@ -0,0 +1,48 @@
+/*!
+@file
+Defines a replacement for `std::decay`, which is sometimes too slow at
+compile-time.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_DECAY_HPP
+#define BOOST_HANA_DETAIL_DECAY_HPP
+
+#include <boost/hana/config.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ //! @ingroup group-details
+ //! Equivalent to `std::decay`, except faster.
+ //!
+ //! `std::decay` in libc++ is implemented in a suboptimal way. Since
+ //! this is used literally everywhere by the `make<...>` functions, it
+ //! is very important to keep this as efficient as possible.
+ //!
+ //! @note
+ //! `std::decay` is still being used in some places in the library.
+ //! Indeed, this is a peephole optimization and it would not be wise
+ //! to clutter the code with our own implementation of `std::decay`,
+ //! except when this actually makes a difference in compile-times.
+ template <typename T, typename U = typename std::remove_reference<T>::type>
+ struct decay {
+ using type = typename std::remove_cv<U>::type;
+ };
+
+ template <typename T, typename U>
+ struct decay<T, U[]> { using type = U*; };
+ template <typename T, typename U, std::size_t N>
+ struct decay<T, U[N]> { using type = U*; };
+
+ template <typename T, typename R, typename ...A>
+ struct decay<T, R(A...)> { using type = R(*)(A...); };
+ template <typename T, typename R, typename ...A>
+ struct decay<T, R(A..., ...)> { using type = R(*)(A..., ...); };
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_DECAY_HPP
diff --git a/boost/hana/detail/dependent_on.hpp b/boost/hana/detail/dependent_on.hpp
new file mode 100644
index 0000000000..97141664b0
--- /dev/null
+++ b/boost/hana/detail/dependent_on.hpp
@@ -0,0 +1,24 @@
+/*!
+@file
+Defines `boost::hana::detail::dependent_on`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_DEPENDENT_ON_HPP
+#define BOOST_HANA_DETAIL_DEPENDENT_ON_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <bool dummy, typename T>
+ struct dependent_on { using type = T; };
+
+ template <bool dummy, typename T>
+ using dependent_on_t = typename dependent_on<dummy, T>::type;
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_DEPENDENT_ON_HPP
diff --git a/boost/hana/detail/dispatch_if.hpp b/boost/hana/detail/dispatch_if.hpp
new file mode 100644
index 0000000000..88073fa7a2
--- /dev/null
+++ b/boost/hana/detail/dispatch_if.hpp
@@ -0,0 +1,56 @@
+/*!
+@file
+Defines `BOOST_HANA_DISPATCH_IF`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_DISPATCH_IF_HPP
+#define BOOST_HANA_DETAIL_DISPATCH_IF_HPP
+
+#include <boost/hana/config.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ struct deleted_implementation {
+ template <typename ...T>
+ static constexpr auto apply(T&& ...) = delete;
+ };
+
+ //! @ingroup group-details
+ //! Dispatch to the given implementation method only when a condition is
+ //! satisfied.
+ //!
+ //! If the condition is satisfied, this macro is equivalent to the type
+ //! `IMPL`. Otherwise, it is equivalent to a type with a deleted static
+ //! function named `apply`. When a tag-dispatching error happens, the
+ //! condition should be false and the deleted static function `apply`
+ //! will prevent the compiler from generating too much garbage.
+ //!
+ //! @note
+ //! When `BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS` is defined, the
+ //! condition is always ignored and this macro expands to the
+ //! implementation only.
+ //!
+ //! @remark
+ //! This must be implemented as a macro, because we don't want the
+ //! condition to be evaluated at all when
+ //! `BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS` is defined.
+#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ #define BOOST_HANA_DISPATCH_IF(IMPL, ...) \
+ ::std::conditional_t< \
+ (__VA_ARGS__), \
+ IMPL, \
+ ::boost::hana::deleted_implementation \
+ > \
+ /**/
+#else
+ #define BOOST_HANA_DISPATCH_IF(IMPL, ...) IMPL
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_DISPATCH_IF_HPP
diff --git a/boost/hana/detail/fast_and.hpp b/boost/hana/detail/fast_and.hpp
new file mode 100644
index 0000000000..a03ab05bcf
--- /dev/null
+++ b/boost/hana/detail/fast_and.hpp
@@ -0,0 +1,25 @@
+/*!
+@file
+Defines `boost::hana::detail::fast_and`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_FAST_AND_HPP
+#define BOOST_HANA_DETAIL_FAST_AND_HPP
+
+#include <boost/hana/config.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <bool ...b>
+ struct fast_and
+ : std::is_same<fast_and<b...>, fast_and<(b, true)...>>
+ { };
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_FAST_AND_HPP
diff --git a/boost/hana/detail/first_unsatisfied_index.hpp b/boost/hana/detail/first_unsatisfied_index.hpp
new file mode 100644
index 0000000000..d4a894e4bd
--- /dev/null
+++ b/boost/hana/detail/first_unsatisfied_index.hpp
@@ -0,0 +1,56 @@
+/*!
+@file
+Defines `boost::hana::detail::first_unsatisfied_index`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_FIRST_UNSATISFIED_INDEX_HPP
+#define BOOST_HANA_DETAIL_FIRST_UNSATISFIED_INDEX_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/value.hpp>
+
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <bool, typename Pred, typename ...Xs>
+ struct find_tail_size;
+
+ template <typename Pred, typename X, typename ...Xs>
+ struct find_tail_size<true, Pred, X, Xs...> {
+ static constexpr int value = find_tail_size<
+ static_cast<bool>(hana::value<decltype(std::declval<Pred>()(std::declval<X>()))>()),
+ Pred, Xs...
+ >::value;
+ };
+
+ template <typename Pred>
+ struct find_tail_size<true, Pred> {
+ static constexpr int value = -1;
+ };
+
+ template <typename Pred, typename ...Xs>
+ struct find_tail_size<false, Pred, Xs...> {
+ static constexpr int value = sizeof...(Xs);
+ };
+
+ //! @ingroup group-details
+ //! Returns the index of the first element which does not satisfy `Pred`,
+ //! or `sizeof...(Xs)` if no such element exists.
+ template <typename Pred>
+ struct first_unsatisfied_index {
+ template <typename ...Xs>
+ constexpr auto operator()(Xs&& ...) const {
+ return hana::size_c<
+ sizeof...(Xs) - 1 - find_tail_size<true, Pred, Xs&&...>::value
+ >;
+ }
+ };
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_FIRST_UNSATISFIED_INDEX_HPP
diff --git a/boost/hana/detail/has_common_embedding.hpp b/boost/hana/detail/has_common_embedding.hpp
new file mode 100644
index 0000000000..d1e8db5861
--- /dev/null
+++ b/boost/hana/detail/has_common_embedding.hpp
@@ -0,0 +1,69 @@
+/*!
+@file
+Defines `boost::hana::detail::has_[nontrivial_]common_embedding`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_HAS_COMMON_EMBEDDING_HPP
+#define BOOST_HANA_DETAIL_HAS_COMMON_EMBEDDING_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/common.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/detail/void_t.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <template <typename...> class Concept, typename T, typename U, typename = void>
+ struct has_common_embedding_impl : std::false_type { };
+
+ template <template <typename...> class Concept, typename T, typename U>
+ struct has_common_embedding_impl<Concept, T, U, detail::void_t<
+ typename common<T, U>::type
+ >> {
+ using Common = typename common<T, U>::type;
+ using type = std::integral_constant<bool,
+ Concept<T>::value &&
+ Concept<U>::value &&
+ Concept<Common>::value &&
+ is_embedded<T, Common>::value &&
+ is_embedded<U, Common>::value
+ >;
+ };
+
+ //! @ingroup group-details
+ //! Returns whether `T` and `U` both have an embedding into a
+ //! common type.
+ //!
+ //! If `T` and `U` do not have a common-type, this metafunction returns
+ //! false.
+ template <template <typename...> class Concept, typename T, typename U>
+ using has_common_embedding = typename has_common_embedding_impl<Concept, T, U>::type;
+
+ template <template <typename...> class Concept, typename T, typename U>
+ struct has_nontrivial_common_embedding_impl
+ : has_common_embedding_impl<Concept, T, U>
+ { };
+
+ template <template <typename...> class Concept, typename T>
+ struct has_nontrivial_common_embedding_impl<Concept, T, T>
+ : std::false_type
+ { };
+
+ //! @ingroup group-details
+ //! Returns whether `T` and `U` are distinct and both have an embedding
+ //! into a common type.
+ //!
+ //! If `T` and `U` do not have a common-type, this metafunction returns
+ //! false.
+ template <template <typename...> class Concept, typename T, typename U>
+ using has_nontrivial_common_embedding =
+ typename has_nontrivial_common_embedding_impl<Concept, T, U>::type;
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_HAS_COMMON_EMBEDDING_HPP
diff --git a/boost/hana/detail/has_duplicates.hpp b/boost/hana/detail/has_duplicates.hpp
new file mode 100644
index 0000000000..191f1e744e
--- /dev/null
+++ b/boost/hana/detail/has_duplicates.hpp
@@ -0,0 +1,65 @@
+/*!
+@file
+Defines `boost::hana::detail::has_duplicates`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_HAS_DUPLICATES_HPP
+#define BOOST_HANA_DETAIL_HAS_DUPLICATES_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/fast_and.hpp>
+#include <boost/hana/equal.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <typename T, typename ...U>
+ constexpr std::size_t pack_count() {
+ std::size_t c = 0;
+ std::size_t expand[] = {0, // avoid empty array
+ (decltype(hana::equal(std::declval<T>(), std::declval<U>()))::value
+ ? ++c
+ : c)...
+ };
+ (void)expand;
+
+ return c;
+ }
+
+ //! @ingroup group-details
+ //! Returns whether any of the `T`s are duplicate w.r.t. `hana::equal`.
+ //!
+ //! In particular, this does not check whether all of the `T`s are unique
+ //! as _types_, but rather whether they are unique when compared as
+ //! `hana::equal(std::declval<T>(), std::declval<U>())`. This assumes
+ //! the comparison to return an `IntegralConstant` that can be explicitly
+ //! converted to `bool`.
+ //!
+ //! @note
+ //! Since this utility is mostly used in assertions to check that there
+ //! are no duplicates in a sequence, we expect it to return `false` most
+ //! of the time (otherwise we will assert). Hence, this implementation is
+ //! biased towards the fact that we __will__ have to compare every pair of
+ //! elements in most cases, and it does not try to be lazy.
+ //!
+ //! @todo
+ //! This implementation is O(n^2). We could do it in O(n), but that would
+ //! require a more elaborate setup including storage with O(1) lookup
+ //! (which could be based on a compile-time hash). If we implement such
+ //! storage for associative sequences, we could use it to optimize this.
+ template <typename ...T>
+ struct has_duplicates {
+ static constexpr bool value =
+ sizeof...(T) > 0 &&
+ !detail::fast_and<(detail::pack_count<T, T...>() == 1)...>::value
+ ;
+ };
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_HAS_DUPLICATES_HPP
diff --git a/boost/hana/detail/hash_table.hpp b/boost/hana/detail/hash_table.hpp
new file mode 100644
index 0000000000..19a85dd764
--- /dev/null
+++ b/boost/hana/detail/hash_table.hpp
@@ -0,0 +1,145 @@
+/*!
+@file
+Defines `boost::hana::detail::hash_table`.
+
+@copyright Louis Dionne 2016
+@copyright Jason Rice 2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_HASH_TABLE_HPP
+#define BOOST_HANA_DETAIL_HASH_TABLE_HPP
+
+#include <boost/hana/equal.hpp>
+#include <boost/hana/ext/std/integer_sequence.hpp>
+#include <boost/hana/ext/std/integral_constant.hpp>
+#include <boost/hana/find_if.hpp>
+#include <boost/hana/fold_left.hpp>
+#include <boost/hana/hash.hpp>
+#include <boost/hana/optional.hpp>
+#include <boost/hana/range.hpp>
+#include <boost/hana/type.hpp>
+#include <boost/hana/value.hpp>
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <typename Hash, std::size_t ...i>
+ struct bucket { };
+
+ template <typename ...Buckets>
+ struct hash_table
+ : Buckets...
+ { };
+
+ // find_indices:
+ // Returns an `index_sequence` containing possible indices for the given
+ // `Key` in the `Map`.
+ template <typename Hash, std::size_t ...i>
+ std::index_sequence<i...> find_indices_impl(bucket<Hash, i...> const&);
+
+ template <typename Hash>
+ std::index_sequence<> find_indices_impl(...);
+
+ template <typename Map, typename Key>
+ struct find_indices {
+ using Hash = typename decltype(hana::hash(std::declval<Key>()))::type;
+ using type = decltype(detail::find_indices_impl<Hash>(std::declval<Map>()));
+ };
+ // end find_indices
+
+ // find_index:
+ // Returns the actual index of a `Key` in the `Map`. The type of the key
+ // associated to any given index must be retrievable with the `KeyAtIndex`
+ // alias.
+ template <template <std::size_t> class KeyAtIndex, typename Key>
+ struct find_pred {
+ template <typename Index>
+ auto operator()(Index const&) const -> decltype(
+ hana::equal(std::declval<KeyAtIndex<Index::value>>(),
+ std::declval<Key>())
+ );
+ };
+
+ template <typename Indices, typename Key, template <std::size_t> class KeyAtIndex>
+ struct find_index_impl {
+ using type = decltype(hana::find_if(Indices{}, find_pred<KeyAtIndex, Key>{}));
+ };
+
+ // This is a peephole optimization for buckets that have a single entry.
+ // It provides a nice speedup in the at_key.number_of_lookups benchmark.
+ // It is perhaps possible to make this part of `find_if` itself, but we
+ // should make sure that we retain that speedup.
+ template <std::size_t i, typename Key, template <std::size_t> class KeyAtIndex>
+ struct find_index_impl<std::index_sequence<i>, Key, KeyAtIndex> {
+ using Equal = decltype(
+ hana::equal(std::declval<KeyAtIndex<i>>(),
+ std::declval<Key>())
+ );
+ using type = typename std::conditional<Equal::value,
+ hana::optional<std::integral_constant<std::size_t, i>>,
+ hana::optional<>
+ >::type;
+ };
+
+ template <typename Map, typename Key, template <std::size_t> class KeyAtIndex>
+ struct find_index {
+ using Indices = typename find_indices<Map, Key>::type;
+ using type = typename find_index_impl<Indices, Key, KeyAtIndex>::type;
+ };
+ // end find_index
+
+ // bucket_insert:
+ // Inserts the given `Index` into the bucket of the `Map` in which `Key` falls.
+ template <typename Bucket, typename Hash, std::size_t Index>
+ struct update_bucket {
+ using type = Bucket;
+ };
+
+ template <std::size_t ...i, typename Hash, std::size_t Index>
+ struct update_bucket<bucket<Hash, i...>, Hash, Index> {
+ using type = bucket<Hash, i..., Index>;
+ };
+
+ template <typename Map, typename Key, std::size_t Index, bool =
+ (find_indices<Map, Key>::type::size() > 0)
+ >
+ struct bucket_insert;
+
+ template <typename ...Buckets, typename Key, std::size_t Index>
+ struct bucket_insert<hash_table<Buckets...>, Key, Index, true> {
+ // There is a bucket for that Hash; append the new index to it.
+ using Hash = typename decltype(hana::hash(std::declval<Key>()))::type;
+ using type = hash_table<typename update_bucket<Buckets, Hash, Index>::type...>;
+ };
+
+ template <typename ...Buckets, typename Key, std::size_t Index>
+ struct bucket_insert<hash_table<Buckets...>, Key, Index, false> {
+ // There is no bucket for that Hash; insert a new bucket.
+ using Hash = typename decltype(hana::hash(std::declval<Key>()))::type;
+ using type = hash_table<Buckets..., bucket<Hash, Index>>;
+ };
+ // end bucket_insert
+
+ // make_hash_table:
+ // Creates a `hash_table` type able of holding the given number of
+ // elements. The type of the key associated to any given index must
+ // be retrievable using the `KeyAtIndex` alias. All the keys must
+ // be distinct and have different hashes too.
+ template <template <std::size_t> class KeyAtIndex, std::size_t N,
+ typename Indices = std::make_index_sequence<N>>
+ struct make_hash_table;
+
+ template <template <std::size_t> class KeyAtIndex, std::size_t N, std::size_t ...i>
+ struct make_hash_table<KeyAtIndex, N, std::index_sequence<i...>> {
+ using type = hash_table<
+ bucket<typename decltype(hana::hash(std::declval<KeyAtIndex<i>>()))::type, i>...
+ >;
+ };
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_HASH_TABLE_HPP
diff --git a/boost/hana/detail/index_if.hpp b/boost/hana/detail/index_if.hpp
new file mode 100644
index 0000000000..116f278c87
--- /dev/null
+++ b/boost/hana/detail/index_if.hpp
@@ -0,0 +1,69 @@
+/*!
+@file
+Defines `boost::hana::detail::index_if`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_INDEX_IF_HPP
+#define BOOST_HANA_DETAIL_INDEX_IF_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <typename ...T>
+ struct pack {
+ static constexpr std::size_t length = sizeof...(T);
+ };
+
+ template <typename T>
+ struct make_pack;
+
+ template <template <typename...> class Template, typename ...T>
+ struct make_pack<Template<T...>> {
+ using type = pack<T...>;
+ };
+
+ template <typename T> struct make_pack<T const> : make_pack<T> { };
+ template <typename T> struct make_pack<T&> : make_pack<T> { };
+ template <typename T> struct make_pack<T&&> : make_pack<T> { };
+
+
+ //! @ingroup group-details
+ //! Returns the index of the first element of the `pack<>` that satisfies
+ //! the predicate, or the size of the pack if there is no such element.
+ //!
+ //! @note
+ //! The predicate must return an `IntegralConstant` that can be explicitly
+ //! converted to `bool`.
+ template <typename Pred, typename Ts, typename = when<true>>
+ struct index_if;
+
+ template <typename Pred, typename T, typename ...Ts>
+ struct index_if<Pred, pack<T, Ts...>, when<static_cast<bool>(decltype(
+ std::declval<Pred>()(std::declval<T>())
+ )::value)>> {
+ static constexpr std::size_t value = 0;
+ };
+
+ template <typename Pred, typename T, typename ...Ts>
+ struct index_if<Pred, pack<T, Ts...>, when<!static_cast<bool>(decltype(
+ std::declval<Pred>()(std::declval<T>())
+ )::value)>> {
+ static constexpr std::size_t value = 1 + index_if<Pred, pack<Ts...>>::value;
+ };
+
+ template <typename Pred>
+ struct index_if<Pred, pack<>> {
+ static constexpr std::size_t value = 0;
+ };
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_INDEX_IF_HPP
diff --git a/boost/hana/detail/intrinsics.hpp b/boost/hana/detail/intrinsics.hpp
new file mode 100644
index 0000000000..6483f212aa
--- /dev/null
+++ b/boost/hana/detail/intrinsics.hpp
@@ -0,0 +1,67 @@
+/*!
+@file
+Defines macros for commonly used type traits.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_INTRINSICS_HPP
+#define BOOST_HANA_DETAIL_INTRINSICS_HPP
+
+#include <boost/hana/config.hpp>
+
+
+// We use intrinsics if they are available because it speeds up the
+// compile-times.
+#if defined(BOOST_HANA_CONFIG_CLANG)
+# if __has_extension(is_empty)
+# define BOOST_HANA_TT_IS_EMPTY(T) __is_empty(T)
+# endif
+
+# if __has_extension(is_final)
+# define BOOST_HANA_TT_IS_FINAL(T) __is_final(T)
+# endif
+
+// TODO: Right now, this intrinsic is never used directly because of
+// https://llvm.org/bugs/show_bug.cgi?id=24173
+# if __has_extension(is_constructible) && false
+# define BOOST_HANA_TT_IS_CONSTRUCTIBLE(...) __is_constructible(__VA_ARGS__)
+# endif
+
+# if __has_extension(is_assignable)
+# define BOOST_HANA_TT_IS_ASSIGNABLE(T, U) __is_assignable(T, U)
+# endif
+
+# if __has_extension(is_convertible)
+# define BOOST_HANA_TT_IS_CONVERTIBLE(T, U) __is_convertible(T, U)
+# endif
+#endif
+
+#if !defined(BOOST_HANA_TT_IS_EMPTY)
+# include <type_traits>
+# define BOOST_HANA_TT_IS_EMPTY(T) ::std::is_empty<T>::value
+#endif
+
+#if !defined(BOOST_HANA_TT_IS_FINAL)
+# include <type_traits>
+# define BOOST_HANA_TT_IS_FINAL(T) ::std::is_final<T>::value
+#endif
+
+#if !defined(BOOST_HANA_TT_IS_CONSTRUCTIBLE)
+# include <type_traits>
+# define BOOST_HANA_TT_IS_CONSTRUCTIBLE(...) ::std::is_constructible<__VA_ARGS__>::value
+#endif
+
+#if !defined(BOOST_HANA_TT_IS_ASSIGNABLE)
+# include <type_traits>
+# define BOOST_HANA_TT_IS_ASSIGNABLE(T, U) ::std::is_assignable<T, U>::value
+#endif
+
+#if !defined(BOOST_HANA_TT_IS_CONVERTIBLE)
+# include <type_traits>
+# define BOOST_HANA_TT_IS_CONVERTIBLE(T, U) ::std::is_convertible<T, U>::value
+#endif
+
+#endif // !BOOST_HANA_DETAIL_INTRINSICS_HPP
diff --git a/boost/hana/detail/nested_by.hpp b/boost/hana/detail/nested_by.hpp
new file mode 100644
index 0000000000..5eabf3528b
--- /dev/null
+++ b/boost/hana/detail/nested_by.hpp
@@ -0,0 +1,40 @@
+/*!
+@file
+Defines `boost::hana::detail::nested_by`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_NESTED_BY_HPP
+#define BOOST_HANA_DETAIL_NESTED_BY_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/nested_by_fwd.hpp>
+
+#include <boost/hana/functional/flip.hpp>
+#include <boost/hana/functional/partial.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ //! @cond
+ template <typename Algorithm>
+ template <typename Predicate, typename Object>
+ constexpr decltype(auto) nested_by_t<Algorithm>::
+ operator()(Predicate&& predicate, Object&& object) const {
+ return Algorithm{}(static_cast<Object&&>(object),
+ static_cast<Predicate&&>(predicate));
+ }
+
+ template <typename Algorithm>
+ template <typename Predicate>
+ constexpr decltype(auto)
+ nested_by_t<Algorithm>::operator()(Predicate&& predicate) const {
+ return hana::partial(hana::flip(Algorithm{}),
+ static_cast<Predicate&&>(predicate));
+ }
+ //! @endcond
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_NESTED_BY_HPP
diff --git a/boost/hana/detail/nested_by_fwd.hpp b/boost/hana/detail/nested_by_fwd.hpp
new file mode 100644
index 0000000000..3ca9dc7058
--- /dev/null
+++ b/boost/hana/detail/nested_by_fwd.hpp
@@ -0,0 +1,55 @@
+/*!
+@file
+Forward declares `boost::hana::detail::nested_by`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_NESTED_BY_FWD_HPP
+#define BOOST_HANA_DETAIL_NESTED_BY_FWD_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <typename Algorithm>
+ struct nested_by_t {
+ template <typename Predicate, typename Object>
+ constexpr decltype(auto)
+ operator()(Predicate&& predicate, Object&& object) const;
+
+ template <typename Predicate>
+ constexpr decltype(auto) operator()(Predicate&& predicate) const;
+ };
+
+ //! @ingroup group-details
+ //! Provides a `.by` static constexpr function object.
+ //!
+ //! When creating a binary function object of type `Algorithm` whose
+ //! signature is `Object x Predicate -> Return`, `nested_by<Algorithm>`
+ //! can be used as a base class to `Algorithm`. Doing so will provide a
+ //! static constexpr member called `by`, which has the two following
+ //! signatures:
+ //! @code
+ //! Predicate x Object -> Return
+ //! Predicate -> (Object -> Return)
+ //! @endcode
+ //!
+ //! In other words, `nested_by` is a `curry`ed and `flip`ped version of
+ //! `Algorithm`. Note that the function object `Algorithm` must be
+ //! default-constructible, since the algorithm will be called as
+ //! `Algorithm{}(arguments...)`.
+ //!
+ //! @note
+ //! This function object is especially useful because it takes care of
+ //! avoiding ODR violations caused by the nested static constexpr member.
+ template <typename Algorithm>
+ struct nested_by { static constexpr nested_by_t<Algorithm> by{}; };
+
+ template <typename Algorithm>
+ constexpr nested_by_t<Algorithm> nested_by<Algorithm>::by;
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_NESTED_BY_FWD_HPP
diff --git a/boost/hana/detail/nested_than.hpp b/boost/hana/detail/nested_than.hpp
new file mode 100644
index 0000000000..fce96eecf0
--- /dev/null
+++ b/boost/hana/detail/nested_than.hpp
@@ -0,0 +1,29 @@
+/*!
+@file
+Defines `boost::hana::detail::nested_than`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_NESTED_THAN_HPP
+#define BOOST_HANA_DETAIL_NESTED_THAN_HPP
+
+#include <boost/hana/detail/nested_than_fwd.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/functional/flip.hpp>
+#include <boost/hana/functional/partial.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ //! @cond
+ template <typename Algorithm>
+ template <typename X>
+ constexpr decltype(auto) nested_than_t<Algorithm>::operator()(X&& x) const
+ { return hana::partial(hana::flip(Algorithm{}), static_cast<X&&>(x)); }
+ //! @endcond
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_NESTED_THAN_HPP
diff --git a/boost/hana/detail/nested_than_fwd.hpp b/boost/hana/detail/nested_than_fwd.hpp
new file mode 100644
index 0000000000..5e60d10251
--- /dev/null
+++ b/boost/hana/detail/nested_than_fwd.hpp
@@ -0,0 +1,47 @@
+/*!
+@file
+Forward declares `boost::hana::detail::nested_than`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_NESTED_THAN_FWD_HPP
+#define BOOST_HANA_DETAIL_NESTED_THAN_FWD_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <typename Algorithm>
+ struct nested_than_t {
+ template <typename X>
+ constexpr decltype(auto) operator()(X&& x) const;
+ };
+
+ //! @ingroup group-details
+ //! Provides a `.than` static constexpr function object.
+ //!
+ //! When creating a binary function object of type `Algo` whose signature
+ //! is `A x B -> Return`, `nested_than<Algo>` can be used as a base class
+ //! of `Algo`. Doing so will provide a static constexpr member called
+ //! `than`, which has the following signature:
+ //! @code
+ //! B -> A -> Return
+ //! @endcode
+ //!
+ //! Note that the function object `Algo` must be default-constructible,
+ //! since it will be called as `Algo{}(arguments...)`.
+ //!
+ //! @note
+ //! This function object is especially useful because it takes care of
+ //! avoiding ODR violations caused by the nested static constexpr member.
+ template <typename Algorithm>
+ struct nested_than { static constexpr nested_than_t<Algorithm> than{}; };
+
+ template <typename Algorithm>
+ constexpr nested_than_t<Algorithm> nested_than<Algorithm>::than;
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_NESTED_THAN_FWD_HPP
diff --git a/boost/hana/detail/nested_to.hpp b/boost/hana/detail/nested_to.hpp
new file mode 100644
index 0000000000..eee664ca93
--- /dev/null
+++ b/boost/hana/detail/nested_to.hpp
@@ -0,0 +1,28 @@
+/*!
+@file
+Defines `boost::hana::detail::nested_to`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_NESTED_TO_HPP
+#define BOOST_HANA_DETAIL_NESTED_TO_HPP
+
+#include <boost/hana/detail/nested_to_fwd.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/functional/partial.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ //! @cond
+ template <typename Algorithm>
+ template <typename X>
+ constexpr decltype(auto) nested_to_t<Algorithm>::operator()(X&& x) const
+ { return hana::partial(Algorithm{}, static_cast<X&&>(x)); }
+ //! @endcond
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_NESTED_TO_HPP
diff --git a/boost/hana/detail/nested_to_fwd.hpp b/boost/hana/detail/nested_to_fwd.hpp
new file mode 100644
index 0000000000..f21e0b181d
--- /dev/null
+++ b/boost/hana/detail/nested_to_fwd.hpp
@@ -0,0 +1,47 @@
+/*!
+@file
+Forward declares `boost::hana::detail::nested_to`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_NESTED_TO_FWD_HPP
+#define BOOST_HANA_DETAIL_NESTED_TO_FWD_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <typename Algorithm>
+ struct nested_to_t {
+ template <typename X>
+ constexpr decltype(auto) operator()(X&& x) const;
+ };
+
+ //! @ingroup group-details
+ //! Provides a `.to` static constexpr function object.
+ //!
+ //! When creating a binary function object of type `Algo` whose signature
+ //! is `Object x Object -> Return`, `nested_to<Algo>` can be used as a base
+ //! class of `Algo`. Doing so will provide a static constexpr member called
+ //! `to`, which has the following signature:
+ //! @code
+ //! Object -> Object -> Return
+ //! @endcode
+ //!
+ //! Note that the function object `Algo` must be default-constructible,
+ //! since the algorithm will be called as `Algo{}(arguments...)`.
+ //!
+ //! @note
+ //! This function object is especially useful because it takes care of
+ //! avoiding ODR violations caused by the nested static constexpr member.
+ template <typename Algorithm>
+ struct nested_to { static constexpr nested_to_t<Algorithm> to{}; };
+
+ template <typename Algorithm>
+ constexpr nested_to_t<Algorithm> nested_to<Algorithm>::to;
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_NESTED_TO_FWD_HPP
diff --git a/boost/hana/detail/operators/adl.hpp b/boost/hana/detail/operators/adl.hpp
new file mode 100644
index 0000000000..22f804bad4
--- /dev/null
+++ b/boost/hana/detail/operators/adl.hpp
@@ -0,0 +1,34 @@
+/*!
+@file
+Defines `boost::hana::detail::operators::adl`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_OPERATORS_ADL_HPP
+#define BOOST_HANA_DETAIL_OPERATORS_ADL_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace operators {
+ //! @ingroup group-details
+ //! Enables [ADL](http://en.cppreference.com/w/cpp/language/adl) in the
+ //! `hana::detail::operators` namespace.
+ //!
+ //! This is used by containers in Hana as a quick way to automatically
+ //! define the operators associated to some concepts, in conjunction
+ //! with the `detail::xxx_operators` family of metafunctions.
+ //!
+ //! Note that `adl` can be passed template arguments to make it unique
+ //! amongst a set of derived classes. This allows a set of derived classes
+ //! not to possess a common base class, which would disable the EBO when
+ //! many of these derived classes are stored in a Hana container. If EBO
+ //! is not a concern, `adl<>` can simply be used.
+ template <typename ...>
+ struct adl { };
+}} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_OPERATORS_ADL_HPP
diff --git a/boost/hana/detail/operators/arithmetic.hpp b/boost/hana/detail/operators/arithmetic.hpp
new file mode 100644
index 0000000000..d0459115b8
--- /dev/null
+++ b/boost/hana/detail/operators/arithmetic.hpp
@@ -0,0 +1,78 @@
+/*!
+@file
+Defines arithmetic operators.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_OPERATORS_ARITHMETIC_HPP
+#define BOOST_HANA_DETAIL_OPERATORS_ARITHMETIC_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/fwd/div.hpp>
+#include <boost/hana/fwd/minus.hpp>
+#include <boost/hana/fwd/mod.hpp>
+#include <boost/hana/fwd/mult.hpp>
+#include <boost/hana/fwd/negate.hpp>
+#include <boost/hana/fwd/plus.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <typename Tag>
+ struct arithmetic_operators {
+ static constexpr bool value = false;
+ };
+
+ namespace operators {
+ template <typename X, typename Y, typename = typename std::enable_if<
+ detail::arithmetic_operators<typename hana::tag_of<X>::type>::value ||
+ detail::arithmetic_operators<typename hana::tag_of<Y>::type>::value
+ >::type>
+ constexpr auto operator+(X&& x, Y&& y)
+ { return hana::plus(static_cast<X&&>(x), static_cast<Y&&>(y)); }
+
+
+ template <typename X, typename Y, typename = typename std::enable_if<
+ detail::arithmetic_operators<typename hana::tag_of<X>::type>::value ||
+ detail::arithmetic_operators<typename hana::tag_of<Y>::type>::value
+ >::type>
+ constexpr auto operator-(X&& x, Y&& y)
+ { return hana::minus(static_cast<X&&>(x), static_cast<Y&&>(y)); }
+
+ template <typename X, typename = typename std::enable_if<
+ detail::arithmetic_operators<typename hana::tag_of<X>::type>::value
+ >::type>
+ constexpr auto operator-(X&& x)
+ { return hana::negate(static_cast<X&&>(x)); }
+
+
+ template <typename X, typename Y, typename = typename std::enable_if<
+ detail::arithmetic_operators<typename hana::tag_of<X>::type>::value ||
+ detail::arithmetic_operators<typename hana::tag_of<Y>::type>::value
+ >::type>
+ constexpr auto operator*(X&& x, Y&& y)
+ { return hana::mult(static_cast<X&&>(x), static_cast<Y&&>(y)); }
+
+
+ template <typename X, typename Y, typename = typename std::enable_if<
+ detail::arithmetic_operators<typename hana::tag_of<X>::type>::value ||
+ detail::arithmetic_operators<typename hana::tag_of<Y>::type>::value
+ >::type>
+ constexpr auto operator/(X&& x, Y&& y)
+ { return hana::div(static_cast<X&&>(x), static_cast<Y&&>(y)); }
+
+ template <typename X, typename Y, typename = typename std::enable_if<
+ detail::arithmetic_operators<typename hana::tag_of<X>::type>::value ||
+ detail::arithmetic_operators<typename hana::tag_of<Y>::type>::value
+ >::type>
+ constexpr auto operator%(X&& x, Y&& y)
+ { return hana::mod(static_cast<X&&>(x), static_cast<Y&&>(y)); }
+ } // end namespace operators
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_OPERATORS_ARITHMETIC_HPP
diff --git a/boost/hana/detail/operators/comparable.hpp b/boost/hana/detail/operators/comparable.hpp
new file mode 100644
index 0000000000..579245f0f2
--- /dev/null
+++ b/boost/hana/detail/operators/comparable.hpp
@@ -0,0 +1,44 @@
+/*!
+@file
+Defines operators for Comparables.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_OPERATORS_COMPARABLE_HPP
+#define BOOST_HANA_DETAIL_OPERATORS_COMPARABLE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/fwd/equal.hpp>
+#include <boost/hana/fwd/not_equal.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <typename Tag>
+ struct comparable_operators {
+ static constexpr bool value = false;
+ };
+
+ namespace operators {
+ template <typename X, typename Y, typename = typename std::enable_if<
+ detail::comparable_operators<typename hana::tag_of<X>::type>::value ||
+ detail::comparable_operators<typename hana::tag_of<Y>::type>::value
+ >::type>
+ constexpr auto operator==(X&& x, Y&& y)
+ { return hana::equal(static_cast<X&&>(x), static_cast<Y&&>(y)); }
+
+ template <typename X, typename Y, typename = typename std::enable_if<
+ detail::comparable_operators<typename hana::tag_of<X>::type>::value ||
+ detail::comparable_operators<typename hana::tag_of<Y>::type>::value
+ >::type>
+ constexpr auto operator!=(X&& x, Y&& y)
+ { return hana::not_equal(static_cast<X&&>(x), static_cast<Y&&>(y)); }
+ } // end namespace operators
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_OPERATORS_COMPARABLE_HPP
diff --git a/boost/hana/detail/operators/iterable.hpp b/boost/hana/detail/operators/iterable.hpp
new file mode 100644
index 0000000000..95dadeedfe
--- /dev/null
+++ b/boost/hana/detail/operators/iterable.hpp
@@ -0,0 +1,40 @@
+/*!
+@file
+Defines operators for Iterables.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_OPERATORS_ITERABLE_HPP
+#define BOOST_HANA_DETAIL_OPERATORS_ITERABLE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/fwd/at.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <typename Derived>
+ struct iterable_operators {
+ template <typename N>
+ constexpr decltype(auto) operator[](N&& n) & {
+ return hana::at(static_cast<Derived&>(*this),
+ static_cast<N&&>(n));
+ }
+
+ template <typename N>
+ constexpr decltype(auto) operator[](N&& n) const& {
+ return hana::at(static_cast<Derived const&>(*this),
+ static_cast<N&&>(n));
+ }
+
+ template <typename N>
+ constexpr decltype(auto) operator[](N&& n) && {
+ return hana::at(static_cast<Derived&&>(*this),
+ static_cast<N&&>(n));
+ }
+ };
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_OPERATORS_ITERABLE_HPP
diff --git a/boost/hana/detail/operators/logical.hpp b/boost/hana/detail/operators/logical.hpp
new file mode 100644
index 0000000000..28623df322
--- /dev/null
+++ b/boost/hana/detail/operators/logical.hpp
@@ -0,0 +1,51 @@
+/*!
+@file
+Defines logical operators.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_OPERATORS_LOGICAL_HPP
+#define BOOST_HANA_DETAIL_OPERATORS_LOGICAL_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/fwd/and.hpp>
+#include <boost/hana/fwd/not.hpp>
+#include <boost/hana/fwd/or.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <typename Tag>
+ struct logical_operators {
+ static constexpr bool value = false;
+ };
+
+ namespace operators {
+ template <typename X, typename Y, typename = typename std::enable_if<
+ detail::logical_operators<typename hana::tag_of<X>::type>::value ||
+ detail::logical_operators<typename hana::tag_of<Y>::type>::value
+ >::type>
+ constexpr auto operator||(X&& x, Y&& y)
+ { return hana::or_(static_cast<X&&>(x), static_cast<Y&&>(y)); }
+
+ template <typename X, typename Y, typename = typename std::enable_if<
+ detail::logical_operators<typename hana::tag_of<X>::type>::value ||
+ detail::logical_operators<typename hana::tag_of<Y>::type>::value
+ >::type>
+ constexpr auto operator&&(X&& x, Y&& y)
+ { return hana::and_(static_cast<X&&>(x), static_cast<Y&&>(y)); }
+
+ template <typename X, typename = typename std::enable_if<
+ detail::logical_operators<typename hana::tag_of<X>::type>::value
+ >::type>
+ constexpr auto operator!(X&& x)
+ { return hana::not_(static_cast<X&&>(x)); }
+ } // end namespace operators
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_OPERATORS_LOGICAL_HPP
diff --git a/boost/hana/detail/operators/monad.hpp b/boost/hana/detail/operators/monad.hpp
new file mode 100644
index 0000000000..4cdf76b178
--- /dev/null
+++ b/boost/hana/detail/operators/monad.hpp
@@ -0,0 +1,35 @@
+/*!
+@file
+Defines operators for Monads.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_OPERATORS_MONAD_HPP
+#define BOOST_HANA_DETAIL_OPERATORS_MONAD_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/fwd/chain.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <typename Tag>
+ struct monad_operators {
+ static constexpr bool value = false;
+ };
+
+ namespace operators {
+ template <typename Xs, typename F, typename = typename std::enable_if<
+ detail::monad_operators<typename hana::tag_of<Xs>::type>::value
+ >::type>
+ constexpr auto operator|(Xs&& xs, F&& f)
+ { return hana::chain(static_cast<Xs&&>(xs), static_cast<F&&>(f)); }
+ } // end namespace operators
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_OPERATORS_MONAD_HPP
diff --git a/boost/hana/detail/operators/orderable.hpp b/boost/hana/detail/operators/orderable.hpp
new file mode 100644
index 0000000000..f60f14bbde
--- /dev/null
+++ b/boost/hana/detail/operators/orderable.hpp
@@ -0,0 +1,60 @@
+/*!
+@file
+Defines operators for Orderables.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_OPERATORS_ORDERABLE_HPP
+#define BOOST_HANA_DETAIL_OPERATORS_ORDERABLE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/fwd/greater.hpp>
+#include <boost/hana/fwd/greater_equal.hpp>
+#include <boost/hana/fwd/less.hpp>
+#include <boost/hana/fwd/less_equal.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <typename Tag>
+ struct orderable_operators {
+ static constexpr bool value = false;
+ };
+
+ namespace operators {
+ template <typename X, typename Y, typename = typename std::enable_if<
+ detail::orderable_operators<typename hana::tag_of<X>::type>::value ||
+ detail::orderable_operators<typename hana::tag_of<Y>::type>::value
+ >::type>
+ constexpr auto operator<(X&& x, Y&& y)
+ { return hana::less(static_cast<X&&>(x), static_cast<Y&&>(y)); }
+
+ template <typename X, typename Y, typename = typename std::enable_if<
+ detail::orderable_operators<typename hana::tag_of<X>::type>::value ||
+ detail::orderable_operators<typename hana::tag_of<Y>::type>::value
+ >::type>
+ constexpr auto operator>(X&& x, Y&& y)
+ { return hana::greater(static_cast<X&&>(x), static_cast<Y&&>(y)); }
+
+ template <typename X, typename Y, typename = typename std::enable_if<
+ detail::orderable_operators<typename hana::tag_of<X>::type>::value ||
+ detail::orderable_operators<typename hana::tag_of<Y>::type>::value
+ >::type>
+ constexpr auto operator<=(X&& x, Y&& y)
+ { return hana::less_equal(static_cast<X&&>(x), static_cast<Y&&>(y)); }
+
+ template <typename X, typename Y, typename = typename std::enable_if<
+ detail::orderable_operators<typename hana::tag_of<X>::type>::value ||
+ detail::orderable_operators<typename hana::tag_of<Y>::type>::value
+ >::type>
+ constexpr auto operator>=(X&& x, Y&& y)
+ { return hana::greater_equal(static_cast<X&&>(x), static_cast<Y&&>(y)); }
+ } // end namespace operators
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_OPERATORS_ORDERABLE_HPP
diff --git a/boost/hana/detail/operators/searchable.hpp b/boost/hana/detail/operators/searchable.hpp
new file mode 100644
index 0000000000..7b4cc231e7
--- /dev/null
+++ b/boost/hana/detail/operators/searchable.hpp
@@ -0,0 +1,40 @@
+/*!
+@file
+Defines operators for Searchables.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_OPERATORS_SEARCHABLE_HPP
+#define BOOST_HANA_DETAIL_OPERATORS_SEARCHABLE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/fwd/at_key.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <typename Derived>
+ struct searchable_operators {
+ template <typename Key>
+ constexpr decltype(auto) operator[](Key&& key) & {
+ return hana::at_key(static_cast<Derived&>(*this),
+ static_cast<Key&&>(key));
+ }
+
+ template <typename Key>
+ constexpr decltype(auto) operator[](Key&& key) && {
+ return hana::at_key(static_cast<Derived&&>(*this),
+ static_cast<Key&&>(key));
+ }
+
+ template <typename Key>
+ constexpr decltype(auto) operator[](Key&& key) const& {
+ return hana::at_key(static_cast<Derived const&>(*this),
+ static_cast<Key&&>(key));
+ }
+ };
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_OPERATORS_SEARCHABLE_HPP
diff --git a/boost/hana/detail/preprocessor.hpp b/boost/hana/detail/preprocessor.hpp
new file mode 100644
index 0000000000..a0432e8b44
--- /dev/null
+++ b/boost/hana/detail/preprocessor.hpp
@@ -0,0 +1,106 @@
+/*!
+@file
+Defines generally useful preprocessor macros.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_PREPROCESSOR_HPP
+#define BOOST_HANA_DETAIL_PREPROCESSOR_HPP
+
+//! @ingroup group-details
+//! Macro expanding to the number of arguments it is passed.
+//!
+//! Specifically, `BOOST_HANA_PP_NARG(x1, ..., xn)` expands to `n`.
+//! It is undefined behavior if `n > 64` or if `n == 0`.
+#define BOOST_HANA_PP_NARG(...) \
+ BOOST_HANA_PP_NARG_IMPL(__VA_ARGS__, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 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,)
+
+#define BOOST_HANA_PP_NARG_IMPL(e0, 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, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63, N, ...) N
+
+//! @ingroup group-details
+//! Expands to the concatenation of its two arguments.
+#define BOOST_HANA_PP_CONCAT(x, y) BOOST_HANA_PP_CONCAT_PRIMITIVE(x, y)
+#define BOOST_HANA_PP_CONCAT_PRIMITIVE(x, y) x ## y
+
+//! @ingroup group-details
+//! Expands to the stringized version of its argument.
+#define BOOST_HANA_PP_STRINGIZE(...) BOOST_HANA_PP_STRINGIZE_PRIMITIVE(__VA_ARGS__)
+#define BOOST_HANA_PP_STRINGIZE_PRIMITIVE(...) #__VA_ARGS__
+
+//! @ingroup group-details
+//! Expands to its last argument.
+//!
+//! This macro can be passed up to 20 arguments.
+#define BOOST_HANA_PP_BACK(...) \
+ BOOST_HANA_PP_BACK_IMPL(BOOST_HANA_PP_NARG(__VA_ARGS__), __VA_ARGS__)
+
+#define BOOST_HANA_PP_BACK_IMPL(N, ...) \
+ BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_BACK_IMPL_, N)(__VA_ARGS__)
+
+#define BOOST_HANA_PP_BACK_IMPL_1(e0) e0
+#define BOOST_HANA_PP_BACK_IMPL_2(e0, e1) e1
+#define BOOST_HANA_PP_BACK_IMPL_3(e0, e1, e2) e2
+#define BOOST_HANA_PP_BACK_IMPL_4(e0, e1, e2, e3) e3
+#define BOOST_HANA_PP_BACK_IMPL_5(e0, e1, e2, e3, e4) e4
+#define BOOST_HANA_PP_BACK_IMPL_6(e0, e1, e2, e3, e4, e5) e5
+#define BOOST_HANA_PP_BACK_IMPL_7(e0, e1, e2, e3, e4, e5, e6) e6
+#define BOOST_HANA_PP_BACK_IMPL_8(e0, e1, e2, e3, e4, e5, e6, e7) e7
+#define BOOST_HANA_PP_BACK_IMPL_9(e0, e1, e2, e3, e4, e5, e6, e7, e8) e8
+#define BOOST_HANA_PP_BACK_IMPL_10(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9) e9
+#define BOOST_HANA_PP_BACK_IMPL_11(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10) e10
+#define BOOST_HANA_PP_BACK_IMPL_12(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11) e11
+#define BOOST_HANA_PP_BACK_IMPL_13(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) e12
+#define BOOST_HANA_PP_BACK_IMPL_14(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13) e13
+#define BOOST_HANA_PP_BACK_IMPL_15(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14) e14
+#define BOOST_HANA_PP_BACK_IMPL_16(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15) e15
+#define BOOST_HANA_PP_BACK_IMPL_17(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16) e16
+#define BOOST_HANA_PP_BACK_IMPL_18(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17) e17
+#define BOOST_HANA_PP_BACK_IMPL_19(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18) e18
+#define BOOST_HANA_PP_BACK_IMPL_20(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19) e19
+
+//! @ingroup group-details
+//! Expands to all of its arguments, except for the last one.
+//!
+//! This macro can be given up to 20 arguments.
+#define BOOST_HANA_PP_DROP_BACK(...) \
+ BOOST_HANA_PP_DROP_BACK_IMPL(BOOST_HANA_PP_NARG(__VA_ARGS__), __VA_ARGS__)
+
+#define BOOST_HANA_PP_DROP_BACK_IMPL(N, ...) \
+ BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_DROP_BACK_IMPL_, N)(__VA_ARGS__)
+
+#define BOOST_HANA_PP_DROP_BACK_IMPL_1(e0)
+#define BOOST_HANA_PP_DROP_BACK_IMPL_2(e0, e1) e0
+#define BOOST_HANA_PP_DROP_BACK_IMPL_3(e0, e1, e2) e0, e1
+#define BOOST_HANA_PP_DROP_BACK_IMPL_4(e0, e1, e2, e3) e0, e1, e2
+#define BOOST_HANA_PP_DROP_BACK_IMPL_5(e0, e1, e2, e3, e4) e0, e1, e2, e3
+#define BOOST_HANA_PP_DROP_BACK_IMPL_6(e0, e1, e2, e3, e4, e5) e0, e1, e2, e3, e4
+#define BOOST_HANA_PP_DROP_BACK_IMPL_7(e0, e1, e2, e3, e4, e5, e6) e0, e1, e2, e3, e4, e5
+#define BOOST_HANA_PP_DROP_BACK_IMPL_8(e0, e1, e2, e3, e4, e5, e6, e7) e0, e1, e2, e3, e4, e5, e6
+#define BOOST_HANA_PP_DROP_BACK_IMPL_9(e0, e1, e2, e3, e4, e5, e6, e7, e8) e0, e1, e2, e3, e4, e5, e6, e7
+#define BOOST_HANA_PP_DROP_BACK_IMPL_10(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9) e0, e1, e2, e3, e4, e5, e6, e7, e8
+#define BOOST_HANA_PP_DROP_BACK_IMPL_11(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9
+#define BOOST_HANA_PP_DROP_BACK_IMPL_12(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10
+#define BOOST_HANA_PP_DROP_BACK_IMPL_13(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11
+#define BOOST_HANA_PP_DROP_BACK_IMPL_14(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12
+#define BOOST_HANA_PP_DROP_BACK_IMPL_15(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13
+#define BOOST_HANA_PP_DROP_BACK_IMPL_16(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14
+#define BOOST_HANA_PP_DROP_BACK_IMPL_17(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15
+#define BOOST_HANA_PP_DROP_BACK_IMPL_18(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16
+#define BOOST_HANA_PP_DROP_BACK_IMPL_19(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17
+#define BOOST_HANA_PP_DROP_BACK_IMPL_20(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18
+
+//! @ingroup group-details
+//! Expands to its first argument.
+#define BOOST_HANA_PP_FRONT(...) BOOST_HANA_PP_FRONT_IMPL(__VA_ARGS__, )
+#define BOOST_HANA_PP_FRONT_IMPL(e0, ...) e0
+
+//! @ingroup group-details
+//! Expands to all of its arguments, except for the first one.
+//!
+//! This macro may not be called with less than 2 arguments.
+#define BOOST_HANA_PP_DROP_FRONT(e0, ...) __VA_ARGS__
+
+#endif // !BOOST_HANA_DETAIL_PREPROCESSOR_HPP
diff --git a/boost/hana/detail/std_common_type.hpp b/boost/hana/detail/std_common_type.hpp
new file mode 100644
index 0000000000..209c8fcb04
--- /dev/null
+++ b/boost/hana/detail/std_common_type.hpp
@@ -0,0 +1,36 @@
+/*!
+@file
+Defines a SFINAE-friendly version of `std::common_type`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_STD_COMMON_TYPE_HPP
+#define BOOST_HANA_DETAIL_STD_COMMON_TYPE_HPP
+
+#include <boost/hana/config.hpp>
+
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ //! @ingroup group-details
+ //! Equivalent to `std::common_type`, except it is SFINAE-friendly and
+ //! does not support custom specializations.
+ template <typename T, typename U, typename = void>
+ struct std_common_type { };
+
+ template <typename T, typename U>
+ struct std_common_type<T, U, decltype((void)(
+ true ? std::declval<T>() : std::declval<U>()
+ ))> {
+ using type = typename std::decay<
+ decltype(true ? std::declval<T>() : std::declval<U>())
+ >::type;
+ };
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_STD_COMMON_TYPE_HPP
diff --git a/boost/hana/detail/struct_macros.erb.hpp b/boost/hana/detail/struct_macros.erb.hpp
new file mode 100644
index 0000000000..dfd94b1340
--- /dev/null
+++ b/boost/hana/detail/struct_macros.erb.hpp
@@ -0,0 +1,185 @@
+<%#
+ This is an ERB [1] template file used to generate the
+ <boost/hana/detail/struct_macros.hpp> header. The maximum
+ number of members that can be handled by the macros can
+ be controlled with the 'MAX_NUMBER_OF_MEMBERS' variable,
+ which can be set when calling ERB to generate the header:
+
+ export MAX_NUMBER_OF_MEMBERS=55; erb struct_macros.erb.hpp
+
+ 'MAX_NUMBER_OF_MEMBERS' must be <= 62, otherwise an error is triggered.
+ In case 'MAX_NUMBER_OF_MEMBERS' is not specified, it defaults to 40.
+
+ [1]: http://en.wikipedia.org/wiki/ERuby
+%>
+
+<%
+ MAX_NUMBER_OF_MEMBERS = (ENV["MAX_NUMBER_OF_MEMBERS"] || 40).to_i
+ raise "MAX_NUMBER_OF_MEMBERS must be <= 62" if MAX_NUMBER_OF_MEMBERS > 62
+%>
+
+/*!
+@file
+Defines the `BOOST_HANA_DEFINE_STRUCT`, `BOOST_HANA_ADAPT_STRUCT`, and
+`BOOST_HANA_ADAPT_ADT` macros.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+//////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS GENERATED FROM THE <boost/hana/detail/struct_macros.erb.hpp>
+// ERB TEMPLATE. DO NOT EDIT THIS FILE DIRECTLY.
+//
+// THE ERB TEMPLATE CONTAINS INFORMATION ABOUT HOW TO REGENERATE THIS FILE.
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_HANA_DETAIL_STRUCT_MACROS_HPP
+#define BOOST_HANA_DETAIL_STRUCT_MACROS_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/preprocessor.hpp>
+#include <boost/hana/pair.hpp>
+#include <boost/hana/string.hpp>
+#include <boost/hana/tuple.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace struct_detail {
+ template <typename Memptr, Memptr ptr>
+ struct member_ptr {
+ template <typename T>
+ constexpr decltype(auto) operator()(T&& t) const
+ { return static_cast<T&&>(t).*ptr; }
+ };
+
+ constexpr std::size_t strlen(char const* s) {
+ std::size_t n = 0;
+ while (*s++ != '\0')
+ ++n;
+ return n;
+ }
+
+ template <std::size_t n, typename Names, std::size_t ...i>
+ constexpr auto prepare_member_name_impl(std::index_sequence<i...>) {
+ return hana::string_c<hana::at_c<n>(Names::get())[i]...>;
+ }
+
+ template <std::size_t n, typename Names>
+ constexpr auto prepare_member_name() {
+ constexpr std::size_t len = strlen(hana::at_c<n>(Names::get()));
+ return prepare_member_name_impl<n, Names>(std::make_index_sequence<len>{});
+ }
+} BOOST_HANA_NAMESPACE_END
+
+//////////////////////////////////////////////////////////////////////////////
+// BOOST_HANA_ADAPT_STRUCT
+//////////////////////////////////////////////////////////////////////////////
+template <typename ...>
+struct BOOST_HANA_ADAPT_STRUCT_must_be_called_in_the_global_namespace;
+
+#define BOOST_HANA_ADAPT_STRUCT(...) \
+ template <> \
+ struct BOOST_HANA_ADAPT_STRUCT_must_be_called_in_the_global_namespace<>; \
+ BOOST_HANA_ADAPT_STRUCT_IMPL(BOOST_HANA_PP_NARG(__VA_ARGS__), __VA_ARGS__)\
+ static_assert(true, "force the usage of a trailing semicolon") \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL(N, ...) \
+ BOOST_HANA_PP_CONCAT(BOOST_HANA_ADAPT_STRUCT_IMPL_, N)(__VA_ARGS__)
+
+<% (0..MAX_NUMBER_OF_MEMBERS).each do |n| %>
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_<%= n+1 %>(TYPE <%= (1..n).map { |i| ", m#{i}" }.join %>) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ <%= (1..n).map { |i| "BOOST_HANA_PP_STRINGIZE(m#{i})" }.join(', ') %> \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ <%= (1..n).map { |i| "::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<#{i-1}, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m#{i}), &TYPE::m#{i}>{})" }.join(', ') %>\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+<% end %>
+
+//////////////////////////////////////////////////////////////////////////////
+// BOOST_HANA_ADAPT_ADT
+//////////////////////////////////////////////////////////////////////////////
+template <typename ...>
+struct BOOST_HANA_ADAPT_ADT_must_be_called_in_the_global_namespace;
+
+#define BOOST_HANA_ADAPT_ADT(...) \
+ template <> \
+ struct BOOST_HANA_ADAPT_ADT_must_be_called_in_the_global_namespace<>; \
+ BOOST_HANA_ADAPT_ADT_IMPL(BOOST_HANA_PP_NARG(__VA_ARGS__), __VA_ARGS__) \
+ static_assert(true, "force the usage of a trailing semicolon") \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL(N, ...) \
+ BOOST_HANA_PP_CONCAT(BOOST_HANA_ADAPT_ADT_IMPL_, N)(__VA_ARGS__)
+
+<% (0..MAX_NUMBER_OF_MEMBERS).each do |n| %>
+#define BOOST_HANA_ADAPT_ADT_IMPL_<%= n+1 %>(TYPE <%= (1..n).map { |i| ", m#{i}" }.join %>) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ <%= (1..n).map { |i| "BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m#{i})" }.join(', ') %>\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ <%= (1..n).map { |i| "::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<#{i-1}, member_names>(), BOOST_HANA_PP_DROP_FRONT m#{i})" }.join(', ') %>\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+<% end %>
+
+//////////////////////////////////////////////////////////////////////////////
+// BOOST_HANA_DEFINE_STRUCT
+//////////////////////////////////////////////////////////////////////////////
+#define BOOST_HANA_DEFINE_STRUCT(...) \
+ BOOST_HANA_DEFINE_STRUCT_IMPL(BOOST_HANA_PP_NARG(__VA_ARGS__), __VA_ARGS__)
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL(N, ...) \
+ BOOST_HANA_PP_CONCAT(BOOST_HANA_DEFINE_STRUCT_IMPL_, N)(__VA_ARGS__)
+
+<% (0..MAX_NUMBER_OF_MEMBERS).each do |n| %>
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_<%= n+1 %>(TYPE <%= (1..n).map { |i| ", m#{i}" }.join %>) \
+ <%= (1..n).map { |i| "BOOST_HANA_PP_DROP_BACK m#{i} BOOST_HANA_PP_BACK m#{i};" }.join(' ') %> \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ <%= (1..n).map { |i| "BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m#{i})" }.join(', ') %>\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ <%= (1..n).map { |i| "::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<#{i-1}, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m#{i}), &TYPE::BOOST_HANA_PP_BACK m#{i}>{})" }.join(', ') %>\
+ ); \
+ } \
+ } \
+/**/
+<% end %>
+
+#endif // !BOOST_HANA_DETAIL_STRUCT_MACROS_HPP
diff --git a/boost/hana/detail/struct_macros.hpp b/boost/hana/detail/struct_macros.hpp
new file mode 100644
index 0000000000..daeeb8a57a
--- /dev/null
+++ b/boost/hana/detail/struct_macros.hpp
@@ -0,0 +1,3469 @@
+
+
+
+
+/*!
+@file
+Defines the `BOOST_HANA_DEFINE_STRUCT`, `BOOST_HANA_ADAPT_STRUCT`, and
+`BOOST_HANA_ADAPT_ADT` macros.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+//////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS GENERATED FROM THE <boost/hana/detail/struct_macros.erb.hpp>
+// ERB TEMPLATE. DO NOT EDIT THIS FILE DIRECTLY.
+//
+// THE ERB TEMPLATE CONTAINS INFORMATION ABOUT HOW TO REGENERATE THIS FILE.
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_HANA_DETAIL_STRUCT_MACROS_HPP
+#define BOOST_HANA_DETAIL_STRUCT_MACROS_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/preprocessor.hpp>
+#include <boost/hana/pair.hpp>
+#include <boost/hana/string.hpp>
+#include <boost/hana/tuple.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace struct_detail {
+ template <typename Memptr, Memptr ptr>
+ struct member_ptr {
+ template <typename T>
+ constexpr decltype(auto) operator()(T&& t) const
+ { return static_cast<T&&>(t).*ptr; }
+ };
+
+ constexpr std::size_t strlen(char const* s) {
+ std::size_t n = 0;
+ while (*s++ != '\0')
+ ++n;
+ return n;
+ }
+
+ template <std::size_t n, typename Names, std::size_t ...i>
+ constexpr auto prepare_member_name_impl(std::index_sequence<i...>) {
+ return hana::string_c<hana::at_c<n>(Names::get())[i]...>;
+ }
+
+ template <std::size_t n, typename Names>
+ constexpr auto prepare_member_name() {
+ constexpr std::size_t len = strlen(hana::at_c<n>(Names::get()));
+ return prepare_member_name_impl<n, Names>(std::make_index_sequence<len>{});
+ }
+} BOOST_HANA_NAMESPACE_END
+
+//////////////////////////////////////////////////////////////////////////////
+// BOOST_HANA_ADAPT_STRUCT
+//////////////////////////////////////////////////////////////////////////////
+template <typename ...>
+struct BOOST_HANA_ADAPT_STRUCT_must_be_called_in_the_global_namespace;
+
+#define BOOST_HANA_ADAPT_STRUCT(...) \
+ template <> \
+ struct BOOST_HANA_ADAPT_STRUCT_must_be_called_in_the_global_namespace<>; \
+ BOOST_HANA_ADAPT_STRUCT_IMPL(BOOST_HANA_PP_NARG(__VA_ARGS__), __VA_ARGS__)\
+ static_assert(true, "force the usage of a trailing semicolon") \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL(N, ...) \
+ BOOST_HANA_PP_CONCAT(BOOST_HANA_ADAPT_STRUCT_IMPL_, N)(__VA_ARGS__)
+
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_1(TYPE ) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ \
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_2(TYPE , m1) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_3(TYPE , m1, m2) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_4(TYPE , m1, m2, m3) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_5(TYPE , m1, m2, m3, m4) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_6(TYPE , m1, m2, m3, m4, m5) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_7(TYPE , m1, m2, m3, m4, m5, m6) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_8(TYPE , m1, m2, m3, m4, m5, m6, m7) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_9(TYPE , m1, m2, m3, m4, m5, m6, m7, m8) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_10(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_11(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_12(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_13(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_14(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_15(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_16(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_17(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_18(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_19(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_20(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_21(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_22(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_23(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_24(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_25(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_26(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_27(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_28(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_29(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_30(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_31(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_32(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_33(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_34(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_35(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_36(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_37(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35), BOOST_HANA_PP_STRINGIZE(m36) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m36), &TYPE::m36>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_38(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35), BOOST_HANA_PP_STRINGIZE(m36), BOOST_HANA_PP_STRINGIZE(m37) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m36), &TYPE::m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m37), &TYPE::m37>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_39(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35), BOOST_HANA_PP_STRINGIZE(m36), BOOST_HANA_PP_STRINGIZE(m37), BOOST_HANA_PP_STRINGIZE(m38) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m36), &TYPE::m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m37), &TYPE::m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m38), &TYPE::m38>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_40(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35), BOOST_HANA_PP_STRINGIZE(m36), BOOST_HANA_PP_STRINGIZE(m37), BOOST_HANA_PP_STRINGIZE(m38), BOOST_HANA_PP_STRINGIZE(m39) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m36), &TYPE::m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m37), &TYPE::m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m38), &TYPE::m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m39), &TYPE::m39>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_41(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35), BOOST_HANA_PP_STRINGIZE(m36), BOOST_HANA_PP_STRINGIZE(m37), BOOST_HANA_PP_STRINGIZE(m38), BOOST_HANA_PP_STRINGIZE(m39), BOOST_HANA_PP_STRINGIZE(m40) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m36), &TYPE::m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m37), &TYPE::m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m38), &TYPE::m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m39), &TYPE::m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m40), &TYPE::m40>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_42(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35), BOOST_HANA_PP_STRINGIZE(m36), BOOST_HANA_PP_STRINGIZE(m37), BOOST_HANA_PP_STRINGIZE(m38), BOOST_HANA_PP_STRINGIZE(m39), BOOST_HANA_PP_STRINGIZE(m40), BOOST_HANA_PP_STRINGIZE(m41) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m36), &TYPE::m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m37), &TYPE::m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m38), &TYPE::m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m39), &TYPE::m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m40), &TYPE::m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m41), &TYPE::m41>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_43(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35), BOOST_HANA_PP_STRINGIZE(m36), BOOST_HANA_PP_STRINGIZE(m37), BOOST_HANA_PP_STRINGIZE(m38), BOOST_HANA_PP_STRINGIZE(m39), BOOST_HANA_PP_STRINGIZE(m40), BOOST_HANA_PP_STRINGIZE(m41), BOOST_HANA_PP_STRINGIZE(m42) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m36), &TYPE::m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m37), &TYPE::m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m38), &TYPE::m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m39), &TYPE::m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m40), &TYPE::m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m41), &TYPE::m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m42), &TYPE::m42>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_44(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35), BOOST_HANA_PP_STRINGIZE(m36), BOOST_HANA_PP_STRINGIZE(m37), BOOST_HANA_PP_STRINGIZE(m38), BOOST_HANA_PP_STRINGIZE(m39), BOOST_HANA_PP_STRINGIZE(m40), BOOST_HANA_PP_STRINGIZE(m41), BOOST_HANA_PP_STRINGIZE(m42), BOOST_HANA_PP_STRINGIZE(m43) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m36), &TYPE::m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m37), &TYPE::m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m38), &TYPE::m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m39), &TYPE::m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m40), &TYPE::m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m41), &TYPE::m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m42), &TYPE::m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m43), &TYPE::m43>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_45(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35), BOOST_HANA_PP_STRINGIZE(m36), BOOST_HANA_PP_STRINGIZE(m37), BOOST_HANA_PP_STRINGIZE(m38), BOOST_HANA_PP_STRINGIZE(m39), BOOST_HANA_PP_STRINGIZE(m40), BOOST_HANA_PP_STRINGIZE(m41), BOOST_HANA_PP_STRINGIZE(m42), BOOST_HANA_PP_STRINGIZE(m43), BOOST_HANA_PP_STRINGIZE(m44) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m36), &TYPE::m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m37), &TYPE::m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m38), &TYPE::m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m39), &TYPE::m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m40), &TYPE::m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m41), &TYPE::m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m42), &TYPE::m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m43), &TYPE::m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m44), &TYPE::m44>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_46(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35), BOOST_HANA_PP_STRINGIZE(m36), BOOST_HANA_PP_STRINGIZE(m37), BOOST_HANA_PP_STRINGIZE(m38), BOOST_HANA_PP_STRINGIZE(m39), BOOST_HANA_PP_STRINGIZE(m40), BOOST_HANA_PP_STRINGIZE(m41), BOOST_HANA_PP_STRINGIZE(m42), BOOST_HANA_PP_STRINGIZE(m43), BOOST_HANA_PP_STRINGIZE(m44), BOOST_HANA_PP_STRINGIZE(m45) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m36), &TYPE::m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m37), &TYPE::m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m38), &TYPE::m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m39), &TYPE::m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m40), &TYPE::m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m41), &TYPE::m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m42), &TYPE::m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m43), &TYPE::m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m44), &TYPE::m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m45), &TYPE::m45>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_47(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35), BOOST_HANA_PP_STRINGIZE(m36), BOOST_HANA_PP_STRINGIZE(m37), BOOST_HANA_PP_STRINGIZE(m38), BOOST_HANA_PP_STRINGIZE(m39), BOOST_HANA_PP_STRINGIZE(m40), BOOST_HANA_PP_STRINGIZE(m41), BOOST_HANA_PP_STRINGIZE(m42), BOOST_HANA_PP_STRINGIZE(m43), BOOST_HANA_PP_STRINGIZE(m44), BOOST_HANA_PP_STRINGIZE(m45), BOOST_HANA_PP_STRINGIZE(m46) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m36), &TYPE::m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m37), &TYPE::m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m38), &TYPE::m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m39), &TYPE::m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m40), &TYPE::m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m41), &TYPE::m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m42), &TYPE::m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m43), &TYPE::m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m44), &TYPE::m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m45), &TYPE::m45>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m46), &TYPE::m46>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_48(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35), BOOST_HANA_PP_STRINGIZE(m36), BOOST_HANA_PP_STRINGIZE(m37), BOOST_HANA_PP_STRINGIZE(m38), BOOST_HANA_PP_STRINGIZE(m39), BOOST_HANA_PP_STRINGIZE(m40), BOOST_HANA_PP_STRINGIZE(m41), BOOST_HANA_PP_STRINGIZE(m42), BOOST_HANA_PP_STRINGIZE(m43), BOOST_HANA_PP_STRINGIZE(m44), BOOST_HANA_PP_STRINGIZE(m45), BOOST_HANA_PP_STRINGIZE(m46), BOOST_HANA_PP_STRINGIZE(m47) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m36), &TYPE::m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m37), &TYPE::m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m38), &TYPE::m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m39), &TYPE::m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m40), &TYPE::m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m41), &TYPE::m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m42), &TYPE::m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m43), &TYPE::m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m44), &TYPE::m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m45), &TYPE::m45>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m46), &TYPE::m46>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m47), &TYPE::m47>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_49(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35), BOOST_HANA_PP_STRINGIZE(m36), BOOST_HANA_PP_STRINGIZE(m37), BOOST_HANA_PP_STRINGIZE(m38), BOOST_HANA_PP_STRINGIZE(m39), BOOST_HANA_PP_STRINGIZE(m40), BOOST_HANA_PP_STRINGIZE(m41), BOOST_HANA_PP_STRINGIZE(m42), BOOST_HANA_PP_STRINGIZE(m43), BOOST_HANA_PP_STRINGIZE(m44), BOOST_HANA_PP_STRINGIZE(m45), BOOST_HANA_PP_STRINGIZE(m46), BOOST_HANA_PP_STRINGIZE(m47), BOOST_HANA_PP_STRINGIZE(m48) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m36), &TYPE::m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m37), &TYPE::m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m38), &TYPE::m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m39), &TYPE::m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m40), &TYPE::m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m41), &TYPE::m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m42), &TYPE::m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m43), &TYPE::m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m44), &TYPE::m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m45), &TYPE::m45>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m46), &TYPE::m46>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m47), &TYPE::m47>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m48), &TYPE::m48>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_50(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35), BOOST_HANA_PP_STRINGIZE(m36), BOOST_HANA_PP_STRINGIZE(m37), BOOST_HANA_PP_STRINGIZE(m38), BOOST_HANA_PP_STRINGIZE(m39), BOOST_HANA_PP_STRINGIZE(m40), BOOST_HANA_PP_STRINGIZE(m41), BOOST_HANA_PP_STRINGIZE(m42), BOOST_HANA_PP_STRINGIZE(m43), BOOST_HANA_PP_STRINGIZE(m44), BOOST_HANA_PP_STRINGIZE(m45), BOOST_HANA_PP_STRINGIZE(m46), BOOST_HANA_PP_STRINGIZE(m47), BOOST_HANA_PP_STRINGIZE(m48), BOOST_HANA_PP_STRINGIZE(m49) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m36), &TYPE::m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m37), &TYPE::m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m38), &TYPE::m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m39), &TYPE::m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m40), &TYPE::m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m41), &TYPE::m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m42), &TYPE::m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m43), &TYPE::m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m44), &TYPE::m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m45), &TYPE::m45>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m46), &TYPE::m46>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m47), &TYPE::m47>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m48), &TYPE::m48>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m49), &TYPE::m49>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_51(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49, m50) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35), BOOST_HANA_PP_STRINGIZE(m36), BOOST_HANA_PP_STRINGIZE(m37), BOOST_HANA_PP_STRINGIZE(m38), BOOST_HANA_PP_STRINGIZE(m39), BOOST_HANA_PP_STRINGIZE(m40), BOOST_HANA_PP_STRINGIZE(m41), BOOST_HANA_PP_STRINGIZE(m42), BOOST_HANA_PP_STRINGIZE(m43), BOOST_HANA_PP_STRINGIZE(m44), BOOST_HANA_PP_STRINGIZE(m45), BOOST_HANA_PP_STRINGIZE(m46), BOOST_HANA_PP_STRINGIZE(m47), BOOST_HANA_PP_STRINGIZE(m48), BOOST_HANA_PP_STRINGIZE(m49), BOOST_HANA_PP_STRINGIZE(m50) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m36), &TYPE::m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m37), &TYPE::m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m38), &TYPE::m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m39), &TYPE::m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m40), &TYPE::m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m41), &TYPE::m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m42), &TYPE::m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m43), &TYPE::m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m44), &TYPE::m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m45), &TYPE::m45>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m46), &TYPE::m46>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m47), &TYPE::m47>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m48), &TYPE::m48>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m49), &TYPE::m49>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<49, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m50), &TYPE::m50>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_52(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49, m50, m51) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35), BOOST_HANA_PP_STRINGIZE(m36), BOOST_HANA_PP_STRINGIZE(m37), BOOST_HANA_PP_STRINGIZE(m38), BOOST_HANA_PP_STRINGIZE(m39), BOOST_HANA_PP_STRINGIZE(m40), BOOST_HANA_PP_STRINGIZE(m41), BOOST_HANA_PP_STRINGIZE(m42), BOOST_HANA_PP_STRINGIZE(m43), BOOST_HANA_PP_STRINGIZE(m44), BOOST_HANA_PP_STRINGIZE(m45), BOOST_HANA_PP_STRINGIZE(m46), BOOST_HANA_PP_STRINGIZE(m47), BOOST_HANA_PP_STRINGIZE(m48), BOOST_HANA_PP_STRINGIZE(m49), BOOST_HANA_PP_STRINGIZE(m50), BOOST_HANA_PP_STRINGIZE(m51) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m36), &TYPE::m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m37), &TYPE::m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m38), &TYPE::m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m39), &TYPE::m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m40), &TYPE::m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m41), &TYPE::m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m42), &TYPE::m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m43), &TYPE::m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m44), &TYPE::m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m45), &TYPE::m45>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m46), &TYPE::m46>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m47), &TYPE::m47>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m48), &TYPE::m48>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m49), &TYPE::m49>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<49, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m50), &TYPE::m50>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<50, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m51), &TYPE::m51>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_53(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49, m50, m51, m52) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35), BOOST_HANA_PP_STRINGIZE(m36), BOOST_HANA_PP_STRINGIZE(m37), BOOST_HANA_PP_STRINGIZE(m38), BOOST_HANA_PP_STRINGIZE(m39), BOOST_HANA_PP_STRINGIZE(m40), BOOST_HANA_PP_STRINGIZE(m41), BOOST_HANA_PP_STRINGIZE(m42), BOOST_HANA_PP_STRINGIZE(m43), BOOST_HANA_PP_STRINGIZE(m44), BOOST_HANA_PP_STRINGIZE(m45), BOOST_HANA_PP_STRINGIZE(m46), BOOST_HANA_PP_STRINGIZE(m47), BOOST_HANA_PP_STRINGIZE(m48), BOOST_HANA_PP_STRINGIZE(m49), BOOST_HANA_PP_STRINGIZE(m50), BOOST_HANA_PP_STRINGIZE(m51), BOOST_HANA_PP_STRINGIZE(m52) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m36), &TYPE::m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m37), &TYPE::m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m38), &TYPE::m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m39), &TYPE::m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m40), &TYPE::m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m41), &TYPE::m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m42), &TYPE::m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m43), &TYPE::m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m44), &TYPE::m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m45), &TYPE::m45>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m46), &TYPE::m46>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m47), &TYPE::m47>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m48), &TYPE::m48>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m49), &TYPE::m49>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<49, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m50), &TYPE::m50>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<50, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m51), &TYPE::m51>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<51, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m52), &TYPE::m52>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_54(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49, m50, m51, m52, m53) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35), BOOST_HANA_PP_STRINGIZE(m36), BOOST_HANA_PP_STRINGIZE(m37), BOOST_HANA_PP_STRINGIZE(m38), BOOST_HANA_PP_STRINGIZE(m39), BOOST_HANA_PP_STRINGIZE(m40), BOOST_HANA_PP_STRINGIZE(m41), BOOST_HANA_PP_STRINGIZE(m42), BOOST_HANA_PP_STRINGIZE(m43), BOOST_HANA_PP_STRINGIZE(m44), BOOST_HANA_PP_STRINGIZE(m45), BOOST_HANA_PP_STRINGIZE(m46), BOOST_HANA_PP_STRINGIZE(m47), BOOST_HANA_PP_STRINGIZE(m48), BOOST_HANA_PP_STRINGIZE(m49), BOOST_HANA_PP_STRINGIZE(m50), BOOST_HANA_PP_STRINGIZE(m51), BOOST_HANA_PP_STRINGIZE(m52), BOOST_HANA_PP_STRINGIZE(m53) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m36), &TYPE::m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m37), &TYPE::m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m38), &TYPE::m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m39), &TYPE::m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m40), &TYPE::m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m41), &TYPE::m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m42), &TYPE::m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m43), &TYPE::m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m44), &TYPE::m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m45), &TYPE::m45>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m46), &TYPE::m46>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m47), &TYPE::m47>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m48), &TYPE::m48>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m49), &TYPE::m49>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<49, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m50), &TYPE::m50>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<50, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m51), &TYPE::m51>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<51, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m52), &TYPE::m52>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<52, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m53), &TYPE::m53>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_55(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49, m50, m51, m52, m53, m54) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35), BOOST_HANA_PP_STRINGIZE(m36), BOOST_HANA_PP_STRINGIZE(m37), BOOST_HANA_PP_STRINGIZE(m38), BOOST_HANA_PP_STRINGIZE(m39), BOOST_HANA_PP_STRINGIZE(m40), BOOST_HANA_PP_STRINGIZE(m41), BOOST_HANA_PP_STRINGIZE(m42), BOOST_HANA_PP_STRINGIZE(m43), BOOST_HANA_PP_STRINGIZE(m44), BOOST_HANA_PP_STRINGIZE(m45), BOOST_HANA_PP_STRINGIZE(m46), BOOST_HANA_PP_STRINGIZE(m47), BOOST_HANA_PP_STRINGIZE(m48), BOOST_HANA_PP_STRINGIZE(m49), BOOST_HANA_PP_STRINGIZE(m50), BOOST_HANA_PP_STRINGIZE(m51), BOOST_HANA_PP_STRINGIZE(m52), BOOST_HANA_PP_STRINGIZE(m53), BOOST_HANA_PP_STRINGIZE(m54) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m36), &TYPE::m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m37), &TYPE::m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m38), &TYPE::m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m39), &TYPE::m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m40), &TYPE::m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m41), &TYPE::m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m42), &TYPE::m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m43), &TYPE::m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m44), &TYPE::m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m45), &TYPE::m45>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m46), &TYPE::m46>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m47), &TYPE::m47>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m48), &TYPE::m48>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m49), &TYPE::m49>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<49, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m50), &TYPE::m50>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<50, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m51), &TYPE::m51>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<51, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m52), &TYPE::m52>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<52, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m53), &TYPE::m53>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<53, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m54), &TYPE::m54>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_STRUCT_IMPL_56(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49, m50, m51, m52, m53, m54, m55) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(m1), BOOST_HANA_PP_STRINGIZE(m2), BOOST_HANA_PP_STRINGIZE(m3), BOOST_HANA_PP_STRINGIZE(m4), BOOST_HANA_PP_STRINGIZE(m5), BOOST_HANA_PP_STRINGIZE(m6), BOOST_HANA_PP_STRINGIZE(m7), BOOST_HANA_PP_STRINGIZE(m8), BOOST_HANA_PP_STRINGIZE(m9), BOOST_HANA_PP_STRINGIZE(m10), BOOST_HANA_PP_STRINGIZE(m11), BOOST_HANA_PP_STRINGIZE(m12), BOOST_HANA_PP_STRINGIZE(m13), BOOST_HANA_PP_STRINGIZE(m14), BOOST_HANA_PP_STRINGIZE(m15), BOOST_HANA_PP_STRINGIZE(m16), BOOST_HANA_PP_STRINGIZE(m17), BOOST_HANA_PP_STRINGIZE(m18), BOOST_HANA_PP_STRINGIZE(m19), BOOST_HANA_PP_STRINGIZE(m20), BOOST_HANA_PP_STRINGIZE(m21), BOOST_HANA_PP_STRINGIZE(m22), BOOST_HANA_PP_STRINGIZE(m23), BOOST_HANA_PP_STRINGIZE(m24), BOOST_HANA_PP_STRINGIZE(m25), BOOST_HANA_PP_STRINGIZE(m26), BOOST_HANA_PP_STRINGIZE(m27), BOOST_HANA_PP_STRINGIZE(m28), BOOST_HANA_PP_STRINGIZE(m29), BOOST_HANA_PP_STRINGIZE(m30), BOOST_HANA_PP_STRINGIZE(m31), BOOST_HANA_PP_STRINGIZE(m32), BOOST_HANA_PP_STRINGIZE(m33), BOOST_HANA_PP_STRINGIZE(m34), BOOST_HANA_PP_STRINGIZE(m35), BOOST_HANA_PP_STRINGIZE(m36), BOOST_HANA_PP_STRINGIZE(m37), BOOST_HANA_PP_STRINGIZE(m38), BOOST_HANA_PP_STRINGIZE(m39), BOOST_HANA_PP_STRINGIZE(m40), BOOST_HANA_PP_STRINGIZE(m41), BOOST_HANA_PP_STRINGIZE(m42), BOOST_HANA_PP_STRINGIZE(m43), BOOST_HANA_PP_STRINGIZE(m44), BOOST_HANA_PP_STRINGIZE(m45), BOOST_HANA_PP_STRINGIZE(m46), BOOST_HANA_PP_STRINGIZE(m47), BOOST_HANA_PP_STRINGIZE(m48), BOOST_HANA_PP_STRINGIZE(m49), BOOST_HANA_PP_STRINGIZE(m50), BOOST_HANA_PP_STRINGIZE(m51), BOOST_HANA_PP_STRINGIZE(m52), BOOST_HANA_PP_STRINGIZE(m53), BOOST_HANA_PP_STRINGIZE(m54), BOOST_HANA_PP_STRINGIZE(m55) \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m1), &TYPE::m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m2), &TYPE::m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m3), &TYPE::m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m4), &TYPE::m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m5), &TYPE::m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m6), &TYPE::m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m7), &TYPE::m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m8), &TYPE::m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m9), &TYPE::m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m10), &TYPE::m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m11), &TYPE::m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m12), &TYPE::m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m13), &TYPE::m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m14), &TYPE::m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m15), &TYPE::m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m16), &TYPE::m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m17), &TYPE::m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m18), &TYPE::m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m19), &TYPE::m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m20), &TYPE::m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m21), &TYPE::m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m22), &TYPE::m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m23), &TYPE::m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m24), &TYPE::m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m25), &TYPE::m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m26), &TYPE::m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m27), &TYPE::m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m28), &TYPE::m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m29), &TYPE::m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m30), &TYPE::m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m31), &TYPE::m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m32), &TYPE::m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m33), &TYPE::m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m34), &TYPE::m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m35), &TYPE::m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m36), &TYPE::m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m37), &TYPE::m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m38), &TYPE::m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m39), &TYPE::m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m40), &TYPE::m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m41), &TYPE::m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m42), &TYPE::m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m43), &TYPE::m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m44), &TYPE::m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m45), &TYPE::m45>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m46), &TYPE::m46>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m47), &TYPE::m47>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m48), &TYPE::m48>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m49), &TYPE::m49>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<49, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m50), &TYPE::m50>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<50, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m51), &TYPE::m51>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<51, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m52), &TYPE::m52>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<52, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m53), &TYPE::m53>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<53, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m54), &TYPE::m54>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<54, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m55), &TYPE::m55>{})\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+
+//////////////////////////////////////////////////////////////////////////////
+// BOOST_HANA_ADAPT_ADT
+//////////////////////////////////////////////////////////////////////////////
+template <typename ...>
+struct BOOST_HANA_ADAPT_ADT_must_be_called_in_the_global_namespace;
+
+#define BOOST_HANA_ADAPT_ADT(...) \
+ template <> \
+ struct BOOST_HANA_ADAPT_ADT_must_be_called_in_the_global_namespace<>; \
+ BOOST_HANA_ADAPT_ADT_IMPL(BOOST_HANA_PP_NARG(__VA_ARGS__), __VA_ARGS__) \
+ static_assert(true, "force the usage of a trailing semicolon") \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL(N, ...) \
+ BOOST_HANA_PP_CONCAT(BOOST_HANA_ADAPT_ADT_IMPL_, N)(__VA_ARGS__)
+
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_1(TYPE ) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ \
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_2(TYPE , m1) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_3(TYPE , m1, m2) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_4(TYPE , m1, m2, m3) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_5(TYPE , m1, m2, m3, m4) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_6(TYPE , m1, m2, m3, m4, m5) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_7(TYPE , m1, m2, m3, m4, m5, m6) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_8(TYPE , m1, m2, m3, m4, m5, m6, m7) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_9(TYPE , m1, m2, m3, m4, m5, m6, m7, m8) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_10(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_11(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_12(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_13(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_14(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_15(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_16(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_17(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_18(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_19(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_20(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_21(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_22(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_23(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_24(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_25(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_26(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_27(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_28(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_29(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_30(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_31(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_32(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_33(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_34(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_35(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_36(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_37(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m36)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), BOOST_HANA_PP_DROP_FRONT m36)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_38(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m37)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), BOOST_HANA_PP_DROP_FRONT m36), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), BOOST_HANA_PP_DROP_FRONT m37)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_39(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m38)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), BOOST_HANA_PP_DROP_FRONT m36), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), BOOST_HANA_PP_DROP_FRONT m37), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), BOOST_HANA_PP_DROP_FRONT m38)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_40(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m39)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), BOOST_HANA_PP_DROP_FRONT m36), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), BOOST_HANA_PP_DROP_FRONT m37), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), BOOST_HANA_PP_DROP_FRONT m38), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), BOOST_HANA_PP_DROP_FRONT m39)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_41(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m40)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), BOOST_HANA_PP_DROP_FRONT m36), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), BOOST_HANA_PP_DROP_FRONT m37), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), BOOST_HANA_PP_DROP_FRONT m38), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), BOOST_HANA_PP_DROP_FRONT m39), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), BOOST_HANA_PP_DROP_FRONT m40)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_42(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m41)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), BOOST_HANA_PP_DROP_FRONT m36), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), BOOST_HANA_PP_DROP_FRONT m37), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), BOOST_HANA_PP_DROP_FRONT m38), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), BOOST_HANA_PP_DROP_FRONT m39), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), BOOST_HANA_PP_DROP_FRONT m40), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), BOOST_HANA_PP_DROP_FRONT m41)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_43(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m42)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), BOOST_HANA_PP_DROP_FRONT m36), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), BOOST_HANA_PP_DROP_FRONT m37), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), BOOST_HANA_PP_DROP_FRONT m38), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), BOOST_HANA_PP_DROP_FRONT m39), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), BOOST_HANA_PP_DROP_FRONT m40), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), BOOST_HANA_PP_DROP_FRONT m41), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), BOOST_HANA_PP_DROP_FRONT m42)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_44(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m43)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), BOOST_HANA_PP_DROP_FRONT m36), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), BOOST_HANA_PP_DROP_FRONT m37), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), BOOST_HANA_PP_DROP_FRONT m38), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), BOOST_HANA_PP_DROP_FRONT m39), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), BOOST_HANA_PP_DROP_FRONT m40), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), BOOST_HANA_PP_DROP_FRONT m41), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), BOOST_HANA_PP_DROP_FRONT m42), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), BOOST_HANA_PP_DROP_FRONT m43)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_45(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m44)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), BOOST_HANA_PP_DROP_FRONT m36), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), BOOST_HANA_PP_DROP_FRONT m37), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), BOOST_HANA_PP_DROP_FRONT m38), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), BOOST_HANA_PP_DROP_FRONT m39), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), BOOST_HANA_PP_DROP_FRONT m40), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), BOOST_HANA_PP_DROP_FRONT m41), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), BOOST_HANA_PP_DROP_FRONT m42), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), BOOST_HANA_PP_DROP_FRONT m43), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), BOOST_HANA_PP_DROP_FRONT m44)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_46(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m45)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), BOOST_HANA_PP_DROP_FRONT m36), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), BOOST_HANA_PP_DROP_FRONT m37), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), BOOST_HANA_PP_DROP_FRONT m38), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), BOOST_HANA_PP_DROP_FRONT m39), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), BOOST_HANA_PP_DROP_FRONT m40), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), BOOST_HANA_PP_DROP_FRONT m41), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), BOOST_HANA_PP_DROP_FRONT m42), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), BOOST_HANA_PP_DROP_FRONT m43), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), BOOST_HANA_PP_DROP_FRONT m44), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), BOOST_HANA_PP_DROP_FRONT m45)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_47(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m45), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m46)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), BOOST_HANA_PP_DROP_FRONT m36), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), BOOST_HANA_PP_DROP_FRONT m37), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), BOOST_HANA_PP_DROP_FRONT m38), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), BOOST_HANA_PP_DROP_FRONT m39), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), BOOST_HANA_PP_DROP_FRONT m40), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), BOOST_HANA_PP_DROP_FRONT m41), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), BOOST_HANA_PP_DROP_FRONT m42), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), BOOST_HANA_PP_DROP_FRONT m43), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), BOOST_HANA_PP_DROP_FRONT m44), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), BOOST_HANA_PP_DROP_FRONT m45), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), BOOST_HANA_PP_DROP_FRONT m46)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_48(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m45), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m46), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m47)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), BOOST_HANA_PP_DROP_FRONT m36), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), BOOST_HANA_PP_DROP_FRONT m37), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), BOOST_HANA_PP_DROP_FRONT m38), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), BOOST_HANA_PP_DROP_FRONT m39), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), BOOST_HANA_PP_DROP_FRONT m40), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), BOOST_HANA_PP_DROP_FRONT m41), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), BOOST_HANA_PP_DROP_FRONT m42), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), BOOST_HANA_PP_DROP_FRONT m43), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), BOOST_HANA_PP_DROP_FRONT m44), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), BOOST_HANA_PP_DROP_FRONT m45), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), BOOST_HANA_PP_DROP_FRONT m46), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), BOOST_HANA_PP_DROP_FRONT m47)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_49(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m45), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m46), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m47), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m48)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), BOOST_HANA_PP_DROP_FRONT m36), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), BOOST_HANA_PP_DROP_FRONT m37), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), BOOST_HANA_PP_DROP_FRONT m38), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), BOOST_HANA_PP_DROP_FRONT m39), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), BOOST_HANA_PP_DROP_FRONT m40), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), BOOST_HANA_PP_DROP_FRONT m41), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), BOOST_HANA_PP_DROP_FRONT m42), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), BOOST_HANA_PP_DROP_FRONT m43), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), BOOST_HANA_PP_DROP_FRONT m44), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), BOOST_HANA_PP_DROP_FRONT m45), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), BOOST_HANA_PP_DROP_FRONT m46), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), BOOST_HANA_PP_DROP_FRONT m47), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), BOOST_HANA_PP_DROP_FRONT m48)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_50(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m45), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m46), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m47), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m48), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m49)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), BOOST_HANA_PP_DROP_FRONT m36), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), BOOST_HANA_PP_DROP_FRONT m37), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), BOOST_HANA_PP_DROP_FRONT m38), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), BOOST_HANA_PP_DROP_FRONT m39), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), BOOST_HANA_PP_DROP_FRONT m40), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), BOOST_HANA_PP_DROP_FRONT m41), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), BOOST_HANA_PP_DROP_FRONT m42), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), BOOST_HANA_PP_DROP_FRONT m43), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), BOOST_HANA_PP_DROP_FRONT m44), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), BOOST_HANA_PP_DROP_FRONT m45), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), BOOST_HANA_PP_DROP_FRONT m46), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), BOOST_HANA_PP_DROP_FRONT m47), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), BOOST_HANA_PP_DROP_FRONT m48), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), BOOST_HANA_PP_DROP_FRONT m49)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_51(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49, m50) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m45), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m46), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m47), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m48), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m49), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m50)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), BOOST_HANA_PP_DROP_FRONT m36), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), BOOST_HANA_PP_DROP_FRONT m37), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), BOOST_HANA_PP_DROP_FRONT m38), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), BOOST_HANA_PP_DROP_FRONT m39), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), BOOST_HANA_PP_DROP_FRONT m40), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), BOOST_HANA_PP_DROP_FRONT m41), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), BOOST_HANA_PP_DROP_FRONT m42), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), BOOST_HANA_PP_DROP_FRONT m43), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), BOOST_HANA_PP_DROP_FRONT m44), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), BOOST_HANA_PP_DROP_FRONT m45), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), BOOST_HANA_PP_DROP_FRONT m46), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), BOOST_HANA_PP_DROP_FRONT m47), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), BOOST_HANA_PP_DROP_FRONT m48), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), BOOST_HANA_PP_DROP_FRONT m49), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<49, member_names>(), BOOST_HANA_PP_DROP_FRONT m50)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_52(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49, m50, m51) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m45), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m46), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m47), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m48), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m49), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m50), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m51)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), BOOST_HANA_PP_DROP_FRONT m36), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), BOOST_HANA_PP_DROP_FRONT m37), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), BOOST_HANA_PP_DROP_FRONT m38), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), BOOST_HANA_PP_DROP_FRONT m39), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), BOOST_HANA_PP_DROP_FRONT m40), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), BOOST_HANA_PP_DROP_FRONT m41), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), BOOST_HANA_PP_DROP_FRONT m42), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), BOOST_HANA_PP_DROP_FRONT m43), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), BOOST_HANA_PP_DROP_FRONT m44), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), BOOST_HANA_PP_DROP_FRONT m45), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), BOOST_HANA_PP_DROP_FRONT m46), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), BOOST_HANA_PP_DROP_FRONT m47), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), BOOST_HANA_PP_DROP_FRONT m48), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), BOOST_HANA_PP_DROP_FRONT m49), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<49, member_names>(), BOOST_HANA_PP_DROP_FRONT m50), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<50, member_names>(), BOOST_HANA_PP_DROP_FRONT m51)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_53(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49, m50, m51, m52) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m45), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m46), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m47), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m48), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m49), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m50), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m51), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m52)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), BOOST_HANA_PP_DROP_FRONT m36), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), BOOST_HANA_PP_DROP_FRONT m37), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), BOOST_HANA_PP_DROP_FRONT m38), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), BOOST_HANA_PP_DROP_FRONT m39), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), BOOST_HANA_PP_DROP_FRONT m40), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), BOOST_HANA_PP_DROP_FRONT m41), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), BOOST_HANA_PP_DROP_FRONT m42), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), BOOST_HANA_PP_DROP_FRONT m43), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), BOOST_HANA_PP_DROP_FRONT m44), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), BOOST_HANA_PP_DROP_FRONT m45), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), BOOST_HANA_PP_DROP_FRONT m46), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), BOOST_HANA_PP_DROP_FRONT m47), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), BOOST_HANA_PP_DROP_FRONT m48), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), BOOST_HANA_PP_DROP_FRONT m49), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<49, member_names>(), BOOST_HANA_PP_DROP_FRONT m50), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<50, member_names>(), BOOST_HANA_PP_DROP_FRONT m51), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<51, member_names>(), BOOST_HANA_PP_DROP_FRONT m52)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_54(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49, m50, m51, m52, m53) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m45), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m46), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m47), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m48), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m49), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m50), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m51), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m52), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m53)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), BOOST_HANA_PP_DROP_FRONT m36), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), BOOST_HANA_PP_DROP_FRONT m37), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), BOOST_HANA_PP_DROP_FRONT m38), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), BOOST_HANA_PP_DROP_FRONT m39), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), BOOST_HANA_PP_DROP_FRONT m40), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), BOOST_HANA_PP_DROP_FRONT m41), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), BOOST_HANA_PP_DROP_FRONT m42), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), BOOST_HANA_PP_DROP_FRONT m43), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), BOOST_HANA_PP_DROP_FRONT m44), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), BOOST_HANA_PP_DROP_FRONT m45), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), BOOST_HANA_PP_DROP_FRONT m46), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), BOOST_HANA_PP_DROP_FRONT m47), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), BOOST_HANA_PP_DROP_FRONT m48), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), BOOST_HANA_PP_DROP_FRONT m49), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<49, member_names>(), BOOST_HANA_PP_DROP_FRONT m50), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<50, member_names>(), BOOST_HANA_PP_DROP_FRONT m51), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<51, member_names>(), BOOST_HANA_PP_DROP_FRONT m52), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<52, member_names>(), BOOST_HANA_PP_DROP_FRONT m53)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_55(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49, m50, m51, m52, m53, m54) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m45), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m46), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m47), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m48), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m49), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m50), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m51), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m52), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m53), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m54)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), BOOST_HANA_PP_DROP_FRONT m36), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), BOOST_HANA_PP_DROP_FRONT m37), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), BOOST_HANA_PP_DROP_FRONT m38), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), BOOST_HANA_PP_DROP_FRONT m39), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), BOOST_HANA_PP_DROP_FRONT m40), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), BOOST_HANA_PP_DROP_FRONT m41), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), BOOST_HANA_PP_DROP_FRONT m42), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), BOOST_HANA_PP_DROP_FRONT m43), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), BOOST_HANA_PP_DROP_FRONT m44), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), BOOST_HANA_PP_DROP_FRONT m45), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), BOOST_HANA_PP_DROP_FRONT m46), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), BOOST_HANA_PP_DROP_FRONT m47), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), BOOST_HANA_PP_DROP_FRONT m48), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), BOOST_HANA_PP_DROP_FRONT m49), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<49, member_names>(), BOOST_HANA_PP_DROP_FRONT m50), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<50, member_names>(), BOOST_HANA_PP_DROP_FRONT m51), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<51, member_names>(), BOOST_HANA_PP_DROP_FRONT m52), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<52, member_names>(), BOOST_HANA_PP_DROP_FRONT m53), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<53, member_names>(), BOOST_HANA_PP_DROP_FRONT m54)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+#define BOOST_HANA_ADAPT_ADT_IMPL_56(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49, m50, m51, m52, m53, m54, m55) \
+ namespace boost { namespace hana { \
+ template <> \
+ struct accessors_impl<TYPE> { \
+ template <typename ...> \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m45), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m46), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m47), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m48), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m49), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m50), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m51), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m52), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m53), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m54), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m55)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), BOOST_HANA_PP_DROP_FRONT m1), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), BOOST_HANA_PP_DROP_FRONT m2), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), BOOST_HANA_PP_DROP_FRONT m3), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), BOOST_HANA_PP_DROP_FRONT m4), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), BOOST_HANA_PP_DROP_FRONT m5), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), BOOST_HANA_PP_DROP_FRONT m6), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), BOOST_HANA_PP_DROP_FRONT m7), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), BOOST_HANA_PP_DROP_FRONT m8), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), BOOST_HANA_PP_DROP_FRONT m9), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), BOOST_HANA_PP_DROP_FRONT m10), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), BOOST_HANA_PP_DROP_FRONT m11), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), BOOST_HANA_PP_DROP_FRONT m12), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), BOOST_HANA_PP_DROP_FRONT m13), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), BOOST_HANA_PP_DROP_FRONT m14), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), BOOST_HANA_PP_DROP_FRONT m15), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), BOOST_HANA_PP_DROP_FRONT m16), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), BOOST_HANA_PP_DROP_FRONT m17), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), BOOST_HANA_PP_DROP_FRONT m18), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), BOOST_HANA_PP_DROP_FRONT m19), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), BOOST_HANA_PP_DROP_FRONT m20), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), BOOST_HANA_PP_DROP_FRONT m21), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), BOOST_HANA_PP_DROP_FRONT m22), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), BOOST_HANA_PP_DROP_FRONT m23), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), BOOST_HANA_PP_DROP_FRONT m24), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), BOOST_HANA_PP_DROP_FRONT m25), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), BOOST_HANA_PP_DROP_FRONT m26), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), BOOST_HANA_PP_DROP_FRONT m27), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), BOOST_HANA_PP_DROP_FRONT m28), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), BOOST_HANA_PP_DROP_FRONT m29), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), BOOST_HANA_PP_DROP_FRONT m30), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), BOOST_HANA_PP_DROP_FRONT m31), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), BOOST_HANA_PP_DROP_FRONT m32), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), BOOST_HANA_PP_DROP_FRONT m33), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), BOOST_HANA_PP_DROP_FRONT m34), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), BOOST_HANA_PP_DROP_FRONT m35), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), BOOST_HANA_PP_DROP_FRONT m36), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), BOOST_HANA_PP_DROP_FRONT m37), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), BOOST_HANA_PP_DROP_FRONT m38), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), BOOST_HANA_PP_DROP_FRONT m39), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), BOOST_HANA_PP_DROP_FRONT m40), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), BOOST_HANA_PP_DROP_FRONT m41), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), BOOST_HANA_PP_DROP_FRONT m42), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), BOOST_HANA_PP_DROP_FRONT m43), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), BOOST_HANA_PP_DROP_FRONT m44), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), BOOST_HANA_PP_DROP_FRONT m45), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), BOOST_HANA_PP_DROP_FRONT m46), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), BOOST_HANA_PP_DROP_FRONT m47), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), BOOST_HANA_PP_DROP_FRONT m48), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), BOOST_HANA_PP_DROP_FRONT m49), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<49, member_names>(), BOOST_HANA_PP_DROP_FRONT m50), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<50, member_names>(), BOOST_HANA_PP_DROP_FRONT m51), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<51, member_names>(), BOOST_HANA_PP_DROP_FRONT m52), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<52, member_names>(), BOOST_HANA_PP_DROP_FRONT m53), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<53, member_names>(), BOOST_HANA_PP_DROP_FRONT m54), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<54, member_names>(), BOOST_HANA_PP_DROP_FRONT m55)\
+ ); \
+ } \
+ }; \
+ }} \
+/**/
+
+
+//////////////////////////////////////////////////////////////////////////////
+// BOOST_HANA_DEFINE_STRUCT
+//////////////////////////////////////////////////////////////////////////////
+#define BOOST_HANA_DEFINE_STRUCT(...) \
+ BOOST_HANA_DEFINE_STRUCT_IMPL(BOOST_HANA_PP_NARG(__VA_ARGS__), __VA_ARGS__)
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL(N, ...) \
+ BOOST_HANA_PP_CONCAT(BOOST_HANA_DEFINE_STRUCT_IMPL_, N)(__VA_ARGS__)
+
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_1(TYPE ) \
+ \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ \
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ \
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_2(TYPE , m1) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_3(TYPE , m1, m2) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_4(TYPE , m1, m2, m3) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_5(TYPE , m1, m2, m3, m4) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_6(TYPE , m1, m2, m3, m4, m5) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_7(TYPE , m1, m2, m3, m4, m5, m6) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_8(TYPE , m1, m2, m3, m4, m5, m6, m7) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_9(TYPE , m1, m2, m3, m4, m5, m6, m7, m8) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_10(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_11(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_12(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_13(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_14(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_15(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_16(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_17(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_18(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_19(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_20(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_21(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_22(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_23(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_24(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_25(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_26(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_27(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_28(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_29(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_30(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_31(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_32(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_33(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_34(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_35(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_36(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_37(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; BOOST_HANA_PP_DROP_BACK m36 BOOST_HANA_PP_BACK m36; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m36)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m36), &TYPE::BOOST_HANA_PP_BACK m36>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_38(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; BOOST_HANA_PP_DROP_BACK m36 BOOST_HANA_PP_BACK m36; BOOST_HANA_PP_DROP_BACK m37 BOOST_HANA_PP_BACK m37; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m37)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m36), &TYPE::BOOST_HANA_PP_BACK m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m37), &TYPE::BOOST_HANA_PP_BACK m37>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_39(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; BOOST_HANA_PP_DROP_BACK m36 BOOST_HANA_PP_BACK m36; BOOST_HANA_PP_DROP_BACK m37 BOOST_HANA_PP_BACK m37; BOOST_HANA_PP_DROP_BACK m38 BOOST_HANA_PP_BACK m38; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m38)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m36), &TYPE::BOOST_HANA_PP_BACK m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m37), &TYPE::BOOST_HANA_PP_BACK m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m38), &TYPE::BOOST_HANA_PP_BACK m38>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_40(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; BOOST_HANA_PP_DROP_BACK m36 BOOST_HANA_PP_BACK m36; BOOST_HANA_PP_DROP_BACK m37 BOOST_HANA_PP_BACK m37; BOOST_HANA_PP_DROP_BACK m38 BOOST_HANA_PP_BACK m38; BOOST_HANA_PP_DROP_BACK m39 BOOST_HANA_PP_BACK m39; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m39)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m36), &TYPE::BOOST_HANA_PP_BACK m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m37), &TYPE::BOOST_HANA_PP_BACK m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m38), &TYPE::BOOST_HANA_PP_BACK m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m39), &TYPE::BOOST_HANA_PP_BACK m39>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_41(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; BOOST_HANA_PP_DROP_BACK m36 BOOST_HANA_PP_BACK m36; BOOST_HANA_PP_DROP_BACK m37 BOOST_HANA_PP_BACK m37; BOOST_HANA_PP_DROP_BACK m38 BOOST_HANA_PP_BACK m38; BOOST_HANA_PP_DROP_BACK m39 BOOST_HANA_PP_BACK m39; BOOST_HANA_PP_DROP_BACK m40 BOOST_HANA_PP_BACK m40; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m40)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m36), &TYPE::BOOST_HANA_PP_BACK m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m37), &TYPE::BOOST_HANA_PP_BACK m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m38), &TYPE::BOOST_HANA_PP_BACK m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m39), &TYPE::BOOST_HANA_PP_BACK m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m40), &TYPE::BOOST_HANA_PP_BACK m40>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_42(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; BOOST_HANA_PP_DROP_BACK m36 BOOST_HANA_PP_BACK m36; BOOST_HANA_PP_DROP_BACK m37 BOOST_HANA_PP_BACK m37; BOOST_HANA_PP_DROP_BACK m38 BOOST_HANA_PP_BACK m38; BOOST_HANA_PP_DROP_BACK m39 BOOST_HANA_PP_BACK m39; BOOST_HANA_PP_DROP_BACK m40 BOOST_HANA_PP_BACK m40; BOOST_HANA_PP_DROP_BACK m41 BOOST_HANA_PP_BACK m41; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m41)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m36), &TYPE::BOOST_HANA_PP_BACK m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m37), &TYPE::BOOST_HANA_PP_BACK m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m38), &TYPE::BOOST_HANA_PP_BACK m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m39), &TYPE::BOOST_HANA_PP_BACK m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m40), &TYPE::BOOST_HANA_PP_BACK m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m41), &TYPE::BOOST_HANA_PP_BACK m41>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_43(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; BOOST_HANA_PP_DROP_BACK m36 BOOST_HANA_PP_BACK m36; BOOST_HANA_PP_DROP_BACK m37 BOOST_HANA_PP_BACK m37; BOOST_HANA_PP_DROP_BACK m38 BOOST_HANA_PP_BACK m38; BOOST_HANA_PP_DROP_BACK m39 BOOST_HANA_PP_BACK m39; BOOST_HANA_PP_DROP_BACK m40 BOOST_HANA_PP_BACK m40; BOOST_HANA_PP_DROP_BACK m41 BOOST_HANA_PP_BACK m41; BOOST_HANA_PP_DROP_BACK m42 BOOST_HANA_PP_BACK m42; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m42)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m36), &TYPE::BOOST_HANA_PP_BACK m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m37), &TYPE::BOOST_HANA_PP_BACK m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m38), &TYPE::BOOST_HANA_PP_BACK m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m39), &TYPE::BOOST_HANA_PP_BACK m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m40), &TYPE::BOOST_HANA_PP_BACK m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m41), &TYPE::BOOST_HANA_PP_BACK m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m42), &TYPE::BOOST_HANA_PP_BACK m42>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_44(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; BOOST_HANA_PP_DROP_BACK m36 BOOST_HANA_PP_BACK m36; BOOST_HANA_PP_DROP_BACK m37 BOOST_HANA_PP_BACK m37; BOOST_HANA_PP_DROP_BACK m38 BOOST_HANA_PP_BACK m38; BOOST_HANA_PP_DROP_BACK m39 BOOST_HANA_PP_BACK m39; BOOST_HANA_PP_DROP_BACK m40 BOOST_HANA_PP_BACK m40; BOOST_HANA_PP_DROP_BACK m41 BOOST_HANA_PP_BACK m41; BOOST_HANA_PP_DROP_BACK m42 BOOST_HANA_PP_BACK m42; BOOST_HANA_PP_DROP_BACK m43 BOOST_HANA_PP_BACK m43; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m43)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m36), &TYPE::BOOST_HANA_PP_BACK m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m37), &TYPE::BOOST_HANA_PP_BACK m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m38), &TYPE::BOOST_HANA_PP_BACK m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m39), &TYPE::BOOST_HANA_PP_BACK m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m40), &TYPE::BOOST_HANA_PP_BACK m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m41), &TYPE::BOOST_HANA_PP_BACK m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m42), &TYPE::BOOST_HANA_PP_BACK m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m43), &TYPE::BOOST_HANA_PP_BACK m43>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_45(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; BOOST_HANA_PP_DROP_BACK m36 BOOST_HANA_PP_BACK m36; BOOST_HANA_PP_DROP_BACK m37 BOOST_HANA_PP_BACK m37; BOOST_HANA_PP_DROP_BACK m38 BOOST_HANA_PP_BACK m38; BOOST_HANA_PP_DROP_BACK m39 BOOST_HANA_PP_BACK m39; BOOST_HANA_PP_DROP_BACK m40 BOOST_HANA_PP_BACK m40; BOOST_HANA_PP_DROP_BACK m41 BOOST_HANA_PP_BACK m41; BOOST_HANA_PP_DROP_BACK m42 BOOST_HANA_PP_BACK m42; BOOST_HANA_PP_DROP_BACK m43 BOOST_HANA_PP_BACK m43; BOOST_HANA_PP_DROP_BACK m44 BOOST_HANA_PP_BACK m44; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m44)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m36), &TYPE::BOOST_HANA_PP_BACK m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m37), &TYPE::BOOST_HANA_PP_BACK m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m38), &TYPE::BOOST_HANA_PP_BACK m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m39), &TYPE::BOOST_HANA_PP_BACK m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m40), &TYPE::BOOST_HANA_PP_BACK m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m41), &TYPE::BOOST_HANA_PP_BACK m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m42), &TYPE::BOOST_HANA_PP_BACK m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m43), &TYPE::BOOST_HANA_PP_BACK m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m44), &TYPE::BOOST_HANA_PP_BACK m44>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_46(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; BOOST_HANA_PP_DROP_BACK m36 BOOST_HANA_PP_BACK m36; BOOST_HANA_PP_DROP_BACK m37 BOOST_HANA_PP_BACK m37; BOOST_HANA_PP_DROP_BACK m38 BOOST_HANA_PP_BACK m38; BOOST_HANA_PP_DROP_BACK m39 BOOST_HANA_PP_BACK m39; BOOST_HANA_PP_DROP_BACK m40 BOOST_HANA_PP_BACK m40; BOOST_HANA_PP_DROP_BACK m41 BOOST_HANA_PP_BACK m41; BOOST_HANA_PP_DROP_BACK m42 BOOST_HANA_PP_BACK m42; BOOST_HANA_PP_DROP_BACK m43 BOOST_HANA_PP_BACK m43; BOOST_HANA_PP_DROP_BACK m44 BOOST_HANA_PP_BACK m44; BOOST_HANA_PP_DROP_BACK m45 BOOST_HANA_PP_BACK m45; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m45)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m36), &TYPE::BOOST_HANA_PP_BACK m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m37), &TYPE::BOOST_HANA_PP_BACK m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m38), &TYPE::BOOST_HANA_PP_BACK m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m39), &TYPE::BOOST_HANA_PP_BACK m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m40), &TYPE::BOOST_HANA_PP_BACK m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m41), &TYPE::BOOST_HANA_PP_BACK m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m42), &TYPE::BOOST_HANA_PP_BACK m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m43), &TYPE::BOOST_HANA_PP_BACK m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m44), &TYPE::BOOST_HANA_PP_BACK m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m45), &TYPE::BOOST_HANA_PP_BACK m45>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_47(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; BOOST_HANA_PP_DROP_BACK m36 BOOST_HANA_PP_BACK m36; BOOST_HANA_PP_DROP_BACK m37 BOOST_HANA_PP_BACK m37; BOOST_HANA_PP_DROP_BACK m38 BOOST_HANA_PP_BACK m38; BOOST_HANA_PP_DROP_BACK m39 BOOST_HANA_PP_BACK m39; BOOST_HANA_PP_DROP_BACK m40 BOOST_HANA_PP_BACK m40; BOOST_HANA_PP_DROP_BACK m41 BOOST_HANA_PP_BACK m41; BOOST_HANA_PP_DROP_BACK m42 BOOST_HANA_PP_BACK m42; BOOST_HANA_PP_DROP_BACK m43 BOOST_HANA_PP_BACK m43; BOOST_HANA_PP_DROP_BACK m44 BOOST_HANA_PP_BACK m44; BOOST_HANA_PP_DROP_BACK m45 BOOST_HANA_PP_BACK m45; BOOST_HANA_PP_DROP_BACK m46 BOOST_HANA_PP_BACK m46; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m45), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m46)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m36), &TYPE::BOOST_HANA_PP_BACK m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m37), &TYPE::BOOST_HANA_PP_BACK m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m38), &TYPE::BOOST_HANA_PP_BACK m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m39), &TYPE::BOOST_HANA_PP_BACK m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m40), &TYPE::BOOST_HANA_PP_BACK m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m41), &TYPE::BOOST_HANA_PP_BACK m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m42), &TYPE::BOOST_HANA_PP_BACK m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m43), &TYPE::BOOST_HANA_PP_BACK m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m44), &TYPE::BOOST_HANA_PP_BACK m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m45), &TYPE::BOOST_HANA_PP_BACK m45>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m46), &TYPE::BOOST_HANA_PP_BACK m46>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_48(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; BOOST_HANA_PP_DROP_BACK m36 BOOST_HANA_PP_BACK m36; BOOST_HANA_PP_DROP_BACK m37 BOOST_HANA_PP_BACK m37; BOOST_HANA_PP_DROP_BACK m38 BOOST_HANA_PP_BACK m38; BOOST_HANA_PP_DROP_BACK m39 BOOST_HANA_PP_BACK m39; BOOST_HANA_PP_DROP_BACK m40 BOOST_HANA_PP_BACK m40; BOOST_HANA_PP_DROP_BACK m41 BOOST_HANA_PP_BACK m41; BOOST_HANA_PP_DROP_BACK m42 BOOST_HANA_PP_BACK m42; BOOST_HANA_PP_DROP_BACK m43 BOOST_HANA_PP_BACK m43; BOOST_HANA_PP_DROP_BACK m44 BOOST_HANA_PP_BACK m44; BOOST_HANA_PP_DROP_BACK m45 BOOST_HANA_PP_BACK m45; BOOST_HANA_PP_DROP_BACK m46 BOOST_HANA_PP_BACK m46; BOOST_HANA_PP_DROP_BACK m47 BOOST_HANA_PP_BACK m47; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m45), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m46), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m47)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m36), &TYPE::BOOST_HANA_PP_BACK m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m37), &TYPE::BOOST_HANA_PP_BACK m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m38), &TYPE::BOOST_HANA_PP_BACK m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m39), &TYPE::BOOST_HANA_PP_BACK m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m40), &TYPE::BOOST_HANA_PP_BACK m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m41), &TYPE::BOOST_HANA_PP_BACK m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m42), &TYPE::BOOST_HANA_PP_BACK m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m43), &TYPE::BOOST_HANA_PP_BACK m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m44), &TYPE::BOOST_HANA_PP_BACK m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m45), &TYPE::BOOST_HANA_PP_BACK m45>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m46), &TYPE::BOOST_HANA_PP_BACK m46>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m47), &TYPE::BOOST_HANA_PP_BACK m47>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_49(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; BOOST_HANA_PP_DROP_BACK m36 BOOST_HANA_PP_BACK m36; BOOST_HANA_PP_DROP_BACK m37 BOOST_HANA_PP_BACK m37; BOOST_HANA_PP_DROP_BACK m38 BOOST_HANA_PP_BACK m38; BOOST_HANA_PP_DROP_BACK m39 BOOST_HANA_PP_BACK m39; BOOST_HANA_PP_DROP_BACK m40 BOOST_HANA_PP_BACK m40; BOOST_HANA_PP_DROP_BACK m41 BOOST_HANA_PP_BACK m41; BOOST_HANA_PP_DROP_BACK m42 BOOST_HANA_PP_BACK m42; BOOST_HANA_PP_DROP_BACK m43 BOOST_HANA_PP_BACK m43; BOOST_HANA_PP_DROP_BACK m44 BOOST_HANA_PP_BACK m44; BOOST_HANA_PP_DROP_BACK m45 BOOST_HANA_PP_BACK m45; BOOST_HANA_PP_DROP_BACK m46 BOOST_HANA_PP_BACK m46; BOOST_HANA_PP_DROP_BACK m47 BOOST_HANA_PP_BACK m47; BOOST_HANA_PP_DROP_BACK m48 BOOST_HANA_PP_BACK m48; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m45), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m46), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m47), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m48)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m36), &TYPE::BOOST_HANA_PP_BACK m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m37), &TYPE::BOOST_HANA_PP_BACK m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m38), &TYPE::BOOST_HANA_PP_BACK m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m39), &TYPE::BOOST_HANA_PP_BACK m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m40), &TYPE::BOOST_HANA_PP_BACK m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m41), &TYPE::BOOST_HANA_PP_BACK m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m42), &TYPE::BOOST_HANA_PP_BACK m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m43), &TYPE::BOOST_HANA_PP_BACK m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m44), &TYPE::BOOST_HANA_PP_BACK m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m45), &TYPE::BOOST_HANA_PP_BACK m45>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m46), &TYPE::BOOST_HANA_PP_BACK m46>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m47), &TYPE::BOOST_HANA_PP_BACK m47>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m48), &TYPE::BOOST_HANA_PP_BACK m48>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_50(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; BOOST_HANA_PP_DROP_BACK m36 BOOST_HANA_PP_BACK m36; BOOST_HANA_PP_DROP_BACK m37 BOOST_HANA_PP_BACK m37; BOOST_HANA_PP_DROP_BACK m38 BOOST_HANA_PP_BACK m38; BOOST_HANA_PP_DROP_BACK m39 BOOST_HANA_PP_BACK m39; BOOST_HANA_PP_DROP_BACK m40 BOOST_HANA_PP_BACK m40; BOOST_HANA_PP_DROP_BACK m41 BOOST_HANA_PP_BACK m41; BOOST_HANA_PP_DROP_BACK m42 BOOST_HANA_PP_BACK m42; BOOST_HANA_PP_DROP_BACK m43 BOOST_HANA_PP_BACK m43; BOOST_HANA_PP_DROP_BACK m44 BOOST_HANA_PP_BACK m44; BOOST_HANA_PP_DROP_BACK m45 BOOST_HANA_PP_BACK m45; BOOST_HANA_PP_DROP_BACK m46 BOOST_HANA_PP_BACK m46; BOOST_HANA_PP_DROP_BACK m47 BOOST_HANA_PP_BACK m47; BOOST_HANA_PP_DROP_BACK m48 BOOST_HANA_PP_BACK m48; BOOST_HANA_PP_DROP_BACK m49 BOOST_HANA_PP_BACK m49; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m45), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m46), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m47), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m48), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m49)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m36), &TYPE::BOOST_HANA_PP_BACK m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m37), &TYPE::BOOST_HANA_PP_BACK m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m38), &TYPE::BOOST_HANA_PP_BACK m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m39), &TYPE::BOOST_HANA_PP_BACK m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m40), &TYPE::BOOST_HANA_PP_BACK m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m41), &TYPE::BOOST_HANA_PP_BACK m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m42), &TYPE::BOOST_HANA_PP_BACK m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m43), &TYPE::BOOST_HANA_PP_BACK m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m44), &TYPE::BOOST_HANA_PP_BACK m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m45), &TYPE::BOOST_HANA_PP_BACK m45>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m46), &TYPE::BOOST_HANA_PP_BACK m46>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m47), &TYPE::BOOST_HANA_PP_BACK m47>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m48), &TYPE::BOOST_HANA_PP_BACK m48>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m49), &TYPE::BOOST_HANA_PP_BACK m49>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_51(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49, m50) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; BOOST_HANA_PP_DROP_BACK m36 BOOST_HANA_PP_BACK m36; BOOST_HANA_PP_DROP_BACK m37 BOOST_HANA_PP_BACK m37; BOOST_HANA_PP_DROP_BACK m38 BOOST_HANA_PP_BACK m38; BOOST_HANA_PP_DROP_BACK m39 BOOST_HANA_PP_BACK m39; BOOST_HANA_PP_DROP_BACK m40 BOOST_HANA_PP_BACK m40; BOOST_HANA_PP_DROP_BACK m41 BOOST_HANA_PP_BACK m41; BOOST_HANA_PP_DROP_BACK m42 BOOST_HANA_PP_BACK m42; BOOST_HANA_PP_DROP_BACK m43 BOOST_HANA_PP_BACK m43; BOOST_HANA_PP_DROP_BACK m44 BOOST_HANA_PP_BACK m44; BOOST_HANA_PP_DROP_BACK m45 BOOST_HANA_PP_BACK m45; BOOST_HANA_PP_DROP_BACK m46 BOOST_HANA_PP_BACK m46; BOOST_HANA_PP_DROP_BACK m47 BOOST_HANA_PP_BACK m47; BOOST_HANA_PP_DROP_BACK m48 BOOST_HANA_PP_BACK m48; BOOST_HANA_PP_DROP_BACK m49 BOOST_HANA_PP_BACK m49; BOOST_HANA_PP_DROP_BACK m50 BOOST_HANA_PP_BACK m50; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m45), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m46), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m47), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m48), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m49), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m50)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m36), &TYPE::BOOST_HANA_PP_BACK m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m37), &TYPE::BOOST_HANA_PP_BACK m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m38), &TYPE::BOOST_HANA_PP_BACK m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m39), &TYPE::BOOST_HANA_PP_BACK m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m40), &TYPE::BOOST_HANA_PP_BACK m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m41), &TYPE::BOOST_HANA_PP_BACK m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m42), &TYPE::BOOST_HANA_PP_BACK m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m43), &TYPE::BOOST_HANA_PP_BACK m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m44), &TYPE::BOOST_HANA_PP_BACK m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m45), &TYPE::BOOST_HANA_PP_BACK m45>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m46), &TYPE::BOOST_HANA_PP_BACK m46>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m47), &TYPE::BOOST_HANA_PP_BACK m47>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m48), &TYPE::BOOST_HANA_PP_BACK m48>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m49), &TYPE::BOOST_HANA_PP_BACK m49>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<49, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m50), &TYPE::BOOST_HANA_PP_BACK m50>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_52(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49, m50, m51) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; BOOST_HANA_PP_DROP_BACK m36 BOOST_HANA_PP_BACK m36; BOOST_HANA_PP_DROP_BACK m37 BOOST_HANA_PP_BACK m37; BOOST_HANA_PP_DROP_BACK m38 BOOST_HANA_PP_BACK m38; BOOST_HANA_PP_DROP_BACK m39 BOOST_HANA_PP_BACK m39; BOOST_HANA_PP_DROP_BACK m40 BOOST_HANA_PP_BACK m40; BOOST_HANA_PP_DROP_BACK m41 BOOST_HANA_PP_BACK m41; BOOST_HANA_PP_DROP_BACK m42 BOOST_HANA_PP_BACK m42; BOOST_HANA_PP_DROP_BACK m43 BOOST_HANA_PP_BACK m43; BOOST_HANA_PP_DROP_BACK m44 BOOST_HANA_PP_BACK m44; BOOST_HANA_PP_DROP_BACK m45 BOOST_HANA_PP_BACK m45; BOOST_HANA_PP_DROP_BACK m46 BOOST_HANA_PP_BACK m46; BOOST_HANA_PP_DROP_BACK m47 BOOST_HANA_PP_BACK m47; BOOST_HANA_PP_DROP_BACK m48 BOOST_HANA_PP_BACK m48; BOOST_HANA_PP_DROP_BACK m49 BOOST_HANA_PP_BACK m49; BOOST_HANA_PP_DROP_BACK m50 BOOST_HANA_PP_BACK m50; BOOST_HANA_PP_DROP_BACK m51 BOOST_HANA_PP_BACK m51; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m45), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m46), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m47), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m48), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m49), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m50), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m51)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m36), &TYPE::BOOST_HANA_PP_BACK m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m37), &TYPE::BOOST_HANA_PP_BACK m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m38), &TYPE::BOOST_HANA_PP_BACK m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m39), &TYPE::BOOST_HANA_PP_BACK m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m40), &TYPE::BOOST_HANA_PP_BACK m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m41), &TYPE::BOOST_HANA_PP_BACK m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m42), &TYPE::BOOST_HANA_PP_BACK m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m43), &TYPE::BOOST_HANA_PP_BACK m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m44), &TYPE::BOOST_HANA_PP_BACK m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m45), &TYPE::BOOST_HANA_PP_BACK m45>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m46), &TYPE::BOOST_HANA_PP_BACK m46>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m47), &TYPE::BOOST_HANA_PP_BACK m47>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m48), &TYPE::BOOST_HANA_PP_BACK m48>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m49), &TYPE::BOOST_HANA_PP_BACK m49>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<49, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m50), &TYPE::BOOST_HANA_PP_BACK m50>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<50, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m51), &TYPE::BOOST_HANA_PP_BACK m51>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_53(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49, m50, m51, m52) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; BOOST_HANA_PP_DROP_BACK m36 BOOST_HANA_PP_BACK m36; BOOST_HANA_PP_DROP_BACK m37 BOOST_HANA_PP_BACK m37; BOOST_HANA_PP_DROP_BACK m38 BOOST_HANA_PP_BACK m38; BOOST_HANA_PP_DROP_BACK m39 BOOST_HANA_PP_BACK m39; BOOST_HANA_PP_DROP_BACK m40 BOOST_HANA_PP_BACK m40; BOOST_HANA_PP_DROP_BACK m41 BOOST_HANA_PP_BACK m41; BOOST_HANA_PP_DROP_BACK m42 BOOST_HANA_PP_BACK m42; BOOST_HANA_PP_DROP_BACK m43 BOOST_HANA_PP_BACK m43; BOOST_HANA_PP_DROP_BACK m44 BOOST_HANA_PP_BACK m44; BOOST_HANA_PP_DROP_BACK m45 BOOST_HANA_PP_BACK m45; BOOST_HANA_PP_DROP_BACK m46 BOOST_HANA_PP_BACK m46; BOOST_HANA_PP_DROP_BACK m47 BOOST_HANA_PP_BACK m47; BOOST_HANA_PP_DROP_BACK m48 BOOST_HANA_PP_BACK m48; BOOST_HANA_PP_DROP_BACK m49 BOOST_HANA_PP_BACK m49; BOOST_HANA_PP_DROP_BACK m50 BOOST_HANA_PP_BACK m50; BOOST_HANA_PP_DROP_BACK m51 BOOST_HANA_PP_BACK m51; BOOST_HANA_PP_DROP_BACK m52 BOOST_HANA_PP_BACK m52; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m45), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m46), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m47), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m48), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m49), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m50), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m51), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m52)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m36), &TYPE::BOOST_HANA_PP_BACK m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m37), &TYPE::BOOST_HANA_PP_BACK m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m38), &TYPE::BOOST_HANA_PP_BACK m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m39), &TYPE::BOOST_HANA_PP_BACK m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m40), &TYPE::BOOST_HANA_PP_BACK m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m41), &TYPE::BOOST_HANA_PP_BACK m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m42), &TYPE::BOOST_HANA_PP_BACK m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m43), &TYPE::BOOST_HANA_PP_BACK m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m44), &TYPE::BOOST_HANA_PP_BACK m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m45), &TYPE::BOOST_HANA_PP_BACK m45>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m46), &TYPE::BOOST_HANA_PP_BACK m46>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m47), &TYPE::BOOST_HANA_PP_BACK m47>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m48), &TYPE::BOOST_HANA_PP_BACK m48>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m49), &TYPE::BOOST_HANA_PP_BACK m49>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<49, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m50), &TYPE::BOOST_HANA_PP_BACK m50>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<50, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m51), &TYPE::BOOST_HANA_PP_BACK m51>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<51, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m52), &TYPE::BOOST_HANA_PP_BACK m52>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_54(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49, m50, m51, m52, m53) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; BOOST_HANA_PP_DROP_BACK m36 BOOST_HANA_PP_BACK m36; BOOST_HANA_PP_DROP_BACK m37 BOOST_HANA_PP_BACK m37; BOOST_HANA_PP_DROP_BACK m38 BOOST_HANA_PP_BACK m38; BOOST_HANA_PP_DROP_BACK m39 BOOST_HANA_PP_BACK m39; BOOST_HANA_PP_DROP_BACK m40 BOOST_HANA_PP_BACK m40; BOOST_HANA_PP_DROP_BACK m41 BOOST_HANA_PP_BACK m41; BOOST_HANA_PP_DROP_BACK m42 BOOST_HANA_PP_BACK m42; BOOST_HANA_PP_DROP_BACK m43 BOOST_HANA_PP_BACK m43; BOOST_HANA_PP_DROP_BACK m44 BOOST_HANA_PP_BACK m44; BOOST_HANA_PP_DROP_BACK m45 BOOST_HANA_PP_BACK m45; BOOST_HANA_PP_DROP_BACK m46 BOOST_HANA_PP_BACK m46; BOOST_HANA_PP_DROP_BACK m47 BOOST_HANA_PP_BACK m47; BOOST_HANA_PP_DROP_BACK m48 BOOST_HANA_PP_BACK m48; BOOST_HANA_PP_DROP_BACK m49 BOOST_HANA_PP_BACK m49; BOOST_HANA_PP_DROP_BACK m50 BOOST_HANA_PP_BACK m50; BOOST_HANA_PP_DROP_BACK m51 BOOST_HANA_PP_BACK m51; BOOST_HANA_PP_DROP_BACK m52 BOOST_HANA_PP_BACK m52; BOOST_HANA_PP_DROP_BACK m53 BOOST_HANA_PP_BACK m53; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m45), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m46), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m47), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m48), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m49), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m50), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m51), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m52), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m53)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m36), &TYPE::BOOST_HANA_PP_BACK m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m37), &TYPE::BOOST_HANA_PP_BACK m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m38), &TYPE::BOOST_HANA_PP_BACK m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m39), &TYPE::BOOST_HANA_PP_BACK m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m40), &TYPE::BOOST_HANA_PP_BACK m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m41), &TYPE::BOOST_HANA_PP_BACK m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m42), &TYPE::BOOST_HANA_PP_BACK m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m43), &TYPE::BOOST_HANA_PP_BACK m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m44), &TYPE::BOOST_HANA_PP_BACK m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m45), &TYPE::BOOST_HANA_PP_BACK m45>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m46), &TYPE::BOOST_HANA_PP_BACK m46>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m47), &TYPE::BOOST_HANA_PP_BACK m47>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m48), &TYPE::BOOST_HANA_PP_BACK m48>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m49), &TYPE::BOOST_HANA_PP_BACK m49>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<49, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m50), &TYPE::BOOST_HANA_PP_BACK m50>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<50, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m51), &TYPE::BOOST_HANA_PP_BACK m51>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<51, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m52), &TYPE::BOOST_HANA_PP_BACK m52>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<52, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m53), &TYPE::BOOST_HANA_PP_BACK m53>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_55(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49, m50, m51, m52, m53, m54) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; BOOST_HANA_PP_DROP_BACK m36 BOOST_HANA_PP_BACK m36; BOOST_HANA_PP_DROP_BACK m37 BOOST_HANA_PP_BACK m37; BOOST_HANA_PP_DROP_BACK m38 BOOST_HANA_PP_BACK m38; BOOST_HANA_PP_DROP_BACK m39 BOOST_HANA_PP_BACK m39; BOOST_HANA_PP_DROP_BACK m40 BOOST_HANA_PP_BACK m40; BOOST_HANA_PP_DROP_BACK m41 BOOST_HANA_PP_BACK m41; BOOST_HANA_PP_DROP_BACK m42 BOOST_HANA_PP_BACK m42; BOOST_HANA_PP_DROP_BACK m43 BOOST_HANA_PP_BACK m43; BOOST_HANA_PP_DROP_BACK m44 BOOST_HANA_PP_BACK m44; BOOST_HANA_PP_DROP_BACK m45 BOOST_HANA_PP_BACK m45; BOOST_HANA_PP_DROP_BACK m46 BOOST_HANA_PP_BACK m46; BOOST_HANA_PP_DROP_BACK m47 BOOST_HANA_PP_BACK m47; BOOST_HANA_PP_DROP_BACK m48 BOOST_HANA_PP_BACK m48; BOOST_HANA_PP_DROP_BACK m49 BOOST_HANA_PP_BACK m49; BOOST_HANA_PP_DROP_BACK m50 BOOST_HANA_PP_BACK m50; BOOST_HANA_PP_DROP_BACK m51 BOOST_HANA_PP_BACK m51; BOOST_HANA_PP_DROP_BACK m52 BOOST_HANA_PP_BACK m52; BOOST_HANA_PP_DROP_BACK m53 BOOST_HANA_PP_BACK m53; BOOST_HANA_PP_DROP_BACK m54 BOOST_HANA_PP_BACK m54; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m45), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m46), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m47), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m48), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m49), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m50), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m51), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m52), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m53), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m54)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m36), &TYPE::BOOST_HANA_PP_BACK m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m37), &TYPE::BOOST_HANA_PP_BACK m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m38), &TYPE::BOOST_HANA_PP_BACK m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m39), &TYPE::BOOST_HANA_PP_BACK m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m40), &TYPE::BOOST_HANA_PP_BACK m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m41), &TYPE::BOOST_HANA_PP_BACK m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m42), &TYPE::BOOST_HANA_PP_BACK m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m43), &TYPE::BOOST_HANA_PP_BACK m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m44), &TYPE::BOOST_HANA_PP_BACK m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m45), &TYPE::BOOST_HANA_PP_BACK m45>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m46), &TYPE::BOOST_HANA_PP_BACK m46>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m47), &TYPE::BOOST_HANA_PP_BACK m47>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m48), &TYPE::BOOST_HANA_PP_BACK m48>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m49), &TYPE::BOOST_HANA_PP_BACK m49>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<49, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m50), &TYPE::BOOST_HANA_PP_BACK m50>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<50, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m51), &TYPE::BOOST_HANA_PP_BACK m51>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<51, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m52), &TYPE::BOOST_HANA_PP_BACK m52>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<52, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m53), &TYPE::BOOST_HANA_PP_BACK m53>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<53, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m54), &TYPE::BOOST_HANA_PP_BACK m54>{})\
+ ); \
+ } \
+ } \
+/**/
+
+#define BOOST_HANA_DEFINE_STRUCT_IMPL_56(TYPE , m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49, m50, m51, m52, m53, m54, m55) \
+ BOOST_HANA_PP_DROP_BACK m1 BOOST_HANA_PP_BACK m1; BOOST_HANA_PP_DROP_BACK m2 BOOST_HANA_PP_BACK m2; BOOST_HANA_PP_DROP_BACK m3 BOOST_HANA_PP_BACK m3; BOOST_HANA_PP_DROP_BACK m4 BOOST_HANA_PP_BACK m4; BOOST_HANA_PP_DROP_BACK m5 BOOST_HANA_PP_BACK m5; BOOST_HANA_PP_DROP_BACK m6 BOOST_HANA_PP_BACK m6; BOOST_HANA_PP_DROP_BACK m7 BOOST_HANA_PP_BACK m7; BOOST_HANA_PP_DROP_BACK m8 BOOST_HANA_PP_BACK m8; BOOST_HANA_PP_DROP_BACK m9 BOOST_HANA_PP_BACK m9; BOOST_HANA_PP_DROP_BACK m10 BOOST_HANA_PP_BACK m10; BOOST_HANA_PP_DROP_BACK m11 BOOST_HANA_PP_BACK m11; BOOST_HANA_PP_DROP_BACK m12 BOOST_HANA_PP_BACK m12; BOOST_HANA_PP_DROP_BACK m13 BOOST_HANA_PP_BACK m13; BOOST_HANA_PP_DROP_BACK m14 BOOST_HANA_PP_BACK m14; BOOST_HANA_PP_DROP_BACK m15 BOOST_HANA_PP_BACK m15; BOOST_HANA_PP_DROP_BACK m16 BOOST_HANA_PP_BACK m16; BOOST_HANA_PP_DROP_BACK m17 BOOST_HANA_PP_BACK m17; BOOST_HANA_PP_DROP_BACK m18 BOOST_HANA_PP_BACK m18; BOOST_HANA_PP_DROP_BACK m19 BOOST_HANA_PP_BACK m19; BOOST_HANA_PP_DROP_BACK m20 BOOST_HANA_PP_BACK m20; BOOST_HANA_PP_DROP_BACK m21 BOOST_HANA_PP_BACK m21; BOOST_HANA_PP_DROP_BACK m22 BOOST_HANA_PP_BACK m22; BOOST_HANA_PP_DROP_BACK m23 BOOST_HANA_PP_BACK m23; BOOST_HANA_PP_DROP_BACK m24 BOOST_HANA_PP_BACK m24; BOOST_HANA_PP_DROP_BACK m25 BOOST_HANA_PP_BACK m25; BOOST_HANA_PP_DROP_BACK m26 BOOST_HANA_PP_BACK m26; BOOST_HANA_PP_DROP_BACK m27 BOOST_HANA_PP_BACK m27; BOOST_HANA_PP_DROP_BACK m28 BOOST_HANA_PP_BACK m28; BOOST_HANA_PP_DROP_BACK m29 BOOST_HANA_PP_BACK m29; BOOST_HANA_PP_DROP_BACK m30 BOOST_HANA_PP_BACK m30; BOOST_HANA_PP_DROP_BACK m31 BOOST_HANA_PP_BACK m31; BOOST_HANA_PP_DROP_BACK m32 BOOST_HANA_PP_BACK m32; BOOST_HANA_PP_DROP_BACK m33 BOOST_HANA_PP_BACK m33; BOOST_HANA_PP_DROP_BACK m34 BOOST_HANA_PP_BACK m34; BOOST_HANA_PP_DROP_BACK m35 BOOST_HANA_PP_BACK m35; BOOST_HANA_PP_DROP_BACK m36 BOOST_HANA_PP_BACK m36; BOOST_HANA_PP_DROP_BACK m37 BOOST_HANA_PP_BACK m37; BOOST_HANA_PP_DROP_BACK m38 BOOST_HANA_PP_BACK m38; BOOST_HANA_PP_DROP_BACK m39 BOOST_HANA_PP_BACK m39; BOOST_HANA_PP_DROP_BACK m40 BOOST_HANA_PP_BACK m40; BOOST_HANA_PP_DROP_BACK m41 BOOST_HANA_PP_BACK m41; BOOST_HANA_PP_DROP_BACK m42 BOOST_HANA_PP_BACK m42; BOOST_HANA_PP_DROP_BACK m43 BOOST_HANA_PP_BACK m43; BOOST_HANA_PP_DROP_BACK m44 BOOST_HANA_PP_BACK m44; BOOST_HANA_PP_DROP_BACK m45 BOOST_HANA_PP_BACK m45; BOOST_HANA_PP_DROP_BACK m46 BOOST_HANA_PP_BACK m46; BOOST_HANA_PP_DROP_BACK m47 BOOST_HANA_PP_BACK m47; BOOST_HANA_PP_DROP_BACK m48 BOOST_HANA_PP_BACK m48; BOOST_HANA_PP_DROP_BACK m49 BOOST_HANA_PP_BACK m49; BOOST_HANA_PP_DROP_BACK m50 BOOST_HANA_PP_BACK m50; BOOST_HANA_PP_DROP_BACK m51 BOOST_HANA_PP_BACK m51; BOOST_HANA_PP_DROP_BACK m52 BOOST_HANA_PP_BACK m52; BOOST_HANA_PP_DROP_BACK m53 BOOST_HANA_PP_BACK m53; BOOST_HANA_PP_DROP_BACK m54 BOOST_HANA_PP_BACK m54; BOOST_HANA_PP_DROP_BACK m55 BOOST_HANA_PP_BACK m55; \
+ \
+ struct hana_accessors_impl { \
+ static constexpr auto apply() { \
+ struct member_names { \
+ static constexpr auto get() { \
+ return ::boost::hana::make_tuple( \
+ BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m1), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m2), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m3), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m4), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m5), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m6), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m7), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m8), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m9), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m10), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m11), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m12), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m13), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m14), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m15), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m16), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m17), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m18), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m19), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m20), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m21), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m22), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m23), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m24), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m25), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m26), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m27), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m28), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m29), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m30), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m31), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m32), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m33), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m34), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m35), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m36), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m37), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m38), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m39), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m40), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m41), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m42), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m43), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m44), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m45), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m46), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m47), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m48), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m49), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m50), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m51), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m52), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m53), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m54), BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m55)\
+ ); \
+ } \
+ }; \
+ return ::boost::hana::make_tuple( \
+ ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<0, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m1), &TYPE::BOOST_HANA_PP_BACK m1>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<1, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m2), &TYPE::BOOST_HANA_PP_BACK m2>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<2, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m3), &TYPE::BOOST_HANA_PP_BACK m3>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<3, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m4), &TYPE::BOOST_HANA_PP_BACK m4>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<4, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m5), &TYPE::BOOST_HANA_PP_BACK m5>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<5, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m6), &TYPE::BOOST_HANA_PP_BACK m6>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<6, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m7), &TYPE::BOOST_HANA_PP_BACK m7>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<7, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m8), &TYPE::BOOST_HANA_PP_BACK m8>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<8, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m9), &TYPE::BOOST_HANA_PP_BACK m9>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<9, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m10), &TYPE::BOOST_HANA_PP_BACK m10>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<10, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m11), &TYPE::BOOST_HANA_PP_BACK m11>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<11, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m12), &TYPE::BOOST_HANA_PP_BACK m12>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<12, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m13), &TYPE::BOOST_HANA_PP_BACK m13>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<13, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m14), &TYPE::BOOST_HANA_PP_BACK m14>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<14, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m15), &TYPE::BOOST_HANA_PP_BACK m15>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<15, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m16), &TYPE::BOOST_HANA_PP_BACK m16>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<16, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m17), &TYPE::BOOST_HANA_PP_BACK m17>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<17, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m18), &TYPE::BOOST_HANA_PP_BACK m18>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<18, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m19), &TYPE::BOOST_HANA_PP_BACK m19>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<19, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m20), &TYPE::BOOST_HANA_PP_BACK m20>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<20, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m21), &TYPE::BOOST_HANA_PP_BACK m21>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<21, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m22), &TYPE::BOOST_HANA_PP_BACK m22>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<22, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m23), &TYPE::BOOST_HANA_PP_BACK m23>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<23, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m24), &TYPE::BOOST_HANA_PP_BACK m24>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<24, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m25), &TYPE::BOOST_HANA_PP_BACK m25>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<25, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m26), &TYPE::BOOST_HANA_PP_BACK m26>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<26, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m27), &TYPE::BOOST_HANA_PP_BACK m27>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<27, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m28), &TYPE::BOOST_HANA_PP_BACK m28>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<28, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m29), &TYPE::BOOST_HANA_PP_BACK m29>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<29, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m30), &TYPE::BOOST_HANA_PP_BACK m30>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<30, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m31), &TYPE::BOOST_HANA_PP_BACK m31>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<31, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m32), &TYPE::BOOST_HANA_PP_BACK m32>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<32, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m33), &TYPE::BOOST_HANA_PP_BACK m33>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<33, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m34), &TYPE::BOOST_HANA_PP_BACK m34>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<34, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m35), &TYPE::BOOST_HANA_PP_BACK m35>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<35, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m36), &TYPE::BOOST_HANA_PP_BACK m36>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<36, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m37), &TYPE::BOOST_HANA_PP_BACK m37>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<37, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m38), &TYPE::BOOST_HANA_PP_BACK m38>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<38, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m39), &TYPE::BOOST_HANA_PP_BACK m39>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<39, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m40), &TYPE::BOOST_HANA_PP_BACK m40>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<40, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m41), &TYPE::BOOST_HANA_PP_BACK m41>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<41, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m42), &TYPE::BOOST_HANA_PP_BACK m42>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<42, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m43), &TYPE::BOOST_HANA_PP_BACK m43>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<43, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m44), &TYPE::BOOST_HANA_PP_BACK m44>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<44, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m45), &TYPE::BOOST_HANA_PP_BACK m45>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<45, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m46), &TYPE::BOOST_HANA_PP_BACK m46>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<46, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m47), &TYPE::BOOST_HANA_PP_BACK m47>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<47, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m48), &TYPE::BOOST_HANA_PP_BACK m48>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<48, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m49), &TYPE::BOOST_HANA_PP_BACK m49>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<49, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m50), &TYPE::BOOST_HANA_PP_BACK m50>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<50, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m51), &TYPE::BOOST_HANA_PP_BACK m51>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<51, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m52), &TYPE::BOOST_HANA_PP_BACK m52>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<52, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m53), &TYPE::BOOST_HANA_PP_BACK m53>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<53, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m54), &TYPE::BOOST_HANA_PP_BACK m54>{}), ::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<54, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m55), &TYPE::BOOST_HANA_PP_BACK m55>{})\
+ ); \
+ } \
+ } \
+/**/
+
+
+#endif // !BOOST_HANA_DETAIL_STRUCT_MACROS_HPP
diff --git a/boost/hana/detail/type_foldl1.hpp b/boost/hana/detail/type_foldl1.hpp
new file mode 100644
index 0000000000..98f2947427
--- /dev/null
+++ b/boost/hana/detail/type_foldl1.hpp
@@ -0,0 +1,145 @@
+/*!
+@file
+Defines `boost::hana::detail::type_foldl1`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_TYPE_FOLDL1_HPP
+#define BOOST_HANA_DETAIL_TYPE_FOLDL1_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <unsigned n>
+ struct type_foldl1_t;
+
+ template <>
+ struct type_foldl1_t<0> {
+ template <
+ template <typename ...> class f,
+ typename state
+ >
+ using result = state;
+ };
+
+ template <>
+ struct type_foldl1_t<1> {
+ template <
+ template <typename ...> class f,
+ typename state,
+ typename x1
+ >
+ using result = typename f<state, x1>::type;
+ };
+
+ template <>
+ struct type_foldl1_t<2> {
+ template <
+ template <typename ...> class f,
+ typename state,
+ typename x1, typename x2
+ >
+ using result = typename f<typename f<state, x1>::type, x2>::type;
+ };
+
+ template <>
+ struct type_foldl1_t<3> {
+ template <
+ template <typename ...> class f,
+ typename state,
+ typename x1, typename x2, typename x3
+ >
+ using result = typename f<
+ typename f<
+ typename f<state, x1>::type,
+ x2
+ >::type,
+ x3
+ >::type;
+ };
+
+ template <>
+ struct type_foldl1_t<4> {
+ template <
+ template <typename ...> class f,
+ typename state,
+ typename x1, typename x2, typename x3, typename x4
+ >
+ using result = typename f<
+ typename f<
+ typename f<
+ typename f<state, x1>::type,
+ x2
+ >::type,
+ x3
+ >::type,
+ x4
+ >::type;
+ };
+
+ template <>
+ struct type_foldl1_t<5> {
+ template <
+ template <typename ...> class f,
+ typename state,
+ typename x1, typename x2, typename x3, typename x4, typename x5
+ >
+ using result = typename f<
+ typename f<
+ typename f<
+ typename f<
+ typename f<state, x1>::type,
+ x2
+ >::type,
+ x3
+ >::type,
+ x4
+ >::type,
+ x5
+ >::type;
+ };
+
+ template <>
+ struct type_foldl1_t<6> {
+ template <
+ template <typename ...> class f,
+ typename state,
+ typename x1, typename x2, typename x3, typename x4, typename x5, typename x6,
+ typename ...xs
+ >
+ using result =
+ typename type_foldl1_t<(sizeof...(xs) > 6 ? 6 : sizeof...(xs))>::
+ template result<
+ f,
+ typename f<
+ typename f<
+ typename f<
+ typename f<
+ typename f<
+ typename f<state, x1>::type,
+ x2
+ >::type,
+ x3
+ >::type,
+ x4
+ >::type,
+ x5
+ >::type,
+ x6
+ >::type,
+ xs...
+ >;
+ };
+
+ template <template <typename ...> class f, typename x1, typename ...xn>
+ struct type_foldl1 {
+ using type = typename type_foldl1_t<(sizeof...(xn) > 6 ? 6 : sizeof...(xn))>
+ ::template result<f, x1, xn...>;
+ };
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_TYPE_FOLDL1_HPP
diff --git a/boost/hana/detail/type_foldr1.hpp b/boost/hana/detail/type_foldr1.hpp
new file mode 100644
index 0000000000..3453d4467b
--- /dev/null
+++ b/boost/hana/detail/type_foldr1.hpp
@@ -0,0 +1,149 @@
+/*!
+@file
+Defines `boost::hana::detail::type_foldr1`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_TYPE_FOLDR1_HPP
+#define BOOST_HANA_DETAIL_TYPE_FOLDR1_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <unsigned n>
+ struct type_foldr1_t;
+
+ template <>
+ struct type_foldr1_t<0> {
+ template <
+ template <typename ...> class f,
+ typename state
+ >
+ using result = state;
+ };
+
+ template <>
+ struct type_foldr1_t<1> {
+ template <
+ template <typename ...> class f,
+ typename x1,
+ typename state
+ >
+ using result = typename f<x1, state>::type;
+ };
+
+ template <>
+ struct type_foldr1_t<2> {
+ template <
+ template <typename ...> class f,
+ typename x1, typename x2,
+ typename state
+ >
+ using result = typename f<x1, typename f<x2, state>::type>::type;
+ };
+
+ template <>
+ struct type_foldr1_t<3> {
+ template <
+ template <typename ...> class f,
+ typename x1, typename x2, typename x3,
+ typename state
+ >
+ using result = typename f<
+ x1,
+ typename f<
+ x2,
+ typename f<
+ x3,
+ state
+ >::type
+ >::type
+ >::type;
+ };
+
+ template <>
+ struct type_foldr1_t<4> {
+ template <
+ template <typename ...> class f,
+ typename x1, typename x2, typename x3, typename x4,
+ typename state
+ >
+ using result = typename f<
+ x1,
+ typename f<
+ x2,
+ typename f<
+ x3,
+ typename f<
+ x4,
+ state
+ >::type
+ >::type
+ >::type
+ >::type;
+ };
+
+ template <>
+ struct type_foldr1_t<5> {
+ template <
+ template <typename ...> class f,
+ typename x1, typename x2, typename x3, typename x4, typename x5,
+ typename state
+ >
+ using result = typename f<
+ x1,
+ typename f<
+ x2,
+ typename f<
+ x3,
+ typename f<
+ x4,
+ typename f<
+ x5,
+ state
+ >::type
+ >::type
+ >::type
+ >::type
+ >::type;
+ };
+
+ template <>
+ struct type_foldr1_t<6> {
+ template <
+ template <typename ...> class f,
+ typename x1, typename x2, typename x3, typename x4, typename x5, typename x6,
+ typename ...xs
+ >
+ using result =
+ typename f<
+ x1,
+ typename f<
+ x2,
+ typename f<
+ x3,
+ typename f<
+ x4,
+ typename f<
+ x5,
+ typename type_foldr1_t<(sizeof...(xs) > 6 ? 6 : sizeof...(xs))>::
+ template result<f, x6, xs...>
+ >::type
+ >::type
+ >::type
+ >::type
+ >::type;
+ };
+
+ template <template <typename ...> class f, typename x1, typename ...xn>
+ struct type_foldr1 {
+ using type = typename type_foldr1_t<(sizeof...(xn) > 6 ? 6 : sizeof...(xn))>
+ ::template result<f, x1, xn...>;
+ };
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_TYPE_FOLDR1_HPP
diff --git a/boost/hana/detail/unpack_flatten.hpp b/boost/hana/detail/unpack_flatten.hpp
new file mode 100644
index 0000000000..f72501a644
--- /dev/null
+++ b/boost/hana/detail/unpack_flatten.hpp
@@ -0,0 +1,70 @@
+/*!
+@file
+Defines `boost::hana::detail::unpack_flatten`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_UNPACK_FLATTEN_HPP
+#define BOOST_HANA_DETAIL_UNPACK_FLATTEN_HPP
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/algorithm.hpp>
+#include <boost/hana/detail/array.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/unpack.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <std::size_t ...Lengths>
+ struct flatten_indices {
+ // avoid empty arrays by appending 0 to `lengths`
+ static constexpr std::size_t lengths[] = {Lengths..., 0};
+ static constexpr auto flat_length =
+ detail::accumulate(lengths, lengths + sizeof...(Lengths), 0);
+
+ template <bool Inner>
+ static constexpr auto compute() {
+ detail::array<std::size_t, flat_length> indices{};
+ for (std::size_t index = 0, i = 0; i < sizeof...(Lengths); ++i)
+ for (std::size_t j = 0; j < lengths[i]; ++j, ++index)
+ indices[index] = (Inner ? i : j);
+ return indices;
+ }
+
+ static constexpr auto inner = compute<true>();
+ static constexpr auto outer = compute<false>();
+
+ template <typename Xs, typename F, std::size_t ...i>
+ static constexpr decltype(auto)
+ apply(Xs&& xs, F&& f, std::index_sequence<i...>) {
+ return static_cast<F&&>(f)(
+ hana::at_c<outer[i]>(hana::at_c<inner[i]>(
+ static_cast<Xs&&>(xs)
+ ))...
+ );
+ }
+ };
+
+ struct make_flatten_indices {
+ template <typename ...Xs>
+ auto operator()(Xs const& ...xs) const -> detail::flatten_indices<
+ decltype(hana::length(xs))::value...
+ >;
+ };
+
+ template <typename Xs, typename F>
+ constexpr decltype(auto) unpack_flatten(Xs&& xs, F&& f) {
+ using Indices = decltype(hana::unpack(xs, make_flatten_indices{}));
+ return Indices::apply(static_cast<Xs&&>(xs), static_cast<F&&>(f),
+ std::make_index_sequence<Indices::flat_length>{});
+ }
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_UNPACK_FLATTEN_HPP
diff --git a/boost/hana/detail/variadic/at.hpp b/boost/hana/detail/variadic/at.hpp
new file mode 100644
index 0000000000..705d0e2ccc
--- /dev/null
+++ b/boost/hana/detail/variadic/at.hpp
@@ -0,0 +1,40 @@
+/*!
+@file
+Defines `boost::hana::detail::variadic::at`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_VARIADIC_AT_HPP
+#define BOOST_HANA_DETAIL_VARIADIC_AT_HPP
+
+#include <boost/hana/config.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
+ template <std::size_t n, typename = std::make_index_sequence<n>>
+ struct at_type;
+
+ template <std::size_t n, std::size_t ...ignore>
+ struct at_type<n, std::index_sequence<ignore...>> {
+ private:
+ template <typename Nth>
+ static constexpr auto go(decltype(ignore, (void*)0)..., Nth nth, ...)
+ { return nth; }
+
+ public:
+ template <typename ...Xs>
+ constexpr auto operator()(Xs ...xs) const
+ { return *go(&xs...); }
+ };
+
+ template <std::size_t n>
+ constexpr at_type<n> at{};
+}} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_VARIADIC_AT_HPP
diff --git a/boost/hana/detail/variadic/drop_into.hpp b/boost/hana/detail/variadic/drop_into.hpp
new file mode 100644
index 0000000000..9e5a80f5dd
--- /dev/null
+++ b/boost/hana/detail/variadic/drop_into.hpp
@@ -0,0 +1,47 @@
+/*!
+@file
+Defines `boost::hana::detail::variadic::drop_into`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_VARIADIC_DROP_INTO_HPP
+#define BOOST_HANA_DETAIL_VARIADIC_DROP_INTO_HPP
+
+#include <boost/hana/config.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
+ template <std::size_t n, typename F, typename = std::make_index_sequence<n>>
+ struct dropper;
+
+ template <std::size_t n, typename F, std::size_t ...ignore>
+ struct dropper<n, F, std::index_sequence<ignore...>> {
+ F f;
+
+ template <typename ...Rest>
+ constexpr auto go(decltype(ignore, (void*)0)..., Rest ...rest) const
+ { return f(*rest...); }
+
+ template <typename ...Xs>
+ constexpr auto operator()(Xs ...xs) const
+ { return go(&xs...); }
+ };
+
+ template <std::size_t n>
+ struct make_dropper {
+ template <typename F>
+ constexpr auto operator()(F f) const
+ { return dropper<n, decltype(f)>{f}; }
+ };
+
+ template <std::size_t n>
+ constexpr make_dropper<n> drop_into{};
+}} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_VARIADIC_DROP_INTO_HPP
diff --git a/boost/hana/detail/variadic/foldl1.hpp b/boost/hana/detail/variadic/foldl1.hpp
new file mode 100644
index 0000000000..ad2946b05f
--- /dev/null
+++ b/boost/hana/detail/variadic/foldl1.hpp
@@ -0,0 +1,212 @@
+/*!
+@file
+Defines `boost::hana::detail::variadic::foldl1`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_VARIADIC_FOLDL1_HPP
+#define BOOST_HANA_DETAIL_VARIADIC_FOLDL1_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
+ template <unsigned int n, typename = when<true>>
+ struct foldl1_impl;
+
+ template <>
+ struct foldl1_impl<1> {
+ template <typename F, typename X1>
+ static constexpr X1 apply(F&&, X1&& x1)
+ { return static_cast<X1&&>(x1); }
+ };
+
+ template <>
+ struct foldl1_impl<2> {
+ template <typename F, typename X1, typename X2>
+ static constexpr decltype(auto) apply(F&& f, X1&& x1, X2&& x2) {
+ return static_cast<F&&>(f)(static_cast<X1&&>(x1),
+ static_cast<X2&&>(x2));
+ }
+ };
+
+ template <>
+ struct foldl1_impl<3> {
+ template <typename F, typename X1, typename X2, typename X3>
+ static constexpr decltype(auto) apply(F&& f, X1&& x1, X2&& x2, X3&& x3) {
+ return f(f(static_cast<X1&&>(x1),
+ static_cast<X2&&>(x2)),
+ static_cast<X3&&>(x3));
+ }
+ };
+
+ template <>
+ struct foldl1_impl<4> {
+ template <typename F, typename X1, typename X2, typename X3, typename X4>
+ static constexpr decltype(auto) apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4) {
+ return f(f(f(static_cast<X1&&>(x1),
+ static_cast<X2&&>(x2)),
+ static_cast<X3&&>(x3)),
+ static_cast<X4&&>(x4));
+ }
+ };
+
+ template <>
+ struct foldl1_impl<5> {
+ template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5>
+ static constexpr decltype(auto) apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5) {
+ return f(f(f(f(static_cast<X1&&>(x1),
+ static_cast<X2&&>(x2)),
+ static_cast<X3&&>(x3)),
+ static_cast<X4&&>(x4)),
+ static_cast<X5&&>(x5));
+ }
+ };
+
+ template <>
+ struct foldl1_impl<6> {
+ template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6>
+ static constexpr decltype(auto) apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6) {
+ return f(f(f(f(f(static_cast<X1&&>(x1),
+ static_cast<X2&&>(x2)),
+ static_cast<X3&&>(x3)),
+ static_cast<X4&&>(x4)),
+ static_cast<X5&&>(x5)),
+ static_cast<X6&&>(x6));
+ }
+ };
+
+ template <unsigned int n>
+ struct foldl1_impl<n, when<(n >= 7) && (n < 14)>> {
+ template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename ...Xn>
+ static constexpr decltype(auto)
+ apply(F&& f
+ , X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7
+ , Xn&& ...xn)
+ {
+ return foldl1_impl<sizeof...(xn) + 1>::apply(
+ f,
+ f(f(f(f(f(f(static_cast<X1&&>(x1),
+ static_cast<X2&&>(x2)),
+ static_cast<X3&&>(x3)),
+ static_cast<X4&&>(x4)),
+ static_cast<X5&&>(x5)),
+ static_cast<X6&&>(x6)),
+ static_cast<X7&&>(x7)),
+ static_cast<Xn&&>(xn)...
+ );
+ }
+ };
+
+ template <unsigned int n>
+ struct foldl1_impl<n, when<(n >= 14) && (n < 28)>> {
+ template <
+ typename F
+ , typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7
+ , typename X8, typename X9, typename X10, typename X11, typename X12, typename X13, typename X14
+ , typename ...Xn
+ >
+ static constexpr decltype(auto)
+ apply(F&& f
+ , X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7
+ , X8&& x8, X9&& x9, X10&& x10, X11&& x11, X12&& x12, X13&& x13, X14&& x14
+ , Xn&& ...xn)
+ {
+ return foldl1_impl<sizeof...(xn) + 1>::apply(
+ f,
+ f(f(f(f(f(f(f(f(f(f(f(f(f(
+ static_cast<X1&&>(x1), static_cast<X2&&>(x2)), static_cast<X3&&>(x3)), static_cast<X4&&>(x4)), static_cast<X5&&>(x5)), static_cast<X6&&>(x6)), static_cast<X7&&>(x7)),
+ static_cast<X8&&>(x8)), static_cast<X9&&>(x9)), static_cast<X10&&>(x10)), static_cast<X11&&>(x11)), static_cast<X12&&>(x12)), static_cast<X13&&>(x13)), static_cast<X14&&>(x14))
+ , static_cast<Xn&&>(xn)...);
+
+ }
+ };
+
+ template <unsigned int n>
+ struct foldl1_impl<n, when<(n >= 28) && (n < 56)>> {
+ template <
+ typename F
+ , typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7
+ , typename X8, typename X9, typename X10, typename X11, typename X12, typename X13, typename X14
+ , typename X15, typename X16, typename X17, typename X18, typename X19, typename X20, typename X21
+ , typename X22, typename X23, typename X24, typename X25, typename X26, typename X27, typename X28
+ , typename ...Xn
+ >
+ static constexpr decltype(auto)
+ apply(F&& f
+ , X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7
+ , X8&& x8, X9&& x9, X10&& x10, X11&& x11, X12&& x12, X13&& x13, X14&& x14
+ , X15&& x15, X16&& x16, X17&& x17, X18&& x18, X19&& x19, X20&& x20, X21&& x21
+ , X22&& x22, X23&& x23, X24&& x24, X25&& x25, X26&& x26, X27&& x27, X28&& x28
+ , Xn&& ...xn)
+ {
+ return foldl1_impl<sizeof...(xn) + 1>::apply(
+ f,
+ f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(
+ static_cast<X1&&>(x1), static_cast<X2&&>(x2)), static_cast<X3&&>(x3)), static_cast<X4&&>(x4)), static_cast<X5&&>(x5)), static_cast<X6&&>(x6)), static_cast<X7&&>(x7)),
+ static_cast<X8&&>(x8)), static_cast<X9&&>(x9)), static_cast<X10&&>(x10)), static_cast<X11&&>(x11)), static_cast<X12&&>(x12)), static_cast<X13&&>(x13)), static_cast<X14&&>(x14)),
+ static_cast<X15&&>(x15)), static_cast<X16&&>(x16)), static_cast<X17&&>(x17)), static_cast<X18&&>(x18)), static_cast<X19&&>(x19)), static_cast<X20&&>(x20)), static_cast<X21&&>(x21)),
+ static_cast<X22&&>(x22)), static_cast<X23&&>(x23)), static_cast<X24&&>(x24)), static_cast<X25&&>(x25)), static_cast<X26&&>(x26)), static_cast<X27&&>(x27)), static_cast<X28&&>(x28))
+ , static_cast<Xn&&>(xn)...);
+ }
+ };
+
+ template <unsigned int n>
+ struct foldl1_impl<n, when<(n >= 56)>> {
+ template <
+ typename F
+ , typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7
+ , typename X8, typename X9, typename X10, typename X11, typename X12, typename X13, typename X14
+ , typename X15, typename X16, typename X17, typename X18, typename X19, typename X20, typename X21
+ , typename X22, typename X23, typename X24, typename X25, typename X26, typename X27, typename X28
+ , typename X29, typename X30, typename X31, typename X32, typename X33, typename X34, typename X35
+ , typename X36, typename X37, typename X38, typename X39, typename X40, typename X41, typename X42
+ , typename X43, typename X44, typename X45, typename X46, typename X47, typename X48, typename X49
+ , typename X50, typename X51, typename X52, typename X53, typename X54, typename X55, typename X56
+ , typename ...Xn
+ >
+ static constexpr decltype(auto)
+ apply(F&& f
+ , X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7
+ , X8&& x8, X9&& x9, X10&& x10, X11&& x11, X12&& x12, X13&& x13, X14&& x14
+ , X15&& x15, X16&& x16, X17&& x17, X18&& x18, X19&& x19, X20&& x20, X21&& x21
+ , X22&& x22, X23&& x23, X24&& x24, X25&& x25, X26&& x26, X27&& x27, X28&& x28
+ , X29&& x29, X30&& x30, X31&& x31, X32&& x32, X33&& x33, X34&& x34, X35&& x35
+ , X36&& x36, X37&& x37, X38&& x38, X39&& x39, X40&& x40, X41&& x41, X42&& x42
+ , X43&& x43, X44&& x44, X45&& x45, X46&& x46, X47&& x47, X48&& x48, X49&& x49
+ , X50&& x50, X51&& x51, X52&& x52, X53&& x53, X54&& x54, X55&& x55, X56&& x56
+ , Xn&& ...xn)
+ {
+ return foldl1_impl<sizeof...(xn) + 1>::apply(
+ f,
+ f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(
+ static_cast<X1&&>(x1), static_cast<X2&&>(x2)), static_cast<X3&&>(x3)), static_cast<X4&&>(x4)), static_cast<X5&&>(x5)), static_cast<X6&&>(x6)), static_cast<X7&&>(x7)),
+ static_cast<X8&&>(x8)), static_cast<X9&&>(x9)), static_cast<X10&&>(x10)), static_cast<X11&&>(x11)), static_cast<X12&&>(x12)), static_cast<X13&&>(x13)), static_cast<X14&&>(x14)),
+ static_cast<X15&&>(x15)), static_cast<X16&&>(x16)), static_cast<X17&&>(x17)), static_cast<X18&&>(x18)), static_cast<X19&&>(x19)), static_cast<X20&&>(x20)), static_cast<X21&&>(x21)),
+ static_cast<X22&&>(x22)), static_cast<X23&&>(x23)), static_cast<X24&&>(x24)), static_cast<X25&&>(x25)), static_cast<X26&&>(x26)), static_cast<X27&&>(x27)), static_cast<X28&&>(x28)),
+ static_cast<X29&&>(x29)), static_cast<X30&&>(x30)), static_cast<X31&&>(x31)), static_cast<X32&&>(x32)), static_cast<X33&&>(x33)), static_cast<X34&&>(x34)), static_cast<X35&&>(x35)),
+ static_cast<X36&&>(x36)), static_cast<X37&&>(x37)), static_cast<X38&&>(x38)), static_cast<X39&&>(x39)), static_cast<X40&&>(x40)), static_cast<X41&&>(x41)), static_cast<X42&&>(x42)),
+ static_cast<X43&&>(x43)), static_cast<X44&&>(x44)), static_cast<X45&&>(x45)), static_cast<X46&&>(x46)), static_cast<X47&&>(x47)), static_cast<X48&&>(x48)), static_cast<X49&&>(x49)),
+ static_cast<X50&&>(x50)), static_cast<X51&&>(x51)), static_cast<X52&&>(x52)), static_cast<X53&&>(x53)), static_cast<X54&&>(x54)), static_cast<X55&&>(x55)), static_cast<X56&&>(x56))
+ , static_cast<Xn&&>(xn)...);
+ }
+ };
+
+ struct foldl1_t {
+ template <typename F, typename X1, typename ...Xn>
+ constexpr decltype(auto) operator()(F&& f, X1&& x1, Xn&& ...xn) const {
+ return foldl1_impl<sizeof...(xn) + 1>::apply(
+ static_cast<F&&>(f), static_cast<X1&&>(x1), static_cast<Xn&&>(xn)...
+ );
+ }
+ };
+
+ constexpr foldl1_t foldl1{};
+ constexpr auto foldl = foldl1;
+}} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_VARIADIC_FOLDL1_HPP
diff --git a/boost/hana/detail/variadic/foldr1.hpp b/boost/hana/detail/variadic/foldr1.hpp
new file mode 100644
index 0000000000..88b5c95305
--- /dev/null
+++ b/boost/hana/detail/variadic/foldr1.hpp
@@ -0,0 +1,208 @@
+/*!
+@file
+Defines `boost::hana::detail::variadic::foldr1`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_VARIADIC_FOLDR1_HPP
+#define BOOST_HANA_DETAIL_VARIADIC_FOLDR1_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
+ template <unsigned int n, typename = when<true>>
+ struct foldr1_impl;
+
+ template <>
+ struct foldr1_impl<1> {
+ template <typename F, typename X1>
+ static constexpr X1 apply(F&&, X1&& x1)
+ { return static_cast<X1&&>(x1); }
+ };
+
+ template <>
+ struct foldr1_impl<2> {
+ template <typename F, typename X1, typename X2>
+ static constexpr decltype(auto) apply(F&& f, X1&& x1, X2&& x2) {
+ return static_cast<F&&>(f)(static_cast<X1&&>(x1),
+ static_cast<X2&&>(x2));
+ }
+ };
+
+ template <>
+ struct foldr1_impl<3> {
+ template <typename F, typename X1, typename X2, typename X3>
+ static constexpr decltype(auto) apply(F&& f, X1&& x1, X2&& x2, X3&& x3) {
+ return f(static_cast<X1&&>(x1),
+ f(static_cast<X2&&>(x2),
+ static_cast<X3&&>(x3)));
+ }
+ };
+
+ template <>
+ struct foldr1_impl<4> {
+ template <typename F, typename X1, typename X2, typename X3, typename X4>
+ static constexpr decltype(auto) apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4) {
+ return f(static_cast<X1&&>(x1),
+ f(static_cast<X2&&>(x2),
+ f(static_cast<X3&&>(x3),
+ static_cast<X4&&>(x4))));
+ }
+ };
+
+ template <>
+ struct foldr1_impl<5> {
+ template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5>
+ static constexpr decltype(auto) apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5) {
+ return f(static_cast<X1&&>(x1),
+ f(static_cast<X2&&>(x2),
+ f(static_cast<X3&&>(x3),
+ f(static_cast<X4&&>(x4),
+ static_cast<X5&&>(x5)))));
+ }
+ };
+
+ template <>
+ struct foldr1_impl<6> {
+ template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6>
+ static constexpr decltype(auto) apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6) {
+ return f(static_cast<X1&&>(x1),
+ f(static_cast<X2&&>(x2),
+ f(static_cast<X3&&>(x3),
+ f(static_cast<X4&&>(x4),
+ f(static_cast<X5&&>(x5),
+ static_cast<X6&&>(x6))))));
+ }
+ };
+
+ template <unsigned int n>
+ struct foldr1_impl<n, when<(n >= 7) && (n < 14)>> {
+ template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename ...Xn>
+ static constexpr decltype(auto)
+ apply(F&& f
+ , X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7
+ , Xn&& ...xn)
+ {
+ return f(static_cast<X1&&>(x1),
+ f(static_cast<X2&&>(x2),
+ f(static_cast<X3&&>(x3),
+ f(static_cast<X4&&>(x4),
+ f(static_cast<X5&&>(x5),
+ f(static_cast<X6&&>(x6),
+ foldr1_impl<sizeof...(xn) + 1>::apply(f, static_cast<X7&&>(x7), static_cast<Xn&&>(xn)...)))))));
+ }
+ };
+
+ template <unsigned int n>
+ struct foldr1_impl<n, when<(n >= 14) && (n < 28)>> {
+ template <
+ typename F
+ , typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7
+ , typename X8, typename X9, typename X10, typename X11, typename X12, typename X13, typename X14
+ , typename ...Xn
+ >
+ static constexpr decltype(auto)
+ apply(F&& f
+ , X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7
+ , X8&& x8, X9&& x9, X10&& x10, X11&& x11, X12&& x12, X13&& x13, X14&& x14
+ , Xn&& ...xn)
+ {
+ return f(static_cast<X1&&>(x1), f(static_cast<X2&&>(x2), f(static_cast<X3&&>(x3), f(static_cast<X4&&>(x4), f(static_cast<X5&&>(x5), f(static_cast<X6&&>(x6), f(static_cast<X7&&>(x7),
+ f(static_cast<X8&&>(x8), f(static_cast<X9&&>(x9), f(static_cast<X10&&>(x10), f(static_cast<X11&&>(x11), f(static_cast<X12&&>(x12), f(static_cast<X13&&>(x13),
+ foldr1_impl<sizeof...(xn) + 1>::apply(f, static_cast<X14&&>(x14), static_cast<Xn&&>(xn)...))))))))))))));
+ }
+ };
+
+ template <unsigned int n>
+ struct foldr1_impl<n, when<(n >= 28) && (n < 56)>> {
+ template <
+ typename F
+ , typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7
+ , typename X8, typename X9, typename X10, typename X11, typename X12, typename X13, typename X14
+ , typename X15, typename X16, typename X17, typename X18, typename X19, typename X20, typename X21
+ , typename X22, typename X23, typename X24, typename X25, typename X26, typename X27, typename X28
+ , typename ...Xn
+ >
+ static constexpr decltype(auto)
+ apply(F&& f
+ , X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7
+ , X8&& x8, X9&& x9, X10&& x10, X11&& x11, X12&& x12, X13&& x13, X14&& x14
+ , X15&& x15, X16&& x16, X17&& x17, X18&& x18, X19&& x19, X20&& x20, X21&& x21
+ , X22&& x22, X23&& x23, X24&& x24, X25&& x25, X26&& x26, X27&& x27, X28&& x28
+ , Xn&& ...xn)
+ {
+ return f(static_cast<X1&&>(x1), f(static_cast<X2&&>(x2), f(static_cast<X3&&>(x3), f(static_cast<X4&&>(x4), f(static_cast<X5&&>(x5), f(static_cast<X6&&>(x6), f(static_cast<X7&&>(x7),
+ f(static_cast<X8&&>(x8), f(static_cast<X9&&>(x9), f(static_cast<X10&&>(x10), f(static_cast<X11&&>(x11), f(static_cast<X12&&>(x12), f(static_cast<X13&&>(x13), f(static_cast<X14&&>(x14),
+ f(static_cast<X15&&>(x15), f(static_cast<X16&&>(x16), f(static_cast<X17&&>(x17), f(static_cast<X18&&>(x18), f(static_cast<X19&&>(x19), f(static_cast<X20&&>(x20), f(static_cast<X21&&>(x21),
+ f(static_cast<X22&&>(x22), f(static_cast<X23&&>(x23), f(static_cast<X24&&>(x24), f(static_cast<X25&&>(x25), f(static_cast<X26&&>(x26), f(static_cast<X27&&>(x27),
+ foldr1_impl<sizeof...(xn) + 1>::apply(f, static_cast<X28&&>(x28), static_cast<Xn&&>(xn)...))))))))))))))))))))))))))));
+ }
+ };
+
+ template <unsigned int n>
+ struct foldr1_impl<n, when<(n >= 56)>> {
+ template <
+ typename F
+ , typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7
+ , typename X8, typename X9, typename X10, typename X11, typename X12, typename X13, typename X14
+ , typename X15, typename X16, typename X17, typename X18, typename X19, typename X20, typename X21
+ , typename X22, typename X23, typename X24, typename X25, typename X26, typename X27, typename X28
+ , typename X29, typename X30, typename X31, typename X32, typename X33, typename X34, typename X35
+ , typename X36, typename X37, typename X38, typename X39, typename X40, typename X41, typename X42
+ , typename X43, typename X44, typename X45, typename X46, typename X47, typename X48, typename X49
+ , typename X50, typename X51, typename X52, typename X53, typename X54, typename X55, typename X56
+ , typename ...Xn
+ >
+ static constexpr decltype(auto)
+ apply(F&& f
+ , X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7
+ , X8&& x8, X9&& x9, X10&& x10, X11&& x11, X12&& x12, X13&& x13, X14&& x14
+ , X15&& x15, X16&& x16, X17&& x17, X18&& x18, X19&& x19, X20&& x20, X21&& x21
+ , X22&& x22, X23&& x23, X24&& x24, X25&& x25, X26&& x26, X27&& x27, X28&& x28
+ , X29&& x29, X30&& x30, X31&& x31, X32&& x32, X33&& x33, X34&& x34, X35&& x35
+ , X36&& x36, X37&& x37, X38&& x38, X39&& x39, X40&& x40, X41&& x41, X42&& x42
+ , X43&& x43, X44&& x44, X45&& x45, X46&& x46, X47&& x47, X48&& x48, X49&& x49
+ , X50&& x50, X51&& x51, X52&& x52, X53&& x53, X54&& x54, X55&& x55, X56&& x56
+ , Xn&& ...xn)
+ {
+ return f(static_cast<X1&&>(x1), f(static_cast<X2&&>(x2), f(static_cast<X3&&>(x3), f(static_cast<X4&&>(x4), f(static_cast<X5&&>(x5), f(static_cast<X6&&>(x6), f(static_cast<X7&&>(x7),
+ f(static_cast<X8&&>(x8), f(static_cast<X9&&>(x9), f(static_cast<X10&&>(x10), f(static_cast<X11&&>(x11), f(static_cast<X12&&>(x12), f(static_cast<X13&&>(x13), f(static_cast<X14&&>(x14),
+ f(static_cast<X15&&>(x15), f(static_cast<X16&&>(x16), f(static_cast<X17&&>(x17), f(static_cast<X18&&>(x18), f(static_cast<X19&&>(x19), f(static_cast<X20&&>(x20), f(static_cast<X21&&>(x21),
+ f(static_cast<X22&&>(x22), f(static_cast<X23&&>(x23), f(static_cast<X24&&>(x24), f(static_cast<X25&&>(x25), f(static_cast<X26&&>(x26), f(static_cast<X27&&>(x27), f(static_cast<X28&&>(x28),
+ f(static_cast<X29&&>(x29), f(static_cast<X30&&>(x30), f(static_cast<X31&&>(x31), f(static_cast<X32&&>(x32), f(static_cast<X33&&>(x33), f(static_cast<X34&&>(x34), f(static_cast<X35&&>(x35),
+ f(static_cast<X36&&>(x36), f(static_cast<X37&&>(x37), f(static_cast<X38&&>(x38), f(static_cast<X39&&>(x39), f(static_cast<X40&&>(x40), f(static_cast<X41&&>(x41), f(static_cast<X42&&>(x42),
+ f(static_cast<X43&&>(x43), f(static_cast<X44&&>(x44), f(static_cast<X45&&>(x45), f(static_cast<X46&&>(x46), f(static_cast<X47&&>(x47), f(static_cast<X48&&>(x48), f(static_cast<X49&&>(x49),
+ f(static_cast<X50&&>(x50), f(static_cast<X51&&>(x51), f(static_cast<X52&&>(x52), f(static_cast<X53&&>(x53), f(static_cast<X54&&>(x54), f(static_cast<X55&&>(x55),
+ foldr1_impl<sizeof...(xn) + 1>::apply(f, static_cast<X56&&>(x56), static_cast<Xn&&>(xn)...))))))))))))))))))))))))))))))))))))))))))))))))))))))));
+ }
+ };
+
+ struct foldr1_t {
+ template <typename F, typename X1, typename ...Xn>
+ constexpr decltype(auto) operator()(F&& f, X1&& x1, Xn&& ...xn) const {
+ return foldr1_impl<sizeof...(xn) + 1>::apply(
+ static_cast<F&&>(f), static_cast<X1&&>(x1), static_cast<Xn&&>(xn)...
+ );
+ }
+ };
+
+ constexpr foldr1_t foldr1{};
+
+ struct foldr_t {
+ template <typename F, typename State, typename ...Xn>
+ constexpr decltype(auto) operator()(F&& f, State&& state, Xn&& ...xn) const {
+ return foldr1_impl<sizeof...(xn) + 1>::apply(
+ static_cast<F&&>(f), static_cast<Xn&&>(xn)..., static_cast<State&&>(state)
+ );
+ }
+ };
+
+ constexpr foldr_t foldr{};
+}} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_VARIADIC_FOLDR1_HPP
diff --git a/boost/hana/detail/variadic/reverse_apply.hpp b/boost/hana/detail/variadic/reverse_apply.hpp
new file mode 100644
index 0000000000..08444a1035
--- /dev/null
+++ b/boost/hana/detail/variadic/reverse_apply.hpp
@@ -0,0 +1,27 @@
+/*!
+@file
+Defines `boost::hana::detail::variadic::reverse_apply`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_HPP
+#define BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/variadic/reverse_apply/unrolled.hpp>
+
+
+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)...
+ );
+ };
+}} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_HPP
diff --git a/boost/hana/detail/variadic/reverse_apply/flat.hpp b/boost/hana/detail/variadic/reverse_apply/flat.hpp
new file mode 100644
index 0000000000..6cd7bed53a
--- /dev/null
+++ b/boost/hana/detail/variadic/reverse_apply/flat.hpp
@@ -0,0 +1,41 @@
+/*!
+@file
+Defines `boost::hana::detail::variadic::reverse_apply_flat`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_FLAT_HPP
+#define BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_FLAT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/variadic/at.hpp>
+
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
+ template <int ...i, typename F, typename ...X>
+ constexpr decltype(auto)
+ reverse_apply_flat_helper(std::integer_sequence<int, i...>, F&& f, X&& ...x)
+ {
+ return static_cast<F&&>(f)(
+ detail::variadic::at<sizeof...(x) - i - 1>(
+ static_cast<X&&>(x)...
+ )...
+ );
+ }
+
+ template <typename F, typename ...X>
+ constexpr decltype(auto) reverse_apply_flat(F&& f, X&& ...x) {
+ return reverse_apply_flat_helper(
+ std::make_integer_sequence<int, sizeof...(x)>{},
+ static_cast<F&&>(f),
+ static_cast<X&&>(x)...
+ );
+ }
+}} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_FLAT_HPP
diff --git a/boost/hana/detail/variadic/reverse_apply/unrolled.hpp b/boost/hana/detail/variadic/reverse_apply/unrolled.hpp
new file mode 100644
index 0000000000..5cddf3c2c1
--- /dev/null
+++ b/boost/hana/detail/variadic/reverse_apply/unrolled.hpp
@@ -0,0 +1,87 @@
+/*!
+@file
+Defines `boost::hana::detail::variadic::reverse_apply_unrolled`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_UNROLLED_HPP
+#define BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_UNROLLED_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/functional/reverse_partial.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
+ struct reverse_apply_unrolled_impl {
+ template <typename F>
+ constexpr decltype(auto) operator()(F&& f) const {
+ return static_cast<F&&>(f)();
+ }
+
+ template <typename F, typename X1>
+ constexpr decltype(auto) operator()(F&& f, X1&& x1) const {
+ return static_cast<F&&>(f)(
+ static_cast<X1&&>(x1)
+ );
+ }
+
+ template <typename F, typename X1, typename X2>
+ constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2) const {
+ return static_cast<F&&>(f)(
+ static_cast<X2&&>(x2),
+ static_cast<X1&&>(x1)
+ );
+ }
+
+ template <typename F, typename X1, typename X2, typename X3>
+ constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3) const {
+ return static_cast<F&&>(f)(
+ static_cast<X3&&>(x3),
+ static_cast<X2&&>(x2),
+ static_cast<X1&&>(x1)
+ );
+ }
+
+ template <typename F, typename X1, typename X2, typename X3, typename X4>
+ constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4) const {
+ return static_cast<F&&>(f)(
+ static_cast<X4&&>(x4),
+ static_cast<X3&&>(x3),
+ static_cast<X2&&>(x2),
+ static_cast<X1&&>(x1)
+ );
+ }
+
+ template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5>
+ constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5) const {
+ return static_cast<F&&>(f)(
+ static_cast<X5&&>(x5),
+ static_cast<X4&&>(x4),
+ static_cast<X3&&>(x3),
+ static_cast<X2&&>(x2),
+ static_cast<X1&&>(x1)
+ );
+ }
+
+ template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename ...Xn>
+ constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, Xn&& ...xn) const {
+ return (*this)(hana::reverse_partial(
+ static_cast<F&&>(f)
+ , static_cast<X6&&>(x6)
+ , static_cast<X5&&>(x5)
+ , static_cast<X4&&>(x4)
+ , static_cast<X3&&>(x3)
+ , static_cast<X2&&>(x2)
+ , static_cast<X1&&>(x1)
+ ), static_cast<Xn&&>(xn)...);
+ }
+ };
+
+ constexpr reverse_apply_unrolled_impl reverse_apply_unrolled{};
+
+}} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_UNROLLED_HPP
diff --git a/boost/hana/detail/variadic/split_at.hpp b/boost/hana/detail/variadic/split_at.hpp
new file mode 100644
index 0000000000..07e75088a6
--- /dev/null
+++ b/boost/hana/detail/variadic/split_at.hpp
@@ -0,0 +1,153 @@
+/*!
+@file
+Defines `boost::hana::detail::variadic::split_at`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_VARIADIC_SPLIT_AT_HPP
+#define BOOST_HANA_DETAIL_VARIADIC_SPLIT_AT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/functional/reverse_partial.hpp>
+
+#include <cstddef>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
+ template <std::size_t n>
+ struct split_at_t {
+ template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename X8, typename ...Xs>
+ constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7, X8&& x8, Xs&& ...xs) const {
+ return split_at_t<n - 8>{}(
+ hana::partial(static_cast<F&&>(f),
+ static_cast<X1&&>(x1),
+ static_cast<X2&&>(x2),
+ static_cast<X3&&>(x3),
+ static_cast<X4&&>(x4),
+ static_cast<X5&&>(x5),
+ static_cast<X6&&>(x6),
+ static_cast<X7&&>(x7),
+ static_cast<X8&&>(x8)
+ ),
+ static_cast<Xs&&>(xs)...
+ );
+ }
+ };
+
+ template <>
+ struct split_at_t<0> {
+ template <typename F, typename ...Xs>
+ constexpr decltype(auto) operator()(F&& f, Xs&& ...xs) const {
+ return static_cast<F&&>(f)()(static_cast<Xs&&>(xs)...);
+ }
+ };
+
+ template <>
+ struct split_at_t<1> {
+ template <typename F, typename X1, typename ...Xs>
+ constexpr decltype(auto) operator()(F&& f, X1&& x1, Xs&& ...xs) const {
+ return static_cast<F&&>(f)(
+ static_cast<X1&&>(x1)
+ )(static_cast<Xs&&>(xs)...);
+ }
+ };
+
+ template <>
+ struct split_at_t<2> {
+ template <typename F, typename X1, typename X2, typename ...Xs>
+ constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, Xs&& ...xs) const {
+ return static_cast<F&&>(f)(
+ static_cast<X1&&>(x1),
+ static_cast<X2&&>(x2)
+ )(static_cast<Xs&&>(xs)...);
+ }
+ };
+
+ template <>
+ struct split_at_t<3> {
+ template <typename F, typename X1, typename X2, typename X3, typename ...Xs>
+ constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, Xs&& ...xs) const {
+ return static_cast<F&&>(f)(
+ static_cast<X1&&>(x1),
+ static_cast<X2&&>(x2),
+ static_cast<X3&&>(x3)
+ )(static_cast<Xs&&>(xs)...);
+ }
+ };
+
+ template <>
+ struct split_at_t<4> {
+ template <typename F, typename X1, typename X2, typename X3, typename X4, typename ...Xs>
+ constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, Xs&& ...xs) const {
+ return static_cast<F&&>(f)(
+ static_cast<X1&&>(x1),
+ static_cast<X2&&>(x2),
+ static_cast<X3&&>(x3),
+ static_cast<X4&&>(x4)
+ )(static_cast<Xs&&>(xs)...);
+ }
+ };
+
+ template <>
+ struct split_at_t<5> {
+ template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename ...Xs>
+ constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, Xs&& ...xs) const {
+ return static_cast<F&&>(f)(
+ static_cast<X1&&>(x1),
+ static_cast<X2&&>(x2),
+ static_cast<X3&&>(x3),
+ static_cast<X4&&>(x4),
+ static_cast<X5&&>(x5)
+ )(static_cast<Xs&&>(xs)...);
+ }
+ };
+
+ template <>
+ struct split_at_t<6> {
+ template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename ...Xs>
+ constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, Xs&& ...xs) const {
+ return static_cast<F&&>(f)(
+ static_cast<X1&&>(x1),
+ static_cast<X2&&>(x2),
+ static_cast<X3&&>(x3),
+ static_cast<X4&&>(x4),
+ static_cast<X5&&>(x5),
+ static_cast<X6&&>(x6)
+ )(static_cast<Xs&&>(xs)...);
+ }
+ };
+
+ template <>
+ struct split_at_t<7> {
+ template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename ...Xs>
+ constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7, Xs&& ...xs) const {
+ return static_cast<F&&>(f)(
+ static_cast<X1&&>(x1),
+ static_cast<X2&&>(x2),
+ static_cast<X3&&>(x3),
+ static_cast<X4&&>(x4),
+ static_cast<X5&&>(x5),
+ static_cast<X6&&>(x6),
+ static_cast<X7&&>(x7)
+ )(static_cast<Xs&&>(xs)...);
+ }
+ };
+
+ template <std::size_t n>
+ struct _makesplit_at_t {
+ template <typename ...Xs>
+ constexpr decltype(auto) operator()(Xs&& ...xs) const {
+ return hana::reverse_partial(split_at_t<n>{},
+ static_cast<Xs&&>(xs)...);
+ }
+ };
+
+ template <std::size_t n>
+ constexpr _makesplit_at_t<n> split_at{};
+}} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_VARIADIC_SPLIT_AT_HPP
diff --git a/boost/hana/detail/variadic/take.hpp b/boost/hana/detail/variadic/take.hpp
new file mode 100644
index 0000000000..01da4b5b29
--- /dev/null
+++ b/boost/hana/detail/variadic/take.hpp
@@ -0,0 +1,51 @@
+/*!
+@file
+Defines `boost::hana::detail::variadic::take`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_VARIADIC_TAKE_HPP
+#define BOOST_HANA_DETAIL_VARIADIC_TAKE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/variadic/split_at.hpp>
+#include <boost/hana/functional/always.hpp>
+#include <boost/hana/functional/reverse_partial.hpp>
+
+#include <cstddef>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
+ struct take_impl2 {
+ template <typename F, typename ...Xs>
+ constexpr decltype(auto) operator()(F&& f, Xs&& ...xs) const {
+ return static_cast<F&&>(f)(static_cast<Xs&&>(xs)...);
+ }
+ };
+
+ struct take_impl1 {
+ template <typename ...Xs>
+ constexpr auto operator()(Xs&& ...xs) const {
+ return hana::always(
+ reverse_partial(take_impl2{},
+ static_cast<Xs&&>(xs)...)
+ );
+ }
+ };
+
+ template <std::size_t n>
+ struct take_t {
+ template <typename ...Xs>
+ constexpr decltype(auto) operator()(Xs&& ...xs) const {
+ return variadic::split_at<n>(static_cast<Xs&&>(xs)...)(take_impl1{});
+ }
+ };
+
+ template <std::size_t n>
+ constexpr take_t<n> take{};
+}} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_VARIADIC_TAKE_HPP
diff --git a/boost/hana/detail/void_t.hpp b/boost/hana/detail/void_t.hpp
new file mode 100644
index 0000000000..f8152d378f
--- /dev/null
+++ b/boost/hana/detail/void_t.hpp
@@ -0,0 +1,21 @@
+/*!
+@file
+Defines an equivalent to the proposed `std::void_t`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_VOID_T_HPP
+#define BOOST_HANA_DETAIL_VOID_T_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <typename ...>
+ using void_t = void;
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_VOID_T_HPP
diff --git a/boost/hana/detail/wrong.hpp b/boost/hana/detail/wrong.hpp
new file mode 100644
index 0000000000..99ca630dd1
--- /dev/null
+++ b/boost/hana/detail/wrong.hpp
@@ -0,0 +1,33 @@
+/*!
+@file
+Defines `boost::hana::detail::wrong`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_WRONG_HPP
+#define BOOST_HANA_DETAIL_WRONG_HPP
+
+#include <boost/hana/config.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ //! @ingroup group-detail
+ //! Equivalent to a type-dependent `std::false_type`.
+ //!
+ //! This is useful for making a static assertion that would otherwise
+ //! always fire up dependent on some template parameters.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/detail/wrong.cpp
+ template <typename ...>
+ struct wrong : std::false_type { };
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_WRONG_HPP
diff --git a/boost/hana/difference.hpp b/boost/hana/difference.hpp
new file mode 100644
index 0000000000..a36223316b
--- /dev/null
+++ b/boost/hana/difference.hpp
@@ -0,0 +1,39 @@
+/*!
+@file
+Defines `boost::hana::difference`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DIFFERENCE_HPP
+#define BOOST_HANA_DIFFERENCE_HPP
+
+#include <boost/hana/fwd/difference.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Ys>
+ constexpr auto difference_t::operator()(Xs&& xs, Ys&& ys) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Difference = BOOST_HANA_DISPATCH_IF(difference_impl<S>,
+ true
+ );
+
+ return Difference::apply(static_cast<Xs&&>(xs), static_cast<Ys&&>(ys));
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct difference_impl<S, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DIFFERENCE_HPP
diff --git a/boost/hana/div.hpp b/boost/hana/div.hpp
new file mode 100644
index 0000000000..ff41a36118
--- /dev/null
+++ b/boost/hana/div.hpp
@@ -0,0 +1,107 @@
+/*!
+@file
+Defines `boost::hana::div`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DIV_HPP
+#define BOOST_HANA_DIV_HPP
+
+#include <boost/hana/fwd/div.hpp>
+
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/euclidean_ring.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/canonical_constant.hpp>
+#include <boost/hana/detail/has_common_embedding.hpp>
+#include <boost/hana/value.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename X, typename Y>
+ constexpr decltype(auto) div_t::operator()(X&& x, Y&& y) const {
+ using T = typename hana::tag_of<X>::type;
+ using U = typename hana::tag_of<Y>::type;
+ using Div = BOOST_HANA_DISPATCH_IF(decltype(div_impl<T, U>{}),
+ hana::EuclideanRing<T>::value &&
+ hana::EuclideanRing<U>::value &&
+ !is_default<div_impl<T, U>>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::EuclideanRing<T>::value,
+ "hana::div(x, y) requires 'x' to be an EuclideanRing");
+
+ static_assert(hana::EuclideanRing<U>::value,
+ "hana::div(x, y) requires 'y' to be an EuclideanRing");
+
+ static_assert(!is_default<div_impl<T, U>>::value,
+ "hana::div(x, y) requires 'x' and 'y' to be embeddable "
+ "in a common EuclideanRing");
+ #endif
+
+ return Div::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
+ }
+ //! @endcond
+
+ template <typename T, typename U, bool condition>
+ struct div_impl<T, U, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+
+ // Cross-type overload
+ template <typename T, typename U>
+ struct div_impl<T, U, when<
+ detail::has_nontrivial_common_embedding<EuclideanRing, T, U>::value
+ >> {
+ using C = typename common<T, U>::type;
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y) {
+ return hana::div(hana::to<C>(static_cast<X&&>(x)),
+ hana::to<C>(static_cast<Y&&>(y)));
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for integral data types
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T>
+ struct div_impl<T, T, when<std::is_integral<T>::value &&
+ !std::is_same<T, bool>::value>> {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y)
+ { return static_cast<X&&>(x) / static_cast<Y&&>(y); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for Constants over an EuclideanRing
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <typename C, typename X, typename Y>
+ struct constant_from_div {
+ static constexpr auto value = hana::div(hana::value<X>(), hana::value<Y>());
+ using hana_tag = detail::CanonicalConstant<typename C::value_type>;
+ };
+ }
+
+ template <typename C>
+ struct div_impl<C, C, when<
+ hana::Constant<C>::value &&
+ EuclideanRing<typename C::value_type>::value
+ >> {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X const&, Y const&)
+ { return hana::to<C>(detail::constant_from_div<C, X, Y>{}); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DIV_HPP
diff --git a/boost/hana/drop_back.hpp b/boost/hana/drop_back.hpp
new file mode 100644
index 0000000000..6869a8b9f9
--- /dev/null
+++ b/boost/hana/drop_back.hpp
@@ -0,0 +1,75 @@
+/*!
+@file
+Defines `boost::hana::drop_back`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DROP_BACK_HPP
+#define BOOST_HANA_DROP_BACK_HPP
+
+#include <boost/hana/fwd/drop_back.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/length.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename N>
+ constexpr auto drop_back_t::operator()(Xs&& xs, N const& n) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using DropBack = BOOST_HANA_DISPATCH_IF(drop_back_impl<S>,
+ hana::Sequence<S>::value &&
+ hana::IntegralConstant<N>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::drop_back(xs, n) requires 'xs' to be a Sequence");
+
+ static_assert(hana::IntegralConstant<N>::value,
+ "hana::drop_back(xs, n) requires 'n' to be an IntegralConstant");
+ #endif
+
+ static_assert(N::value >= 0,
+ "hana::drop_back(xs, n) requires 'n' to be non-negative");
+
+ return DropBack::apply(static_cast<Xs&&>(xs), n);
+ }
+
+ template <typename Xs>
+ constexpr auto drop_back_t::operator()(Xs&& xs) const {
+ return (*this)(static_cast<Xs&&>(xs), hana::size_c<1>);
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct drop_back_impl<S, when<condition>> : default_ {
+ template <typename Xs, std::size_t ...n>
+ static constexpr auto drop_back_helper(Xs&& xs, std::index_sequence<n...>) {
+ return hana::make<S>(hana::at_c<n>(static_cast<Xs&&>(xs))...);
+ }
+
+ template <typename Xs, typename N>
+ static constexpr auto apply(Xs&& xs, N const&) {
+ constexpr std::size_t n = N::value;
+ constexpr std::size_t len = decltype(hana::length(xs))::value;
+ return drop_back_helper(static_cast<Xs&&>(xs),
+ std::make_index_sequence<(n > len ? 0 : len - n)>{});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DROP_BACK_HPP
diff --git a/boost/hana/drop_front.hpp b/boost/hana/drop_front.hpp
new file mode 100644
index 0000000000..053a2f2b13
--- /dev/null
+++ b/boost/hana/drop_front.hpp
@@ -0,0 +1,57 @@
+/*!
+@file
+Defines `boost::hana::drop_front`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DROP_FRONT_HPP
+#define BOOST_HANA_DROP_FRONT_HPP
+
+#include <boost/hana/fwd/drop_front.hpp>
+
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/concept/iterable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/integral_constant.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename N>
+ constexpr auto drop_front_t::operator()(Xs&& xs, N const& n) const {
+ using It = typename hana::tag_of<Xs>::type;
+ using DropFront = BOOST_HANA_DISPATCH_IF(drop_front_impl<It>,
+ hana::Iterable<It>::value &&
+ hana::IntegralConstant<N>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Iterable<It>::value,
+ "hana::drop_front(xs, n) requires 'xs' to be an Iterable");
+
+ static_assert(hana::IntegralConstant<N>::value,
+ "hana::drop_front(xs, n) requires 'n' to be an IntegralConstant");
+ #endif
+
+ return DropFront::apply(static_cast<Xs&&>(xs), n);
+ }
+
+ template <typename Xs>
+ constexpr auto drop_front_t::operator()(Xs&& xs) const {
+ return (*this)(static_cast<Xs&&>(xs), hana::size_c<1>);
+ }
+ //! @endcond
+
+ template <typename It, bool condition>
+ struct drop_front_impl<It, when<condition>> : default_ {
+ template <typename Xs, typename N>
+ static constexpr auto apply(Xs&&, N const&) = delete;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DROP_FRONT_HPP
diff --git a/boost/hana/drop_front_exactly.hpp b/boost/hana/drop_front_exactly.hpp
new file mode 100644
index 0000000000..61b43c4e2a
--- /dev/null
+++ b/boost/hana/drop_front_exactly.hpp
@@ -0,0 +1,85 @@
+/*!
+@file
+Defines `boost::hana::drop_front_exactly`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DROP_FRONT_EXACTLY_HPP
+#define BOOST_HANA_DROP_FRONT_EXACTLY_HPP
+
+#include <boost/hana/fwd/drop_front_exactly.hpp>
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/concept/iterable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/drop_front.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/is_empty.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename N>
+ constexpr auto drop_front_exactly_t::operator()(Xs&& xs, N const& n) const {
+ using It = typename hana::tag_of<Xs>::type;
+ using DropFrontExactly = BOOST_HANA_DISPATCH_IF(drop_front_exactly_impl<It>,
+ hana::Iterable<It>::value &&
+ hana::IntegralConstant<N>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Iterable<It>::value,
+ "hana::drop_front_exactly(xs, n) requires 'xs' to be an Iterable");
+
+ static_assert(hana::IntegralConstant<N>::value,
+ "hana::drop_front_exactly(xs, n) requires 'n' to be an IntegralConstant");
+ #endif
+
+ static_assert(N::value >= 0,
+ "hana::drop_front_exactly(xs, n) requires 'n' to be non-negative");
+
+ return DropFrontExactly::apply(static_cast<Xs&&>(xs), n);
+ }
+
+ template <typename Xs>
+ constexpr auto drop_front_exactly_t::operator()(Xs&& xs) const {
+ return (*this)(static_cast<Xs&&>(xs), hana::size_c<1>);
+ }
+ //! @endcond
+
+ namespace detail {
+ template <typename Xs, typename N>
+ constexpr void check_dfe_overflow(Xs const& xs, N const&, hana::true_) {
+ constexpr bool n_overflew_length = decltype(
+ hana::is_empty(hana::drop_front(xs, hana::size_c<N::value - 1>))
+ )::value;
+ static_assert(!n_overflew_length,
+ "hana::drop_front_exactly(xs, n) requires 'n' to be less than or "
+ "equal to the number of elements in 'xs'");
+ }
+
+ template <typename Xs, typename N>
+ constexpr void check_dfe_overflow(Xs const&, N const&, hana::false_) { }
+ }
+
+ template <typename It, bool condition>
+ struct drop_front_exactly_impl<It, when<condition>> : default_ {
+ template <typename Xs, typename N>
+ static constexpr auto apply(Xs&& xs, N const& n) {
+ auto result = hana::drop_front(static_cast<Xs&&>(xs), n);
+ constexpr bool check_for_overflow =
+ decltype(hana::is_empty(result))::value && N::value != 0;
+
+ detail::check_dfe_overflow(xs, n, hana::bool_c<check_for_overflow>);
+
+ return result; // NRVO applied
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DROP_FRONT_EXACTLY_HPP
diff --git a/boost/hana/drop_while.hpp b/boost/hana/drop_while.hpp
new file mode 100644
index 0000000000..53f58cf26a
--- /dev/null
+++ b/boost/hana/drop_while.hpp
@@ -0,0 +1,93 @@
+/*!
+@file
+Defines `boost::hana::drop_while`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DROP_WHILE_HPP
+#define BOOST_HANA_DROP_WHILE_HPP
+
+#include <boost/hana/fwd/drop_while.hpp>
+
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/concept/iterable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/first_unsatisfied_index.hpp>
+#include <boost/hana/drop_front.hpp>
+#include <boost/hana/eval_if.hpp>
+#include <boost/hana/front.hpp>
+#include <boost/hana/is_empty.hpp>
+#include <boost/hana/lazy.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Pred>
+ constexpr auto drop_while_t::operator()(Xs&& xs, Pred&& pred) const {
+ using It = typename hana::tag_of<Xs>::type;
+ using DropWhile = BOOST_HANA_DISPATCH_IF(drop_while_impl<It>,
+ hana::Iterable<It>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Iterable<It>::value,
+ "hana::drop_while(xs, pred) requires 'xs' to be an Iterable");
+ #endif
+
+ return DropWhile::apply(static_cast<Xs&&>(xs), static_cast<Pred&&>(pred));
+ }
+ //! @endcond
+
+ namespace iterable_detail {
+ struct drop_while_helper {
+ struct next {
+ template <typename Xs, typename Pred>
+ constexpr decltype(auto) operator()(Xs&& xs, Pred&& pred) const {
+ return hana::drop_while(
+ hana::drop_front(static_cast<Xs&&>(xs)),
+ static_cast<Pred&&>(pred)
+ );
+ }
+ };
+
+ template <typename Xs, typename Pred>
+ constexpr decltype(auto) operator()(Xs&& xs, Pred&& pred) const {
+ return hana::eval_if(pred(hana::front(xs)),
+ hana::make_lazy(next{})(xs, pred),
+ hana::make_lazy(xs)
+ );
+ }
+ };
+ }
+
+ template <typename It, bool condition>
+ struct drop_while_impl<It, when<condition>> : default_ {
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs&& xs, Pred&& pred) {
+ return hana::eval_if(hana::is_empty(xs),
+ hana::make_lazy(xs),
+ hana::make_lazy(iterable_detail::drop_while_helper{})(
+ xs, static_cast<Pred&&>(pred))
+ );
+ }
+ };
+
+ template <typename S>
+ struct drop_while_impl<S, when<hana::Foldable<S>::value>> {
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs&& xs, Pred&&) {
+ using FirstUnsatisfied = decltype(
+ hana::unpack(static_cast<Xs&&>(xs),
+ detail::first_unsatisfied_index<Pred&&>{})
+ );
+ return hana::drop_front(static_cast<Xs&&>(xs),
+ FirstUnsatisfied{});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DROP_WHILE_HPP
diff --git a/boost/hana/duplicate.hpp b/boost/hana/duplicate.hpp
new file mode 100644
index 0000000000..1df6fb7a85
--- /dev/null
+++ b/boost/hana/duplicate.hpp
@@ -0,0 +1,48 @@
+/*!
+@file
+Defines `boost::hana::duplicate`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DUPLICATE_HPP
+#define BOOST_HANA_DUPLICATE_HPP
+
+#include <boost/hana/fwd/duplicate.hpp>
+
+#include <boost/hana/concept/comonad.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/extend.hpp>
+#include <boost/hana/functional/id.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename W_>
+ constexpr decltype(auto) duplicate_t::operator()(W_&& w) const {
+ using W = typename hana::tag_of<W_>::type;
+ using Duplicate = BOOST_HANA_DISPATCH_IF(duplicate_impl<W>,
+ hana::Comonad<W>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Comonad<W>::value,
+ "hana::duplicate(w) requires 'w' to be a Comonad");
+ #endif
+
+ return Duplicate::apply(static_cast<W_&&>(w));
+ }
+ //! @endcond
+
+ template <typename W, bool condition>
+ struct duplicate_impl<W, when<condition>> : default_ {
+ template <typename X>
+ static constexpr decltype(auto) apply(X&& x)
+ { return hana::extend(static_cast<X&&>(x), hana::id); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DUPLICATE_HPP
diff --git a/boost/hana/empty.hpp b/boost/hana/empty.hpp
new file mode 100644
index 0000000000..f20a5e5fff
--- /dev/null
+++ b/boost/hana/empty.hpp
@@ -0,0 +1,53 @@
+/*!
+@file
+Defines `boost::hana::empty`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EMPTY_HPP
+#define BOOST_HANA_EMPTY_HPP
+
+#include <boost/hana/fwd/empty.hpp>
+
+#include <boost/hana/concept/monad_plus.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename M>
+ struct empty_t {
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::MonadPlus<M>::value,
+ "hana::empty<M>() requires 'M' to be a MonadPlus");
+ #endif
+
+ constexpr auto operator()() const {
+ using Empty = BOOST_HANA_DISPATCH_IF(empty_impl<M>,
+ hana::MonadPlus<M>::value
+ );
+
+ return Empty::apply();
+ }
+ };
+
+ template <typename M, bool condition>
+ struct empty_impl<M, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+
+ template <typename S>
+ struct empty_impl<S, when<Sequence<S>::value>> {
+ static constexpr auto apply() {
+ return hana::make<S>();
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EMPTY_HPP
diff --git a/boost/hana/equal.hpp b/boost/hana/equal.hpp
new file mode 100644
index 0000000000..498f7a8a2b
--- /dev/null
+++ b/boost/hana/equal.hpp
@@ -0,0 +1,199 @@
+/*!
+@file
+Defines `boost::hana::equal`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EQUAL_HPP
+#define BOOST_HANA_EQUAL_HPP
+
+#include <boost/hana/fwd/equal.hpp>
+
+#include <boost/hana/accessors.hpp>
+#include <boost/hana/all_of.hpp>
+#include <boost/hana/and.hpp>
+#include <boost/hana/at.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/product.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/concept/struct.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/common.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/detail/concepts.hpp>
+#include <boost/hana/detail/dependent_on.hpp>
+#include <boost/hana/detail/has_common_embedding.hpp>
+#include <boost/hana/detail/nested_to.hpp> // required by fwd decl
+#include <boost/hana/first.hpp>
+#include <boost/hana/if.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/second.hpp>
+#include <boost/hana/value.hpp>
+
+#include <cstddef>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename X, typename Y>
+ constexpr auto equal_t::operator()(X&& x, Y&& y) const {
+ using T = typename hana::tag_of<X>::type;
+ using U = typename hana::tag_of<Y>::type;
+ using Equal = equal_impl<T, U>;
+ return Equal::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
+ }
+ //! @endcond
+
+ template <typename T, typename U, bool condition>
+ struct equal_impl<T, U, when<condition>> : default_ {
+ template <typename X, typename Y>
+ static constexpr auto apply(X const&, Y const&) {
+ using T_ = detail::dependent_on_t<sizeof(X) == 1, T>;
+ static_assert(!hana::is_convertible<T_, U>::value &&
+ !hana::is_convertible<U, T_>::value,
+ "No default implementation of hana::equal is provided for related "
+ "types that can't be safely embedded into a common type, because "
+ "those are most likely programming errors. If this is really what "
+ "you want, you can manually convert both objects to a common "
+ "Comparable type before performing the comparison.");
+
+ return hana::false_c;
+ }
+ };
+
+ // Cross-type overload
+ template <typename T, typename U>
+ struct equal_impl<T, U, when<
+ detail::has_nontrivial_common_embedding<Comparable, T, U>::value &&
+ !detail::EqualityComparable<T, U>::value
+ >> {
+ using C = typename hana::common<T, U>::type;
+ template <typename X, typename Y>
+ static constexpr auto apply(X&& x, Y&& y) {
+ return hana::equal(hana::to<C>(static_cast<X&&>(x)),
+ hana::to<C>(static_cast<Y&&>(y)));
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for EqualityComparable data types
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T, typename U>
+ struct equal_impl<T, U, when<detail::EqualityComparable<T, U>::value>> {
+ template <typename X, typename Y>
+ static constexpr auto apply(X&& x, Y&& y)
+ { return static_cast<X&&>(x) == static_cast<Y&&>(y); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for Constants wrapping a Comparable
+ //////////////////////////////////////////////////////////////////////////
+ template <typename C>
+ struct equal_impl<C, C, when<
+ hana::Constant<C>::value &&
+ Comparable<typename C::value_type>::value
+ >> {
+ template <typename X, typename Y>
+ static constexpr auto apply(X const&, Y const&) {
+ constexpr auto eq = hana::equal(hana::value<X>(), hana::value<Y>());
+ constexpr bool truth_value = hana::if_(eq, true, false);
+ return hana::bool_c<truth_value>;
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Comparable for Products
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T, typename U>
+ struct equal_impl<T, U, when<hana::Product<T>::value && hana::Product<U>::value>> {
+ template <typename X, typename Y>
+ static constexpr auto apply(X const& x, Y const& y) {
+ return hana::and_(
+ hana::equal(hana::first(x), hana::first(y)),
+ hana::equal(hana::second(x), hana::second(y))
+ );
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Comparable for Sequences
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <typename Xs, typename Ys, std::size_t Length>
+ struct compare_finite_sequences {
+ Xs const& xs;
+ Ys const& ys;
+
+ template <std::size_t i>
+ constexpr auto apply(hana::false_, hana::true_) const {
+ return compare_finite_sequences::apply<i+1>(
+ hana::bool_c<i+1 == Length>,
+ hana::if_(hana::equal(hana::at_c<i>(xs), hana::at_c<i>(ys)),
+ hana::true_c, hana::false_c)
+ );
+ }
+
+ template <std::size_t i>
+ constexpr auto apply(hana::false_, hana::false_) const
+ { return hana::false_c; }
+
+ template <std::size_t i, typename Result>
+ constexpr auto apply(hana::true_, Result r) const
+ { return r; }
+
+ template <std::size_t i>
+ constexpr bool apply(hana::false_, bool b) const {
+ return b && compare_finite_sequences::apply<i+1>(
+ hana::bool_c<i+1 == Length>,
+ hana::if_(hana::equal(hana::at_c<i>(xs), hana::at_c<i>(ys)),
+ hana::true_c, hana::false_c)
+ );
+ }
+ };
+ }
+
+ template <typename T, typename U>
+ struct equal_impl<T, U, when<Sequence<T>::value && hana::Sequence<U>::value>> {
+ template <typename Xs, typename Ys>
+ static constexpr auto apply(Xs const& xs, Ys const& ys) {
+ constexpr std::size_t xs_size = decltype(hana::length(xs))::value;
+ constexpr std::size_t ys_size = decltype(hana::length(ys))::value;
+ detail::compare_finite_sequences<Xs, Ys, xs_size> comp{xs, ys};
+ return comp.template apply<0>(hana::bool_c<xs_size == 0>,
+ hana::bool_c<xs_size == ys_size>);
+ }
+ };
+
+ namespace detail {
+ template <typename X, typename Y>
+ struct compare_struct_members {
+ X const& x;
+ Y const& y;
+
+ template <typename Member>
+ constexpr auto operator()(Member&& member) const {
+ auto accessor = hana::second(static_cast<Member&&>(member));
+ return hana::equal(accessor(x), accessor(y));
+ }
+ };
+ }
+
+ template <typename S>
+ struct equal_impl<S, S, when<hana::Struct<S>::value>> {
+ template <typename X, typename Y>
+ static constexpr auto apply(X const& x, Y const& y) {
+ return hana::all_of(hana::accessors<S>(),
+ detail::compare_struct_members<X, Y>{x, y});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EQUAL_HPP
diff --git a/boost/hana/erase_key.hpp b/boost/hana/erase_key.hpp
new file mode 100644
index 0000000000..20648f3c29
--- /dev/null
+++ b/boost/hana/erase_key.hpp
@@ -0,0 +1,37 @@
+/*!
+@file
+Defines `boost::hana::erase_key`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_ERASE_KEY_HPP
+#define BOOST_HANA_ERASE_KEY_HPP
+
+#include <boost/hana/fwd/erase_key.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Set, typename ...Args>
+ constexpr decltype(auto) erase_key_t::operator()(Set&& set, Args&& ...args) const {
+ return erase_key_impl<typename hana::tag_of<Set>::type>::apply(
+ static_cast<Set&&>(set),
+ static_cast<Args&&>(args)...
+ );
+ }
+ //! @endcond
+
+ template <typename T, bool condition>
+ struct erase_key_impl<T, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_ERASE_KEY_HPP
diff --git a/boost/hana/eval.hpp b/boost/hana/eval.hpp
new file mode 100644
index 0000000000..1881c18277
--- /dev/null
+++ b/boost/hana/eval.hpp
@@ -0,0 +1,57 @@
+/*!
+@file
+Defines `boost::hana::eval`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EVAL_HPP
+#define BOOST_HANA_EVAL_HPP
+
+#include <boost/hana/fwd/eval.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/wrong.hpp>
+#include <boost/hana/functional/id.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Expr>
+ constexpr decltype(auto) eval_t::operator()(Expr&& expr) const {
+ return eval_impl<typename hana::tag_of<Expr>::type>::apply(
+ static_cast<Expr&&>(expr)
+ );
+ }
+ //! @endcond
+
+ template <typename T, bool condition>
+ struct eval_impl<T, when<condition>> : default_ {
+ template <typename Expr>
+ static constexpr auto eval_helper(Expr&& expr, int)
+ -> decltype(static_cast<Expr&&>(expr)())
+ { return static_cast<Expr&&>(expr)(); }
+
+ template <typename Expr>
+ static constexpr auto eval_helper(Expr&& expr, long)
+ -> decltype(static_cast<Expr&&>(expr)(hana::id))
+ { return static_cast<Expr&&>(expr)(hana::id); }
+
+ template <typename Expr>
+ static constexpr auto eval_helper(Expr&&, ...) {
+ static_assert(detail::wrong<Expr>{},
+ "hana::eval(expr) requires the expression to be a hana::lazy, "
+ "a nullary Callable or a unary Callable that may be "
+ "called with hana::id");
+ }
+
+ template <typename Expr>
+ static constexpr decltype(auto) apply(Expr&& expr)
+ { return eval_helper(static_cast<Expr&&>(expr), int{}); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EVAL_HPP
diff --git a/boost/hana/eval_if.hpp b/boost/hana/eval_if.hpp
new file mode 100644
index 0000000000..e98d987447
--- /dev/null
+++ b/boost/hana/eval_if.hpp
@@ -0,0 +1,93 @@
+/*!
+@file
+Defines `boost::hana::eval_if`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EVAL_IF_HPP
+#define BOOST_HANA_EVAL_IF_HPP
+
+#include <boost/hana/fwd/eval_if.hpp>
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/logical.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/eval.hpp>
+#include <boost/hana/if.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Cond, typename Then, typename Else>
+ constexpr decltype(auto) eval_if_t::operator()(Cond&& cond, Then&& then, Else&& else_) const {
+ using Bool = typename hana::tag_of<Cond>::type;
+ using EvalIf = BOOST_HANA_DISPATCH_IF(eval_if_impl<Bool>,
+ hana::Logical<Bool>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Logical<Bool>::value,
+ "hana::eval_if(cond, then, else) requires 'cond' to be a Logical");
+ #endif
+
+ return EvalIf::apply(static_cast<Cond&&>(cond),
+ static_cast<Then&&>(then),
+ static_cast<Else&&>(else_));
+ }
+ //! @endcond
+
+ template <typename L, bool condition>
+ struct eval_if_impl<L, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for arithmetic data types
+ //////////////////////////////////////////////////////////////////////////
+ template <typename L>
+ struct eval_if_impl<L, when<std::is_arithmetic<L>::value>> {
+ template <typename Cond, typename T, typename E>
+ static constexpr auto apply(Cond const& cond, T&& t, E&& e) {
+ return cond ? hana::eval(static_cast<T&&>(t))
+ : hana::eval(static_cast<E&&>(e));
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for Constants over a Logical
+ //////////////////////////////////////////////////////////////////////////
+ template <typename C>
+ struct eval_if_impl<C, when<
+ hana::Constant<C>::value &&
+ Logical<typename C::value_type>::value
+ >> {
+ template <typename Then, typename Else>
+ static constexpr decltype(auto)
+ eval_if_helper(hana::true_, Then&& t, Else&&)
+ { return hana::eval(static_cast<Then&&>(t)); }
+
+ template <typename Then, typename Else>
+ static constexpr decltype(auto)
+ eval_if_helper(hana::false_, Then&&, Else&& e)
+ { return hana::eval(static_cast<Else&&>(e)); }
+
+ template <typename Cond, typename Then, typename Else>
+ static constexpr decltype(auto) apply(Cond const&, Then&& t, Else&& e) {
+ constexpr auto cond = hana::value<Cond>();
+ constexpr bool truth_value = hana::if_(cond, true, false);
+ return eval_if_helper(hana::bool_c<truth_value>,
+ static_cast<Then&&>(t),
+ static_cast<Else&&>(e));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EVAL_IF_HPP
diff --git a/boost/hana/experimental/printable.hpp b/boost/hana/experimental/printable.hpp
new file mode 100644
index 0000000000..d904b53c25
--- /dev/null
+++ b/boost/hana/experimental/printable.hpp
@@ -0,0 +1,243 @@
+/*
+@file
+Defines `boost::hana::experimental::print`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXPERIMENTAL_PRINTABLE_HPP
+#define BOOST_HANA_EXPERIMENTAL_PRINTABLE_HPP
+
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/product.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/first.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/intersperse.hpp>
+#include <boost/hana/second.hpp>
+#include <boost/hana/transform.hpp>
+#include <boost/hana/tuple.hpp>
+
+// models for different containers
+#include <boost/hana/fwd/map.hpp>
+#include <boost/hana/fwd/optional.hpp>
+#include <boost/hana/fwd/set.hpp>
+#include <boost/hana/fwd/string.hpp>
+#include <boost/hana/fwd/type.hpp>
+
+#include <boost/core/demangle.hpp>
+
+#include <iostream>
+#include <regex>
+#include <sstream>
+#include <string>
+#include <typeinfo>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace experimental {
+ //! @cond
+ template <typename T, typename = void>
+ struct print_impl : print_impl<T, hana::when<true>> { };
+
+ template <typename T, bool condition>
+ struct print_impl<T, hana::when<condition>> : hana::default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+ //! @endcond
+
+ //! @ingroup group-experimental
+ //! Returns a string representation of the given object.
+ //!
+ //! This function is defined for most containers provided by Hana, and
+ //! also for objects that define an `operator<<` that can be used with
+ //! a `std::basic_ostream`. It can recursively print containers within
+ //! containers, but do not expect any kind of proper indentation.
+ //!
+ //! This function requires (the rest of) Boost to be available on the
+ //! system. It also requires RTTI to be enabled.
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ auto print = [](auto const& x) -> std::string {
+ return tag-dispatched;
+ };
+#else
+ struct print_t {
+ template <typename T>
+ std::string operator()(T const& t) const {
+ using Print = print_impl<typename hana::tag_of<T>::type>;
+ return Print::apply(t);
+ }
+ };
+
+ constexpr print_t print{};
+#endif
+
+ // Define the `Printable` concept
+ template <typename T>
+ struct Printable {
+ using Tag = typename hana::tag_of<T>::type;
+ static constexpr bool value = !hana::is_default<print_impl<Tag>>::value;
+ };
+
+ namespace print_detail {
+ std::string strip_type_junk(std::string const& str) {
+ return std::regex_replace(str, std::regex("^([a-z_]+::)*([a-z_]*)_t<"), "$2<");
+ }
+ }
+
+ // model for Sequences
+ template <typename S>
+ struct print_impl<S, hana::when<hana::Sequence<S>::value>> {
+ template <typename Xs>
+ static std::string apply(Xs const& xs) {
+ std::string result = "(";
+ auto comma_separated = hana::intersperse(xs, ", ");
+ hana::for_each(comma_separated, [&result](auto const& x) {
+ result += hana::experimental::print(x);
+ });
+ result += ")";
+ return result;
+ }
+ };
+
+ // model for OutputStreamable types
+ template <typename S>
+ struct print_impl<S, hana::when_valid<decltype(
+ std::declval<std::ostringstream&>() << std::declval<S const&>()
+ )>> {
+ template <typename T>
+ static std::string apply(T const& t) {
+ std::ostringstream os;
+ os << t;
+ return os.str();
+ }
+ };
+
+ // model for hana::optional
+ template <>
+ struct print_impl<hana::optional_tag> {
+ template <typename O>
+ static std::string apply(O const& optional) {
+ return hana::maybe("nothing",
+ [](auto const& x) {
+ return "just(" + hana::experimental::print(x) + ")";
+ }, optional);
+ }
+ };
+
+ // model for hana::maps
+ template <>
+ struct print_impl<hana::map_tag> {
+ template <typename M>
+ static std::string apply(M const& map) {
+ std::string result = "{";
+ auto pairs = hana::transform(hana::to_tuple(map),
+ [](auto const& pair) {
+ return hana::experimental::print(hana::first(pair))
+ + " => "
+ + hana::experimental::print(hana::second(pair));
+ });
+ auto comma_separated = hana::intersperse(pairs, ", ");
+ hana::for_each(comma_separated, [&result](auto const& element) {
+ result += element;
+ });
+ result += "}";
+ return result;
+ }
+ };
+
+ // model for hana::metafunctions
+ template <template <typename ...> class F>
+ struct print_impl<hana::metafunction_t<F>> {
+ template <typename T>
+ static std::string apply(T const&) {
+ return print_detail::strip_type_junk(boost::core::demangle(typeid(T).name()));
+ }
+ };
+
+ // model for hana::metafunction_classes
+ template <typename F>
+ struct print_impl<hana::metafunction_class_t<F>> {
+ template <typename T>
+ static std::string apply(T const&) {
+ return print_detail::strip_type_junk(boost::core::demangle(typeid(T).name()));
+ }
+ };
+
+ // model for Constants holding a `Printable`
+ template <typename C>
+ struct print_impl<C, hana::when<
+ hana::Constant<C>::value &&
+ Printable<typename C::value_type>::value
+ >> {
+ template <typename T>
+ static std::string apply(T const&) {
+ constexpr auto value = hana::value<T>();
+ return hana::experimental::print(value);
+ }
+ };
+
+ // model for Products
+ template <typename P>
+ struct print_impl<P, hana::when<hana::Product<P>::value>> {
+ template <typename T>
+ static std::string apply(T const& t) {
+ return '(' + hana::experimental::print(hana::first(t))
+ + ", "
+ + hana::experimental::print(hana::second(t)) + ')';
+ }
+ };
+
+ // model for hana::strings
+ template <>
+ struct print_impl<hana::string_tag> {
+ template <typename S>
+ static std::string apply(S const& s) {
+ return '"' + std::string{hana::to<char const*>(s)} + '"';
+ }
+ };
+
+ // model for hana::sets
+ template <>
+ struct print_impl<hana::set_tag> {
+ template <typename S>
+ static std::string apply(S const& set) {
+ std::string result = "{";
+ auto as_tuple = hana::transform(hana::to_tuple(set),
+ hana::experimental::print);
+ auto comma_separated = hana::intersperse(as_tuple, ", ");
+ hana::for_each(comma_separated, [&result](auto const& element) {
+ result += element;
+ });
+ result += "}";
+ return result;
+ }
+ };
+
+ // model for hana::templates
+ template <template <typename ...> class F>
+ struct print_impl<template_t<F>> {
+ template <typename T>
+ static std::string apply(T const&) {
+ return print_detail::strip_type_junk(boost::core::demangle(typeid(T).name()));
+ }
+ };
+
+ // model for hana::types
+ template <>
+ struct print_impl<hana::type_tag> {
+ template <typename T>
+ static std::string apply(T const&) {
+ using Type = typename T::type;
+ return "type<" + boost::core::demangle(typeid(Type).name()) + '>';
+ }
+ };
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXPERIMENTAL_PRINTABLE_HPP
diff --git a/boost/hana/experimental/types.hpp b/boost/hana/experimental/types.hpp
new file mode 100644
index 0000000000..4a3c107994
--- /dev/null
+++ b/boost/hana/experimental/types.hpp
@@ -0,0 +1,178 @@
+/*!
+@file
+Defines `boost::hana::experimental::types`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXPERIMENTAL_TYPES_HPP
+#define BOOST_HANA_EXPERIMENTAL_TYPES_HPP
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/metafunction.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/any_of.hpp>
+#include <boost/hana/fwd/at.hpp>
+#include <boost/hana/fwd/contains.hpp>
+#include <boost/hana/fwd/core/tag_of.hpp>
+#include <boost/hana/fwd/equal.hpp>
+#include <boost/hana/fwd/is_empty.hpp>
+#include <boost/hana/fwd/transform.hpp>
+#include <boost/hana/fwd/unpack.hpp>
+#include <boost/hana/type.hpp>
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace experimental {
+ //! @ingroup group-experimental
+ //! Container optimized for holding types.
+ //!
+ //! It is often useful to manipulate a sequence that contains types
+ //! only, without any associated runtime value. This container allows
+ //! storing and manipulating pure types in a much more compile-time
+ //! efficient manner than using `hana::tuple`, which must assume that
+ //! its contents might have runtime values.
+ template <typename ...T>
+ struct types;
+
+ struct types_tag;
+
+ //////////////////////////////////////////////////////////////////////
+
+ template <typename ...T>
+ struct types { };
+ } // end namespace experimental
+
+ template <typename ...T>
+ struct tag_of<experimental::types<T...>> {
+ using type = experimental::types_tag;
+ };
+
+ // Foldable
+ template <>
+ struct unpack_impl<hana::experimental::types_tag> {
+ template <typename ...T, typename F, typename = typename std::enable_if<
+ !hana::Metafunction<F>::value
+ >::type>
+ static constexpr decltype(auto) apply(hana::experimental::types<T...> const&, F&& f) {
+ return static_cast<F&&>(f)(hana::type<T>{}...);
+ }
+
+ template <typename ...T, typename F, typename = typename std::enable_if<
+ hana::Metafunction<F>::value
+ >::type>
+ static constexpr hana::type<typename F::template apply<T...>::type>
+ apply(hana::experimental::types<T...> const&, F const&) { return {}; }
+ };
+
+ // Functor
+ template <>
+ struct transform_impl<hana::experimental::types_tag> {
+ template <typename ...T, typename F, typename = typename std::enable_if<
+ !hana::Metafunction<F>::value
+ >::type>
+ static constexpr auto apply(hana::experimental::types<T...> const&, F&& f)
+ -> hana::experimental::types<typename decltype(f(hana::type<T>{}))::type...>
+ { return {}; }
+
+ template <typename ...T, typename F, typename = typename std::enable_if<
+ hana::Metafunction<F>::value
+ >::type>
+ static constexpr hana::experimental::types<typename F::template apply<T>::type...>
+ apply(hana::experimental::types<T...> const&, F const&) { return {}; }
+ };
+
+ namespace types_detail {
+ template <std::size_t I, typename T>
+ struct elt { using type = T; };
+
+ template <typename Indices, typename ...T>
+ struct indexer;
+
+ template <std::size_t ...I, typename ...T>
+ struct indexer<std::index_sequence<I...>, T...>
+ : elt<I, T>...
+ { };
+
+ template <std::size_t I, typename T>
+ elt<I, T> get_elt(elt<I, T> const&);
+ }
+
+ // Iterable
+ template <>
+ struct at_impl<hana::experimental::types_tag> {
+ template <typename ...T, typename N>
+ static constexpr auto
+ apply(hana::experimental::types<T...> const&, N const&) {
+ using Indexer = types_detail::indexer<std::make_index_sequence<sizeof...(T)>, T...>;
+ using Nth = typename decltype(types_detail::get_elt<N::value>(Indexer{}))::type;
+ return hana::type<Nth>{};
+ }
+ };
+
+ template <>
+ struct is_empty_impl<hana::experimental::types_tag> {
+ template <typename ...T>
+ static constexpr hana::bool_<sizeof...(T) == 0>
+ apply(hana::experimental::types<T...> const&)
+ { return {}; }
+ };
+
+ template <>
+ struct drop_front_impl<hana::experimental::types_tag> {
+ template <std::size_t n, typename Indexer, std::size_t ...i>
+ static hana::experimental::types<
+ typename decltype(types_detail::get_elt<i + n>(Indexer{}))::type...
+ > helper(std::index_sequence<i...>);
+
+ template <typename ...T, typename N>
+ static constexpr auto
+ apply(hana::experimental::types<T...> const&, N const&) {
+ constexpr std::size_t n = N::value > sizeof...(T) ? sizeof...(T) : N::value;
+ using Indices = std::make_index_sequence<sizeof...(T) - n>;
+ using Indexer = types_detail::indexer<std::make_index_sequence<sizeof...(T)>, T...>;
+ return decltype(helper<n, Indexer>(Indices{})){};
+ }
+ };
+
+ // Searchable
+ template <>
+ struct contains_impl<hana::experimental::types_tag> {
+ template <typename U>
+ struct is_same_as {
+ template <typename T>
+ struct apply {
+ static constexpr bool value = std::is_same<U, T>::value;
+ };
+ };
+
+ template <typename ...T, typename U>
+ static constexpr auto apply(hana::experimental::types<T...> const&, U const&)
+ -> hana::bool_<
+ detail::any_of<is_same_as<typename U::type>::template apply, T...>::value
+ >
+ { return {}; }
+
+ static constexpr hana::false_ apply(...) { return {}; }
+ };
+
+ // Comparable
+ template <>
+ struct equal_impl<hana::experimental::types_tag, hana::experimental::types_tag> {
+ template <typename Types>
+ static constexpr hana::true_ apply(Types const&, Types const&)
+ { return {}; }
+
+ template <typename Ts, typename Us>
+ static constexpr hana::false_ apply(Ts const&, Us const&)
+ { return {}; }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXPERIMENTAL_TYPES_HPP
diff --git a/boost/hana/experimental/view.hpp b/boost/hana/experimental/view.hpp
new file mode 100644
index 0000000000..e47674c25d
--- /dev/null
+++ b/boost/hana/experimental/view.hpp
@@ -0,0 +1,512 @@
+/*
+@file
+Defines experimental views.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXPERIMENTAL_VIEW_HPP
+#define BOOST_HANA_EXPERIMENTAL_VIEW_HPP
+
+#include <boost/hana/and.hpp>
+#include <boost/hana/at.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/detail/decay.hpp>
+#include <boost/hana/fold_left.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/fwd/ap.hpp>
+#include <boost/hana/fwd/concat.hpp>
+#include <boost/hana/fwd/drop_front.hpp>
+#include <boost/hana/fwd/empty.hpp>
+#include <boost/hana/fwd/equal.hpp>
+#include <boost/hana/fwd/flatten.hpp>
+#include <boost/hana/fwd/is_empty.hpp>
+#include <boost/hana/fwd/less.hpp>
+#include <boost/hana/fwd/lift.hpp>
+#include <boost/hana/fwd/transform.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/lexicographical_compare.hpp>
+#include <boost/hana/range.hpp>
+#include <boost/hana/tuple.hpp>
+#include <boost/hana/unpack.hpp>
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+// Pros of views
+// - No temporary container created between algorithms
+// - Lazy, so only the minimum is required
+//
+// Cons of views
+// - Reference semantics mean possibility for dangling references
+// - Lose the ability to move from temporary containers
+// - When fetching the members of a view multiple times, no caching is done.
+// So for example, `t = transform(xs, f); at_c<0>(t); at_c<0>(t)` will
+// compute `f(at_c<0>(xs))` twice.
+// - push_back creates a joint_view and a single_view. The single_view holds
+// the value as a member. When doing multiple push_backs, we end up with a
+// joint_view<xxx, joint_view<single_view<T>, joint_view<single_view<T>, ....>>>
+// which contains a reference to `xxx` and all the `T`s by value. Such a
+// "view" is not cheap to copy, which is inconsistent with the usual
+// expectations about views.
+
+BOOST_HANA_NAMESPACE_BEGIN
+
+namespace experimental {
+ struct view_tag;
+
+ namespace detail {
+ template <typename Sequence>
+ struct is_view {
+ static constexpr bool value = false;
+ };
+
+ template <typename Sequence>
+ using view_storage = typename std::conditional<
+ detail::is_view<Sequence>::value, Sequence, Sequence&
+ >::type;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // sliced_view
+ //////////////////////////////////////////////////////////////////////////
+ template <typename Sequence, std::size_t ...indices>
+ struct sliced_view_t {
+ detail::view_storage<Sequence> sequence_;
+ using hana_tag = view_tag;
+ };
+
+ template <typename Sequence, typename Indices>
+ constexpr auto sliced(Sequence& sequence, Indices const& indices) {
+ return hana::unpack(indices, [&](auto ...i) {
+ return sliced_view_t<Sequence, decltype(i)::value...>{sequence};
+ });
+ }
+
+ namespace detail {
+ template <typename Sequence, std::size_t ...i>
+ struct is_view<sliced_view_t<Sequence, i...>> {
+ static constexpr bool value = true;
+ };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // transformed_view
+ //////////////////////////////////////////////////////////////////////////
+ template <typename Sequence, typename F>
+ struct transformed_view_t {
+ detail::view_storage<Sequence> sequence_;
+ F f_;
+ using hana_tag = view_tag;
+ };
+
+ template <typename Sequence, typename F>
+ constexpr transformed_view_t<Sequence, typename std::decay<F>::type>
+ transformed(Sequence& sequence, F&& f) {
+ return {sequence, static_cast<F&&>(f)};
+ }
+
+ namespace detail {
+ template <typename Sequence, typename F>
+ struct is_view<transformed_view_t<Sequence, F>> {
+ static constexpr bool value = true;
+ };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // filtered_view
+ //////////////////////////////////////////////////////////////////////////
+#if 0
+ template <typename Sequence, typename Pred>
+ using filtered_view_t = sliced_view_t<Sequence, detail::filtered_indices<...>>;
+
+ template <typename Sequence, typename Pred>
+ constexpr filtered_view_t<Sequence, Pred> filtered(Sequence& sequence, Pred&& pred) {
+ return {sequence};
+ }
+#endif
+
+ //////////////////////////////////////////////////////////////////////////
+ // joined_view
+ //////////////////////////////////////////////////////////////////////////
+ template <typename Sequence1, typename Sequence2>
+ struct joined_view_t {
+ detail::view_storage<Sequence1> sequence1_;
+ detail::view_storage<Sequence2> sequence2_;
+ using hana_tag = view_tag;
+ };
+
+ struct make_joined_view_t {
+ template <typename Sequence1, typename Sequence2>
+ constexpr joined_view_t<Sequence1, Sequence2> operator()(Sequence1& s1, Sequence2& s2) const {
+ return {s1, s2};
+ }
+ };
+ constexpr make_joined_view_t joined{};
+
+ namespace detail {
+ template <typename Sequence1, typename Sequence2>
+ struct is_view<joined_view_t<Sequence1, Sequence2>> {
+ static constexpr bool value = true;
+ };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // single_view
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T>
+ struct single_view_t {
+ T value_;
+ using hana_tag = view_tag;
+ };
+
+ template <typename T>
+ constexpr single_view_t<typename hana::detail::decay<T>::type> single_view(T&& t) {
+ return {static_cast<T&&>(t)};
+ }
+
+ namespace detail {
+ template <typename T>
+ struct is_view<single_view_t<T>> {
+ static constexpr bool value = true;
+ };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // empty_view
+ //////////////////////////////////////////////////////////////////////////
+ struct empty_view_t {
+ using hana_tag = view_tag;
+ };
+
+ constexpr empty_view_t empty_view() {
+ return {};
+ }
+
+ namespace detail {
+ template <>
+ struct is_view<empty_view_t> {
+ static constexpr bool value = true;
+ };
+ }
+} // end namespace experimental
+
+//////////////////////////////////////////////////////////////////////////
+// Foldable
+//////////////////////////////////////////////////////////////////////////
+template <>
+struct unpack_impl<experimental::view_tag> {
+ // sliced_view
+ template <typename Sequence, std::size_t ...i, typename F>
+ static constexpr decltype(auto)
+ apply(experimental::sliced_view_t<Sequence, i...> view, F&& f) {
+ return static_cast<F&&>(f)(hana::at_c<i>(view.sequence_)...);
+ }
+
+ // transformed_view
+ template <typename Sequence, typename F, typename G>
+ static constexpr decltype(auto)
+ apply(experimental::transformed_view_t<Sequence, F> view, G&& g) {
+ return hana::unpack(view.sequence_, hana::on(static_cast<G&&>(g), view.f_));
+ }
+
+ // joined_view
+ template <typename View, typename F, std::size_t ...i1, std::size_t ...i2>
+ static constexpr decltype(auto)
+ unpack_joined(View view, F&& f, std::index_sequence<i1...>,
+ std::index_sequence<i2...>)
+ {
+ return static_cast<F&&>(f)(hana::at_c<i1>(view.sequence1_)...,
+ hana::at_c<i2>(view.sequence2_)...);
+ }
+
+ template <typename S1, typename S2, typename F>
+ static constexpr decltype(auto)
+ apply(experimental::joined_view_t<S1, S2> view, F&& f) {
+ constexpr auto N1 = decltype(hana::length(view.sequence1_))::value;
+ constexpr auto N2 = decltype(hana::length(view.sequence2_))::value;
+ return unpack_joined(view, static_cast<F&&>(f),
+ std::make_index_sequence<N1>{},
+ std::make_index_sequence<N2>{});
+ }
+
+ // single_view
+ template <typename T, typename F>
+ static constexpr decltype(auto) apply(experimental::single_view_t<T> view, F&& f) {
+ return static_cast<F&&>(f)(view.value_);
+ }
+
+ // empty_view
+ template <typename F>
+ static constexpr decltype(auto) apply(experimental::empty_view_t, F&& f) {
+ return static_cast<F&&>(f)();
+ }
+};
+
+//////////////////////////////////////////////////////////////////////////
+// Iterable
+//////////////////////////////////////////////////////////////////////////
+template <>
+struct at_impl<experimental::view_tag> {
+ // sliced_view
+ template <typename Sequence, std::size_t ...i, typename N>
+ static constexpr decltype(auto)
+ apply(experimental::sliced_view_t<Sequence, i...> view, N const&) {
+ constexpr std::size_t indices[] = {i...};
+ constexpr std::size_t n = indices[N::value];
+ return hana::at_c<n>(view.sequence_);
+ }
+
+ // transformed_view
+ template <typename Sequence, typename F, typename N>
+ static constexpr decltype(auto)
+ apply(experimental::transformed_view_t<Sequence, F> view, N const& n) {
+ return view.f_(hana::at(view.sequence_, n));
+ }
+
+ // joined_view
+ template <std::size_t Left, typename View, typename N>
+ static constexpr decltype(auto) at_joined_view(View view, N const&, hana::true_) {
+ return hana::at_c<N::value>(view.sequence1_);
+ }
+
+ template <std::size_t Left, typename View, typename N>
+ static constexpr decltype(auto) at_joined_view(View view, N const&, hana::false_) {
+ return hana::at_c<N::value - Left>(view.sequence2_);
+ }
+
+ template <typename S1, typename S2, typename N>
+ static constexpr decltype(auto)
+ apply(experimental::joined_view_t<S1, S2> view, N const& n) {
+ constexpr auto Left = decltype(hana::length(view.sequence1_))::value;
+ return at_joined_view<Left>(view, n, hana::bool_c<(N::value < Left)>);
+ }
+
+ // single_view
+ template <typename T, typename N>
+ static constexpr decltype(auto) apply(experimental::single_view_t<T> view, N const&) {
+ static_assert(N::value == 0,
+ "trying to fetch an out-of-bounds element in a hana::single_view");
+ return view.value_;
+ }
+
+ // empty_view
+ template <typename N>
+ static constexpr decltype(auto) apply(experimental::empty_view_t, N const&) = delete;
+};
+
+template <>
+struct length_impl<experimental::view_tag> {
+ // sliced_view
+ template <typename Sequence, std::size_t ...i>
+ static constexpr auto
+ apply(experimental::sliced_view_t<Sequence, i...>) {
+ return hana::size_c<sizeof...(i)>;
+ }
+
+ // transformed_view
+ template <typename Sequence, typename F>
+ static constexpr auto apply(experimental::transformed_view_t<Sequence, F> view) {
+ return hana::length(view.sequence_);
+ }
+
+ // joined_view
+ template <typename S1, typename S2>
+ static constexpr auto apply(experimental::joined_view_t<S1, S2> view) {
+ return hana::size_c<
+ decltype(hana::length(view.sequence1_))::value +
+ decltype(hana::length(view.sequence2_))::value
+ >;
+ }
+
+ // single_view
+ template <typename T>
+ static constexpr auto apply(experimental::single_view_t<T>) {
+ return hana::size_c<1>;
+ }
+
+ // empty_view
+ static constexpr auto apply(experimental::empty_view_t) {
+ return hana::size_c<0>;
+ }
+};
+
+template <>
+struct is_empty_impl<experimental::view_tag> {
+ // sliced_view
+ template <typename Sequence, std::size_t ...i>
+ static constexpr auto
+ apply(experimental::sliced_view_t<Sequence, i...>) {
+ return hana::bool_c<sizeof...(i) == 0>;
+ }
+
+ // transformed_view
+ template <typename Sequence, typename F>
+ static constexpr auto apply(experimental::transformed_view_t<Sequence, F> view) {
+ return hana::is_empty(view.sequence_);
+ }
+
+ // joined_view
+ template <typename S1, typename S2>
+ static constexpr auto apply(experimental::joined_view_t<S1, S2> view) {
+ return hana::and_(hana::is_empty(view.sequence1_),
+ hana::is_empty(view.sequence2_));
+ }
+
+ // single_view
+ template <typename T>
+ static constexpr auto apply(experimental::single_view_t<T>) {
+ return hana::false_c;
+ }
+
+ // empty_view
+ static constexpr auto apply(experimental::empty_view_t) {
+ return hana::true_c;
+ }
+};
+
+template <>
+struct drop_front_impl<experimental::view_tag> {
+ template <typename View, typename N>
+ static constexpr auto apply(View view, N const&) {
+ constexpr auto n = N::value;
+ constexpr auto Length = decltype(hana::length(view))::value;
+ return experimental::sliced(view, hana::range_c<std::size_t, n, Length>);
+ }
+};
+
+//////////////////////////////////////////////////////////////////////////
+// Functor
+//////////////////////////////////////////////////////////////////////////
+template <>
+struct transform_impl<experimental::view_tag> {
+ template <typename Sequence, typename F, typename G>
+ static constexpr auto
+ apply(experimental::transformed_view_t<Sequence, F> view, G&& g) {
+ return experimental::transformed(view.sequence_,
+ hana::compose(static_cast<G&&>(g), view.f_));
+ }
+
+ template <typename View, typename F>
+ static constexpr auto apply(View view, F&& f) {
+ return experimental::transformed(view, static_cast<F&&>(f));
+ }
+};
+
+//////////////////////////////////////////////////////////////////////////
+// Applicative
+//////////////////////////////////////////////////////////////////////////
+template <>
+struct lift_impl<experimental::view_tag> {
+ template <typename T>
+ static constexpr auto apply(T&& t) {
+ return experimental::single_view(static_cast<T&&>(t));
+ }
+};
+
+template <>
+struct ap_impl<experimental::view_tag> {
+ template <typename F, typename X>
+ static constexpr auto apply(F&& f, X&& x) {
+ // TODO: Implement cleverly; we most likely need a cartesian_product
+ // view or something like that.
+ return hana::ap(hana::to_tuple(f), hana::to_tuple(x));
+ }
+};
+
+//////////////////////////////////////////////////////////////////////////
+// Monad
+//////////////////////////////////////////////////////////////////////////
+template <>
+struct flatten_impl<experimental::view_tag> {
+ template <typename View>
+ static constexpr auto apply(View view) {
+ // TODO: Implement a flattened_view instead
+ return hana::fold_left(view, experimental::empty_view(),
+ experimental::joined);
+ }
+};
+
+//////////////////////////////////////////////////////////////////////////
+// MonadPlus
+//////////////////////////////////////////////////////////////////////////
+template <>
+struct concat_impl<experimental::view_tag> {
+ template <typename View1, typename View2>
+ static constexpr auto apply(View1 view1, View2 view2) {
+ return experimental::joined(view1, view2);
+ }
+};
+
+template <>
+struct empty_impl<experimental::view_tag> {
+ static constexpr auto apply() {
+ return experimental::empty_view();
+ }
+};
+
+//////////////////////////////////////////////////////////////////////////
+// Comparable
+//////////////////////////////////////////////////////////////////////////
+template <>
+struct equal_impl<experimental::view_tag, experimental::view_tag> {
+ template <typename View1, typename View2>
+ static constexpr auto apply(View1 v1, View2 v2) {
+ // TODO: Use a lexicographical comparison algorithm.
+ return hana::equal(hana::to_tuple(v1), hana::to_tuple(v2));
+ }
+};
+
+template <typename S>
+struct equal_impl<experimental::view_tag, S, hana::when<hana::Sequence<S>::value>> {
+ template <typename View1, typename Seq>
+ static constexpr auto apply(View1 v1, Seq const& s) {
+ // TODO: Use a lexicographical comparison algorithm.
+ return hana::equal(hana::to_tuple(v1), hana::to_tuple(s));
+ }
+};
+
+template <typename S>
+struct equal_impl<S, experimental::view_tag, hana::when<hana::Sequence<S>::value>> {
+ template <typename Seq, typename View2>
+ static constexpr auto apply(Seq const& s, View2 v2) {
+ // TODO: Use a lexicographical comparison algorithm.
+ return hana::equal(hana::to_tuple(s), hana::to_tuple(v2));
+ }
+};
+
+//////////////////////////////////////////////////////////////////////////
+// Orderable
+//////////////////////////////////////////////////////////////////////////
+template <>
+struct less_impl<experimental::view_tag, experimental::view_tag> {
+ template <typename View1, typename View2>
+ static constexpr auto apply(View1 v1, View2 v2) {
+ return hana::lexicographical_compare(v1, v2);
+ }
+};
+
+template <typename S>
+struct less_impl<experimental::view_tag, S, hana::when<hana::Sequence<S>::value>> {
+ template <typename View1, typename Seq>
+ static constexpr auto apply(View1 v1, Seq const& s) {
+ return hana::lexicographical_compare(v1, s);
+ }
+};
+
+template <typename S>
+struct less_impl<S, experimental::view_tag, hana::when<hana::Sequence<S>::value>> {
+ template <typename Seq, typename View2>
+ static constexpr auto apply(Seq const& s, View2 v2) {
+ return hana::lexicographical_compare(s, v2);
+ }
+};
+
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXPERIMENTAL_VIEW_HPP
diff --git a/boost/hana/ext/boost.hpp b/boost/hana/ext/boost.hpp
new file mode 100644
index 0000000000..2d735c1469
--- /dev/null
+++ b/boost/hana/ext/boost.hpp
@@ -0,0 +1,21 @@
+/*!
+@file
+Includes all the adaptors for external Boost libraries.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXT_BOOST_HPP
+#define BOOST_HANA_EXT_BOOST_HPP
+
+//! @ingroup group-ext
+//! @defgroup group-ext-boost Other Boost adapters
+//! Adapters for miscellaneous heterogeneous containers in Boost.
+
+#include <boost/hana/ext/boost/fusion.hpp>
+#include <boost/hana/ext/boost/mpl.hpp>
+#include <boost/hana/ext/boost/tuple.hpp>
+
+#endif // !BOOST_HANA_EXT_BOOST_HPP
diff --git a/boost/hana/ext/boost/fusion.hpp b/boost/hana/ext/boost/fusion.hpp
new file mode 100644
index 0000000000..dd80e22b5a
--- /dev/null
+++ b/boost/hana/ext/boost/fusion.hpp
@@ -0,0 +1,22 @@
+/*!
+@file
+Includes all the adaptors for the Boost.Fusion library.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXT_BOOST_FUSION_HPP
+#define BOOST_HANA_EXT_BOOST_FUSION_HPP
+
+//! @ingroup group-ext
+//! @defgroup group-ext-fusion Boost.Fusion adapters
+//! Adapters for Boost.Fusion containers.
+
+#include <boost/hana/ext/boost/fusion/deque.hpp>
+#include <boost/hana/ext/boost/fusion/list.hpp>
+#include <boost/hana/ext/boost/fusion/tuple.hpp>
+#include <boost/hana/ext/boost/fusion/vector.hpp>
+
+#endif // !BOOST_HANA_EXT_BOOST_FUSION_HPP
diff --git a/boost/hana/ext/boost/fusion/deque.hpp b/boost/hana/ext/boost/fusion/deque.hpp
new file mode 100644
index 0000000000..bdf8c14b84
--- /dev/null
+++ b/boost/hana/ext/boost/fusion/deque.hpp
@@ -0,0 +1,108 @@
+/*!
+@file
+Adapts `boost::fusion::deque` for use with Hana.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXT_BOOST_FUSION_DEQUE_HPP
+#define BOOST_HANA_EXT_BOOST_FUSION_DEQUE_HPP
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/ext/boost/fusion/detail/common.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+#include <boost/hana/fwd/core/tag_of.hpp>
+#include <boost/hana/fwd/drop_front.hpp>
+#include <boost/hana/length.hpp>
+
+#include <boost/fusion/container/deque.hpp>
+#include <boost/fusion/container/generation/make_deque.hpp>
+#include <boost/fusion/support/tag_of.hpp>
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+namespace boost { namespace fusion {
+ //! @ingroup group-ext-fusion
+ //! Adapter for Boost.Fusion deques.
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! A Fusion deque is a model of the `Sequence` concept, and all the
+ //! concepts it refines. That makes it essentially the same as a Hana
+ //! tuple, although the complexity of some operations might differ from
+ //! that of a tuple.
+ //!
+ //! @include example/ext/boost/fusion/deque.cpp
+ template <typename ...T>
+ struct deque { };
+}}
+#endif
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace ext { namespace boost { namespace fusion {
+ struct deque_tag;
+ }}}
+
+ template <typename T>
+ struct tag_of<T, when<
+ std::is_same<
+ typename ::boost::fusion::traits::tag_of<T>::type,
+ ::boost::fusion::traits::tag_of<
+ ::boost::fusion::deque<>
+ >::type
+ >::value
+ >> {
+ using type = ext::boost::fusion::deque_tag;
+ };
+
+ namespace detail {
+ template <>
+ struct is_fusion_sequence<ext::boost::fusion::deque_tag> {
+ static constexpr bool value = true;
+ };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Iterable (the rest is in detail/common.hpp)
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct drop_front_impl<ext::boost::fusion::deque_tag> {
+ template <std::size_t n, typename Xs, std::size_t ...i>
+ static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence<i...>) {
+ return hana::make<ext::boost::fusion::deque_tag>(
+ hana::at_c<n + i>(static_cast<Xs&&>(xs))...
+ );
+ }
+
+ template <typename Xs, typename N>
+ static constexpr auto apply(Xs&& xs, N const&) {
+ constexpr std::size_t n = N::value;
+ constexpr std::size_t len = decltype(hana::length(xs))::value;
+ return drop_front_helper<n>(static_cast<Xs&&>(xs),
+ std::make_index_sequence<(n < len ? len - n : 0)>{});
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Sequence
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct make_impl<ext::boost::fusion::deque_tag> {
+ template <typename ...Xs>
+ static constexpr auto apply(Xs&& ...xs) {
+ return ::boost::fusion::make_deque(static_cast<Xs&&>(xs)...);
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXT_BOOST_FUSION_DEQUE_HPP
diff --git a/boost/hana/ext/boost/fusion/detail/common.hpp b/boost/hana/ext/boost/fusion/detail/common.hpp
new file mode 100644
index 0000000000..c6ba922be5
--- /dev/null
+++ b/boost/hana/ext/boost/fusion/detail/common.hpp
@@ -0,0 +1,79 @@
+/*!
+@file
+Defines common methods for all Boost.Fusion sequences.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXT_BOOST_FUSION_DETAIL_COMMON_HPP
+#define BOOST_HANA_EXT_BOOST_FUSION_DETAIL_COMMON_HPP
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/fwd/at.hpp>
+#include <boost/hana/fwd/concept/sequence.hpp>
+#include <boost/hana/fwd/is_empty.hpp>
+#include <boost/hana/fwd/length.hpp>
+#include <boost/hana/integral_constant.hpp>
+
+#include <boost/fusion/sequence/intrinsic/at.hpp>
+#include <boost/fusion/sequence/intrinsic/empty.hpp>
+#include <boost/fusion/sequence/intrinsic/size.hpp>
+
+#include <cstddef>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace detail {
+ template <typename T>
+ struct is_fusion_sequence {
+ static constexpr bool value = false;
+ };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Iterable
+ //////////////////////////////////////////////////////////////////////////
+ template <typename S>
+ struct at_impl<S, when<detail::is_fusion_sequence<S>::value>> {
+ template <typename Xs, typename N>
+ static constexpr decltype(auto) apply(Xs&& xs, N const&) {
+ constexpr std::size_t n = N::value;
+ return boost::fusion::at_c<n>(static_cast<Xs&&>(xs));
+ }
+ };
+
+ template <typename S>
+ struct is_empty_impl<S, when<detail::is_fusion_sequence<S>::value>> {
+ template <typename Xs>
+ static constexpr auto apply(Xs&& xs) {
+ using Empty = decltype(boost::fusion::empty(xs));
+ return hana::bool_c<Empty::value>;
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Foldable
+ //////////////////////////////////////////////////////////////////////////
+ template <typename S>
+ struct length_impl<S, when<detail::is_fusion_sequence<S>::value>> {
+ template <typename Xs>
+ static constexpr auto apply(Xs const&) {
+ using Size = typename boost::fusion::result_of::size<Xs>::type;
+ return hana::size_c<Size::value>;
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Sequence
+ //////////////////////////////////////////////////////////////////////////
+ template <typename S>
+ struct Sequence<S, when<detail::is_fusion_sequence<S>::value>> {
+ static constexpr bool value = true;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXT_BOOST_FUSION_DETAIL_COMMON_HPP
diff --git a/boost/hana/ext/boost/fusion/list.hpp b/boost/hana/ext/boost/fusion/list.hpp
new file mode 100644
index 0000000000..0f30f7e7f8
--- /dev/null
+++ b/boost/hana/ext/boost/fusion/list.hpp
@@ -0,0 +1,111 @@
+/*!
+@file
+Adapts `boost::fusion::list` for use with Hana.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXT_BOOST_FUSION_LIST_HPP
+#define BOOST_HANA_EXT_BOOST_FUSION_LIST_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/ext/boost/fusion/detail/common.hpp>
+#include <boost/hana/fwd/at.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+#include <boost/hana/fwd/core/tag_of.hpp>
+#include <boost/hana/fwd/drop_front.hpp>
+#include <boost/hana/fwd/length.hpp>
+
+#include <boost/fusion/algorithm/transformation/pop_front.hpp>
+#include <boost/fusion/container/generation/make_list.hpp>
+#include <boost/fusion/container/list.hpp>
+#include <boost/fusion/container/list/convert.hpp>
+#include <boost/fusion/support/tag_of.hpp>
+#include <boost/version.hpp>
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+namespace boost { namespace fusion {
+ //! @ingroup group-ext-fusion
+ //! Adapter for Boost.Fusion lists.
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! A Fusion list is a model of the `Sequence` concept, and all the
+ //! concepts it refines. That makes it essentially the same as a Hana
+ //! tuple, although the complexity of some operations might differ from
+ //! that of a tuple.
+ //!
+ //! @include example/ext/boost/fusion/list.cpp
+ template <typename ...T>
+ struct list { };
+}}
+#endif
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace ext { namespace boost { namespace fusion {
+ struct list_tag;
+ }}}
+
+ template <typename T>
+ struct tag_of<T, when<
+ std::is_same<
+ typename ::boost::fusion::traits::tag_of<T>::type,
+ ::boost::fusion::traits::tag_of<
+ ::boost::fusion::list<>
+ >::type
+ >::value
+ >> {
+ using type = ext::boost::fusion::list_tag;
+ };
+
+ namespace detail {
+ template <>
+ struct is_fusion_sequence<ext::boost::fusion::list_tag> {
+ static constexpr bool value = true;
+ };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Iterable (the rest is in detail/common.hpp)
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct drop_front_impl<ext::boost::fusion::list_tag> {
+ template <std::size_t n, typename Xs, std::size_t ...i>
+ static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence<i...>) {
+ return hana::make<ext::boost::fusion::list_tag>(
+ hana::at_c<n + i>(static_cast<Xs&&>(xs))...
+ );
+ }
+
+ template <typename Xs, typename N>
+ static constexpr auto apply(Xs&& xs, N const&) {
+ constexpr std::size_t n = N::value;
+ constexpr std::size_t len = decltype(hana::length(xs))::value;
+ return drop_front_helper<n>(static_cast<Xs&&>(xs),
+ std::make_index_sequence<(n < len ? len - n : 0)>{});
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Sequence
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct make_impl<ext::boost::fusion::list_tag> {
+ template <typename ...Xs>
+ static constexpr auto apply(Xs&& ...xs) {
+ return ::boost::fusion::make_list(static_cast<Xs&&>(xs)...);
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXT_BOOST_FUSION_LIST_HPP
diff --git a/boost/hana/ext/boost/fusion/tuple.hpp b/boost/hana/ext/boost/fusion/tuple.hpp
new file mode 100644
index 0000000000..d3e0757911
--- /dev/null
+++ b/boost/hana/ext/boost/fusion/tuple.hpp
@@ -0,0 +1,49 @@
+/*!
+@file
+Adapts `boost::fusion::tuple` for use with Hana.
+
+In the current version of Boost.Fusion, `boost::fusion::tuple` is basically
+an alias to `boost::fusion::vector`, so both data types share the same
+implementation in Hana.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXT_BOOST_FUSION_TUPLE_HPP
+#define BOOST_HANA_EXT_BOOST_FUSION_TUPLE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/ext/boost/fusion/vector.hpp>
+
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+namespace boost { namespace fusion {
+ //! @ingroup group-ext-fusion
+ //! Adapter for Boost.Fusion tuples.
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! A Fusion tuple is a model of the `Sequence` concept, and all the
+ //! concepts it refines. That makes it essentially the same as a Hana
+ //! tuple, although the complexity of some operations might differ from
+ //! that of a tuple.
+ //!
+ //! @include example/ext/boost/fusion/tuple.cpp
+ template <typename ...T>
+ struct tuple { };
+}}
+#endif
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace ext { namespace boost { namespace fusion {
+ // In the current version of Boost.Fusion, `boost::fusion::tuple` is
+ // basically an alias to `boost::fusion::vector`, hence the alias.
+ using tuple_tag = vector_tag;
+ }}}
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXT_BOOST_FUSION_TUPLE_HPP
diff --git a/boost/hana/ext/boost/fusion/vector.hpp b/boost/hana/ext/boost/fusion/vector.hpp
new file mode 100644
index 0000000000..8cf9bdbe50
--- /dev/null
+++ b/boost/hana/ext/boost/fusion/vector.hpp
@@ -0,0 +1,110 @@
+/*!
+@file
+Adapts `boost::fusion::vector` for use with Hana.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXT_BOOST_FUSION_VECTOR_HPP
+#define BOOST_HANA_EXT_BOOST_FUSION_VECTOR_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/ext/boost/fusion/detail/common.hpp>
+#include <boost/hana/fwd/at.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+#include <boost/hana/fwd/core/tag_of.hpp>
+#include <boost/hana/fwd/drop_front.hpp>
+#include <boost/hana/fwd/length.hpp>
+
+#include <boost/fusion/algorithm/transformation/pop_front.hpp>
+#include <boost/fusion/container/generation/make_vector.hpp>
+#include <boost/fusion/container/vector.hpp>
+#include <boost/fusion/container/vector/convert.hpp>
+#include <boost/fusion/support/tag_of.hpp>
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+namespace boost { namespace fusion {
+ //! @ingroup group-ext-fusion
+ //! Adapter for Boost.Fusion vectors.
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! A Fusion vector is a model of the `Sequence` concept, and all the
+ //! concepts it refines. That makes it essentially the same as a Hana
+ //! tuple, although the complexity of some operations might differ from
+ //! that of a tuple.
+ //!
+ //! @include example/ext/boost/fusion/vector.cpp
+ template <typename ...T>
+ struct vector { };
+}}
+#endif
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace ext { namespace boost { namespace fusion {
+ struct vector_tag;
+ }}}
+
+ template <typename T>
+ struct tag_of<T, when<
+ std::is_same<
+ typename ::boost::fusion::traits::tag_of<T>::type,
+ ::boost::fusion::traits::tag_of<
+ ::boost::fusion::vector<>
+ >::type
+ >::value
+ >> {
+ using type = ext::boost::fusion::vector_tag;
+ };
+
+ namespace detail {
+ template <>
+ struct is_fusion_sequence<ext::boost::fusion::vector_tag> {
+ static constexpr bool value = true;
+ };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Iterable (the rest is in detail/common.hpp)
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct drop_front_impl<ext::boost::fusion::vector_tag> {
+ template <std::size_t n, typename Xs, std::size_t ...i>
+ static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence<i...>) {
+ return hana::make<ext::boost::fusion::vector_tag>(
+ hana::at_c<n + i>(static_cast<Xs&&>(xs))...
+ );
+ }
+
+ template <typename Xs, typename N>
+ static constexpr auto apply(Xs&& xs, N const&) {
+ constexpr std::size_t n = N::value;
+ constexpr std::size_t len = decltype(hana::length(xs))::value;
+ return drop_front_helper<n>(static_cast<Xs&&>(xs),
+ std::make_index_sequence<(n < len ? len - n : 0)>{});
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Sequence
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct make_impl<ext::boost::fusion::vector_tag> {
+ template <typename ...Xs>
+ static constexpr auto apply(Xs&& ...xs) {
+ return ::boost::fusion::make_vector(static_cast<Xs&&>(xs)...);
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXT_BOOST_FUSION_VECTOR_HPP
diff --git a/boost/hana/ext/boost/mpl.hpp b/boost/hana/ext/boost/mpl.hpp
new file mode 100644
index 0000000000..02bf0e1b0f
--- /dev/null
+++ b/boost/hana/ext/boost/mpl.hpp
@@ -0,0 +1,21 @@
+/*!
+@file
+Includes all the adaptors for the Boost.MPL library.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXT_BOOST_MPL_HPP
+#define BOOST_HANA_EXT_BOOST_MPL_HPP
+
+//! @ingroup group-ext
+//! @defgroup group-ext-mpl Boost.MPL adapters
+//! Adapters for Boost.MPL containers.
+
+#include <boost/hana/ext/boost/mpl/integral_c.hpp>
+#include <boost/hana/ext/boost/mpl/list.hpp>
+#include <boost/hana/ext/boost/mpl/vector.hpp>
+
+#endif // !BOOST_HANA_EXT_BOOST_MPL_HPP
diff --git a/boost/hana/ext/boost/mpl/integral_c.hpp b/boost/hana/ext/boost/mpl/integral_c.hpp
new file mode 100644
index 0000000000..ef2cad0239
--- /dev/null
+++ b/boost/hana/ext/boost/mpl/integral_c.hpp
@@ -0,0 +1,81 @@
+/*!
+@file
+Adapts Boost.MPL IntegralConstants for use with Hana.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXT_BOOST_MPL_INTEGRAL_C_HPP
+#define BOOST_HANA_EXT_BOOST_MPL_INTEGRAL_C_HPP
+
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/fwd/core/to.hpp>
+
+#include <boost/mpl/integral_c.hpp>
+#include <boost/mpl/integral_c_tag.hpp>
+
+#include <type_traits>
+
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+namespace boost { namespace mpl {
+ //! @ingroup group-ext-mpl
+ //! Adapter for IntegralConstants from the Boost.MPL.
+ //!
+ //! Provided models
+ //! ---------------
+ //! 1. `Constant` and `IntegralConstant`\n
+ //! A Boost.MPL IntegralConstant is a model of the `IntegralConstant`
+ //! and `Constant` concepts just like `hana::integral_constant`s are.
+ //! As a consequence, they are also implicitly a model of the concepts
+ //! provided for all models of `Constant`.
+ //! @include example/ext/boost/mpl/integral_c/integral_constant.cpp
+ template <typename T, T v>
+ struct integral_c { };
+}}
+#endif
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace ext { namespace boost { namespace mpl {
+ template <typename T>
+ struct integral_c_tag { using value_type = T; };
+ }}}
+
+ template <typename T>
+ struct tag_of<T, when<
+ std::is_same<
+ typename T::tag,
+ ::boost::mpl::integral_c_tag
+ >::value
+ >> {
+ using type = ext::boost::mpl::integral_c_tag<
+ typename hana::tag_of<typename T::value_type>::type
+ >;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // IntegralConstant/Constant
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T>
+ struct IntegralConstant<ext::boost::mpl::integral_c_tag<T>> {
+ static constexpr bool value = true;
+ };
+
+ template <typename T, typename C>
+ struct to_impl<ext::boost::mpl::integral_c_tag<T>, C,
+ when<hana::IntegralConstant<C>::value>
+ > : embedding<is_embedded<typename C::value_type, T>::value> {
+ template <typename N>
+ static constexpr auto apply(N const&) {
+ return ::boost::mpl::integral_c<T, N::value>{};
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXT_BOOST_MPL_INTEGRAL_C_HPP
diff --git a/boost/hana/ext/boost/mpl/list.hpp b/boost/hana/ext/boost/mpl/list.hpp
new file mode 100644
index 0000000000..9e569a7d08
--- /dev/null
+++ b/boost/hana/ext/boost/mpl/list.hpp
@@ -0,0 +1,186 @@
+/*!
+@file
+Adapts `boost::mpl::list` for use with Hana.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXT_BOOST_MPL_LIST_HPP
+#define BOOST_HANA_EXT_BOOST_MPL_LIST_HPP
+
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/ext/boost/mpl/integral_c.hpp>
+#include <boost/hana/fwd/at.hpp>
+#include <boost/hana/fwd/core/to.hpp>
+#include <boost/hana/fwd/core/tag_of.hpp>
+#include <boost/hana/fwd/drop_front.hpp>
+#include <boost/hana/fwd/equal.hpp>
+#include <boost/hana/fwd/is_empty.hpp>
+#include <boost/hana/fwd/less.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/type.hpp>
+#include <boost/hana/unpack.hpp>
+
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/empty.hpp>
+#include <boost/mpl/equal.hpp>
+#include <boost/mpl/list.hpp>
+#include <boost/mpl/sequence_tag.hpp>
+#include <boost/mpl/size.hpp>
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+namespace boost { namespace mpl {
+ //! @ingroup group-ext-mpl
+ //! Adapter for Boost.MPL lists.
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! It is possible for MPL lists to model a couple of concepts.
+ //! However, because they are only able to hold types, they lack
+ //! the generality required to model concepts like `Functor`,
+ //! `Sequence` and other related concepts.
+ //!
+ //! 1. `Comparable`\n
+ //! Two MPL lists are equal if and only if they contain the same
+ //! number of types, and if all those types are equal.
+ //! @include example/ext/boost/mpl/list/comparable.cpp
+ //!
+ //! 2. `Foldable`\n
+ //! Folding a MPL list is equivalent to folding it as a `Sequence`.
+ //! @include example/ext/boost/mpl/list/foldable.cpp
+ //!
+ //! 3. `Iterable`\n
+ //! Iterating over a MPL list is just iterating over each of the
+ //! types it contains, as if it were a `Sequence`.
+ //! @include example/ext/boost/mpl/list/iterable.cpp
+ //!
+ //! 4. `Searchable`\n
+ //! A MPL list can be searched as if it were a tuple containing
+ //! `hana::type`s.
+ //! @include example/ext/boost/mpl/list/searchable.cpp
+ //!
+ //!
+ //! Conversion from any `Foldable`
+ //! ------------------------------
+ //! A MPL list can be created from any `Foldable`. More precisely,
+ //! for a `Foldable` `xs` whose linearization is `[x1, ..., xn]`,
+ //! @code
+ //! to<ext::boost::mpl::list_tag>(xs) == mpl::list<t1, ..., tn>{}
+ //! @endcode
+ //! where `tk` is the type of `xk`, or the type contained in `xk` if
+ //! `xk` is a `hana::type`.
+ //! @warning
+ //! The limitations on the size of `mpl::list`s are inherited by
+ //! this conversion utility, and hence trying to convert a `Foldable`
+ //! containing more than [BOOST_MPL_LIMIT_LIST_SIZE][1] elements is
+ //! an error.
+ //! @include example/ext/boost/mpl/list/conversion.cpp
+ //!
+ //! [1]: http://www.boost.org/doc/libs/release/libs/mpl/doc/refmanual/limit-list-size.html
+ template <typename ...T>
+ struct list { };
+}}
+#endif
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace ext { namespace boost { namespace mpl {
+ using list_tag = ::boost::mpl::sequence_tag< ::boost::mpl::list<>>::type;
+ }}}
+
+ template <typename T>
+ struct tag_of<T, when<
+ std::is_same<
+ typename ::boost::mpl::sequence_tag<T>::type,
+ ::boost::mpl::sequence_tag< ::boost::mpl::list<>>::type
+ >::value
+ >> {
+ using type = ext::boost::mpl::list_tag;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Comparable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct equal_impl<ext::boost::mpl::list_tag, ext::boost::mpl::list_tag> {
+ template <typename Xs, typename Ys>
+ static constexpr auto apply(Xs const&, Ys const&) {
+ return typename ::boost::mpl::equal<Xs, Ys>::type{};
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Foldable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct length_impl<ext::boost::mpl::list_tag> {
+ template <typename Xs>
+ static constexpr auto apply(Xs const&) {
+ return hana::size_c< ::boost::mpl::size<Xs>::type::value>;
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Iterable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct at_impl<ext::boost::mpl::list_tag> {
+ template <typename Ts, typename N>
+ static constexpr auto apply(Ts const&, N const&) {
+ constexpr std::size_t n = N::value;
+ using T = typename ::boost::mpl::at_c<Ts, n>::type;
+ return hana::type_c<T>;
+ }
+ };
+
+ template <>
+ struct drop_front_impl<ext::boost::mpl::list_tag> {
+ template <std::size_t n, typename Xs, std::size_t ...i>
+ static constexpr auto drop_front_helper(Xs const&, std::index_sequence<i...>) {
+ return boost::mpl::list<
+ typename boost::mpl::at_c<Xs, n + i>::type...
+ >{};
+ }
+
+ template <typename Xs, typename N>
+ static constexpr auto apply(Xs const& xs, N const&) {
+ constexpr std::size_t n = N::value;
+ constexpr std::size_t len = decltype(hana::length(xs))::value;
+ return drop_front_helper<n>(xs,
+ std::make_index_sequence<(n < len ? len - n : 0)>{});
+ }
+ };
+
+ template <>
+ struct is_empty_impl<ext::boost::mpl::list_tag> {
+ template <typename Xs>
+ static constexpr auto apply(Xs const&)
+ { return typename ::boost::mpl::empty<Xs>::type{}; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Conversion from a Foldable
+ //////////////////////////////////////////////////////////////////////////
+ template <typename F>
+ struct to_impl<ext::boost::mpl::list_tag, F, when<hana::Foldable<F>::value>> {
+ template <typename Xs>
+ static constexpr decltype(auto) apply(Xs&& xs) {
+ auto list_type = hana::unpack(static_cast<Xs&&>(xs),
+ hana::template_<::boost::mpl::list>);
+ return typename decltype(list_type)::type{};
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXT_BOOST_MPL_LIST_HPP
diff --git a/boost/hana/ext/boost/mpl/vector.hpp b/boost/hana/ext/boost/mpl/vector.hpp
new file mode 100644
index 0000000000..59cac5dd2b
--- /dev/null
+++ b/boost/hana/ext/boost/mpl/vector.hpp
@@ -0,0 +1,185 @@
+/*!
+@file
+Adapts `boost::mpl::vector` for use with Hana.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXT_BOOST_MPL_VECTOR_HPP
+#define BOOST_HANA_EXT_BOOST_MPL_VECTOR_HPP
+
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/ext/boost/mpl/integral_c.hpp>
+#include <boost/hana/fwd/at.hpp>
+#include <boost/hana/fwd/core/to.hpp>
+#include <boost/hana/fwd/core/tag_of.hpp>
+#include <boost/hana/fwd/drop_front.hpp>
+#include <boost/hana/fwd/equal.hpp>
+#include <boost/hana/fwd/is_empty.hpp>
+#include <boost/hana/fwd/less.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/type.hpp>
+#include <boost/hana/unpack.hpp>
+
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/empty.hpp>
+#include <boost/mpl/equal.hpp>
+#include <boost/mpl/sequence_tag.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/vector.hpp>
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+namespace boost { namespace mpl {
+ //! @ingroup group-ext-mpl
+ //! Adapter for Boost.MPL vectors.
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! It is possible for MPL vectors to model a couple of concepts.
+ //! However, because they are only able to hold types, they lack
+ //! the generality required to model concepts like `Functor`,
+ //! `Sequence` and other related concepts.
+ //!
+ //! 1. `Comparable`\n
+ //! Two MPL vectors are equal if and only if they contain the same
+ //! number of types, and if all those types are equal.
+ //! @include example/ext/boost/mpl/vector/comparable.cpp
+ //!
+ //! 2. `Foldable`\n
+ //! Folding a MPL vector is equivalent to folding it as a `Sequence`.
+ //! @include example/ext/boost/mpl/vector/foldable.cpp
+ //!
+ //! 3. `Iterable`\n
+ //! Iterating over a MPL vector is just iterating over each of the
+ //! types it contains, as if it were a `Sequence`.
+ //! @include example/ext/boost/mpl/vector/iterable.cpp
+ //!
+ //! 4. `Searchable`\n
+ //! A MPL vector can be searched as if it were a tuple containing
+ //! `hana::type`s.
+ //! @include example/ext/boost/mpl/vector/searchable.cpp
+ //!
+ //!
+ //! Conversion from any `Foldable`
+ //! ------------------------------
+ //! A MPL vector can be created from any `Foldable`. More precisely,
+ //! for a `Foldable` `xs` whose linearization is `[x1, ..., xn]`,
+ //! @code
+ //! to<ext::boost::mpl::vector_tag>(xs) == mpl::vector<t1, ..., tn>
+ //! @endcode
+ //! where `tk` is the type of `xk`, or the type contained in `xk` if
+ //! `xk` is a `hana::type`.
+ //! @warning
+ //! The limitations on the size of `mpl::vector`s are inherited by
+ //! this conversion utility, and hence trying to convert a `Foldable`
+ //! containing more than [BOOST_MPL_LIMIT_VECTOR_SIZE][1] elements
+ //! is an error.
+ //! @include example/ext/boost/mpl/vector/conversion.cpp
+ //!
+ //! [1]: http://www.boost.org/doc/libs/release/libs/mpl/doc/refmanual/limit-vector-size.html
+ template <typename ...T>
+ struct vector { };
+}}
+#endif
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace ext { namespace boost { namespace mpl {
+ using vector_tag = ::boost::mpl::sequence_tag< ::boost::mpl::vector<>>::type;
+ }}}
+
+ template <typename T>
+ struct tag_of<T, when<
+ std::is_same<
+ typename ::boost::mpl::sequence_tag<T>::type,
+ ::boost::mpl::sequence_tag< ::boost::mpl::vector<>>::type
+ >::value
+ >> {
+ using type = ext::boost::mpl::vector_tag;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Comparable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct equal_impl<ext::boost::mpl::vector_tag, ext::boost::mpl::vector_tag> {
+ template <typename Xs, typename Ys>
+ static constexpr auto apply(Xs const&, Ys const&) {
+ return typename ::boost::mpl::equal<Xs, Ys>::type{};
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Foldable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct length_impl<ext::boost::mpl::vector_tag> {
+ template <typename Xs>
+ static constexpr auto apply(Xs const&) {
+ return hana::size_c< ::boost::mpl::size<Xs>::type::value>;
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Iterable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct at_impl<ext::boost::mpl::vector_tag> {
+ template <typename Ts, typename N>
+ static constexpr auto apply(Ts const&, N const&) {
+ constexpr std::size_t n = N::value;
+ using T = typename ::boost::mpl::at_c<Ts, n>::type;
+ return hana::type_c<T>;
+ }
+ };
+
+ template <>
+ struct drop_front_impl<ext::boost::mpl::vector_tag> {
+ template <std::size_t n, typename Xs, std::size_t ...i>
+ static constexpr auto drop_front_helper(Xs const&, std::index_sequence<i...>) {
+ return boost::mpl::vector<
+ typename boost::mpl::at_c<Xs, n + i>::type...
+ >{};
+ }
+
+ template <typename Xs, typename N>
+ static constexpr auto apply(Xs const& xs, N const&) {
+ constexpr std::size_t n = N::value;
+ constexpr std::size_t len = decltype(hana::length(xs))::value;
+ return drop_front_helper<n>(xs,
+ std::make_index_sequence<(n < len ? len - n : 0)>{});
+ }
+ };
+
+ template <>
+ struct is_empty_impl<ext::boost::mpl::vector_tag> {
+ template <typename xs>
+ static constexpr auto apply(xs)
+ { return typename ::boost::mpl::empty<xs>::type{}; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Conversion from a Foldable
+ //////////////////////////////////////////////////////////////////////////
+ template <typename F>
+ struct to_impl<ext::boost::mpl::vector_tag, F, when<hana::Foldable<F>::value>> {
+ template <typename Xs>
+ static constexpr auto apply(Xs const& xs) {
+ auto vector_type = hana::unpack(xs, hana::template_<boost::mpl::vector>);
+ return typename decltype(vector_type)::type{};
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXT_BOOST_MPL_VECTOR_HPP
diff --git a/boost/hana/ext/boost/tuple.hpp b/boost/hana/ext/boost/tuple.hpp
new file mode 100644
index 0000000000..dff9a4a952
--- /dev/null
+++ b/boost/hana/ext/boost/tuple.hpp
@@ -0,0 +1,138 @@
+/*!
+@file
+Adapts `boost::tuple` for use with Hana.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXT_BOOST_TUPLE_HPP
+#define BOOST_HANA_EXT_BOOST_TUPLE_HPP
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/decay.hpp>
+#include <boost/hana/fwd/at.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+#include <boost/hana/fwd/core/tag_of.hpp>
+#include <boost/hana/fwd/drop_front.hpp>
+#include <boost/hana/fwd/is_empty.hpp>
+#include <boost/hana/fwd/length.hpp>
+#include <boost/hana/integral_constant.hpp>
+
+#include <boost/tuple/tuple.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+namespace boost {
+ //! @ingroup group-ext-boost
+ //! Adapter for `boost::tuple`s.
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! A `boost::tuple` is a model of the `Sequence` concept, and all the
+ //! concepts it refines. That makes it essentially the same as a Hana
+ //! tuple, although the complexity of some operations might differ from
+ //! that of Hana's tuple.
+ //!
+ //! @include example/ext/boost/tuple.cpp
+ template <typename ...T>
+ struct tuple { };
+}
+#endif
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace ext { namespace boost { struct tuple_tag; }}
+
+ template <typename ...Xs>
+ struct tag_of<boost::tuple<Xs...>> {
+ using type = ext::boost::tuple_tag;
+ };
+
+ template <typename H, typename T>
+ struct tag_of<boost::tuples::cons<H, T>> {
+ using type = ext::boost::tuple_tag;
+ };
+
+ template <>
+ struct tag_of<boost::tuples::null_type> {
+ using type = ext::boost::tuple_tag;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Iterable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct at_impl<ext::boost::tuple_tag> {
+ template <typename Xs, typename N>
+ static constexpr decltype(auto) apply(Xs&& xs, N const&) {
+ constexpr std::size_t n = N::value;
+ return static_cast<Xs&&>(xs).template get<n>();
+ }
+ };
+
+ template <>
+ struct drop_front_impl<ext::boost::tuple_tag> {
+ template <std::size_t n, typename Xs, std::size_t ...i>
+ static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence<i...>) {
+ return hana::make<ext::boost::tuple_tag>(
+ hana::at_c<n + i>(static_cast<Xs&&>(xs))...
+ );
+ }
+
+ template <typename Xs, typename N>
+ static constexpr auto apply(Xs&& xs, N const&) {
+ constexpr std::size_t n = N::value;
+ constexpr std::size_t len = decltype(hana::length(xs))::value;
+ return drop_front_helper<n>(static_cast<Xs&&>(xs),
+ std::make_index_sequence<(n < len ? len - n : 0)>{});
+ }
+ };
+
+ template <>
+ struct is_empty_impl<ext::boost::tuple_tag> {
+ static constexpr auto apply(boost::tuples::null_type const&)
+ { return hana::true_c; }
+
+ template <typename H, typename T>
+ static constexpr auto apply(boost::tuples::cons<H, T> const&)
+ { return hana::false_c; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Foldable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct length_impl<ext::boost::tuple_tag> {
+ template <typename Xs>
+ static constexpr auto apply(Xs const&) {
+ return hana::size_c<boost::tuples::length<Xs>::value>;
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Sequence
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct Sequence<ext::boost::tuple_tag> {
+ static constexpr bool value = true;
+ };
+
+ template <>
+ struct make_impl<ext::boost::tuple_tag> {
+ template <typename ...Xs>
+ static constexpr auto apply(Xs&& ...xs) {
+ return boost::tuples::tuple<
+ typename detail::decay<Xs>::type...
+ >{static_cast<Xs&&>(xs)...};
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXT_BOOST_TUPLE_HPP
diff --git a/boost/hana/ext/std.hpp b/boost/hana/ext/std.hpp
new file mode 100644
index 0000000000..0d66408dc9
--- /dev/null
+++ b/boost/hana/ext/std.hpp
@@ -0,0 +1,30 @@
+/*!
+@file
+Includes all the adaptors for the standard library.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXT_STD_HPP
+#define BOOST_HANA_EXT_STD_HPP
+
+//! @ingroup group-ext
+//! @defgroup group-ext-std Standard library adapters
+//! Adapters for components in the standard library.
+
+#include <boost/hana/config.hpp>
+
+#ifndef BOOST_HANA_CONFIG_HAS_NO_STD_TUPLE_ADAPTER
+# include <boost/hana/ext/std/tuple.hpp>
+#endif
+
+#include <boost/hana/ext/std/array.hpp>
+#include <boost/hana/ext/std/integer_sequence.hpp>
+#include <boost/hana/ext/std/integral_constant.hpp>
+#include <boost/hana/ext/std/pair.hpp>
+#include <boost/hana/ext/std/ratio.hpp>
+#include <boost/hana/ext/std/vector.hpp>
+
+#endif // !BOOST_HANA_EXT_STD_HPP
diff --git a/boost/hana/ext/std/array.hpp b/boost/hana/ext/std/array.hpp
new file mode 100644
index 0000000000..f733624e57
--- /dev/null
+++ b/boost/hana/ext/std/array.hpp
@@ -0,0 +1,163 @@
+/*!
+@file
+Adapts `std::array` for use with Hana.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXT_STD_ARRAY_HPP
+#define BOOST_HANA_EXT_STD_ARRAY_HPP
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/algorithm.hpp>
+#include <boost/hana/fwd/at.hpp>
+#include <boost/hana/fwd/core/tag_of.hpp>
+#include <boost/hana/fwd/drop_front.hpp>
+#include <boost/hana/fwd/equal.hpp>
+#include <boost/hana/fwd/is_empty.hpp>
+#include <boost/hana/fwd/length.hpp>
+#include <boost/hana/fwd/less.hpp>
+#include <boost/hana/integral_constant.hpp>
+
+#include <array>
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+namespace std {
+ //! @ingroup group-ext-std
+ //! Adaptation of `std::array` for Hana.
+ //!
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! 1. `Comparable`\n
+ //! `std::array`s are compared as per `std::equal`, except that two arrays
+ //! with different sizes compare unequal instead of triggering an error
+ //! and the result of the comparison is `constexpr` if both arrays are
+ //! `constexpr`.
+ //! @include example/ext/std/array/comparable.cpp
+ //!
+ //! 2. `Orderable`\n
+ //! `std::array`s are ordered with the usual lexicographical ordering,
+ //! except that two arrays with different size can be ordered instead
+ //! of triggering an error and the result of the comparison is `constexpr`
+ //! if both arrays are `constexpr`.
+ //! @include example/ext/std/array/orderable.cpp
+ //!
+ //! 3. `Foldable`\n
+ //! Folding an array from the left is equivalent to calling
+ //! `std::accumulate` on it, except it can be `constexpr`.
+ //! @include example/ext/std/array/foldable.cpp
+ //!
+ //! 4. `Iterable`\n
+ //! Iterating over a `std::array` is equivalent to iterating over it with
+ //! a normal `for` loop.
+ //! @include example/ext/std/array/iterable.cpp
+ template <typename T, std::size_t N>
+ struct array { };
+}
+#endif
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace ext { namespace std { struct array_tag; }}
+
+ template <typename T, std::size_t N>
+ struct tag_of<std::array<T, N>> {
+ using type = ext::std::array_tag;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Foldable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct length_impl<ext::std::array_tag> {
+ template <typename Xs>
+ static constexpr auto apply(Xs const&) {
+ return hana::size_c<std::tuple_size<Xs>::type::value>;
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Iterable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct at_impl<ext::std::array_tag> {
+ template <typename Xs, typename N>
+ static constexpr decltype(auto) apply(Xs&& xs, N const&) {
+ constexpr std::size_t n = N::value;
+ return static_cast<Xs&&>(xs)[n];
+ }
+ };
+
+ template <>
+ struct drop_front_impl<ext::std::array_tag> {
+ template <std::size_t n, typename Xs, std::size_t ...i>
+ static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence<i...>) {
+ using T = typename std::remove_reference<Xs>::type::value_type;
+ return std::array<T, sizeof...(i)>{{static_cast<Xs&&>(xs)[n + i]...}};
+ }
+
+ template <typename Xs, typename N>
+ static constexpr auto apply(Xs&& xs, N const&) {
+ constexpr std::size_t n = N::value;
+ constexpr std::size_t len = std::tuple_size<
+ typename std::remove_cv<
+ typename std::remove_reference<Xs>::type
+ >::type
+ >::value;
+ return drop_front_helper<n>(static_cast<Xs&&>(xs),
+ std::make_index_sequence<(n < len ? len - n : 0)>{});
+ }
+ };
+
+ template <>
+ struct is_empty_impl<ext::std::array_tag> {
+ template <typename T, std::size_t N>
+ static constexpr auto apply(std::array<T, N> const&) {
+ return hana::bool_c<N == 0>;
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Comparable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct equal_impl<ext::std::array_tag, ext::std::array_tag> {
+ template <typename T, std::size_t n, typename U>
+ static constexpr bool apply(std::array<T, n> const& xs, std::array<U, n> const& ys)
+ { return detail::equal(&xs[0], &xs[0] + n, &ys[0], &ys[0] + n); }
+
+ template <typename T, typename U>
+ static constexpr auto apply(std::array<T, 0> const&, std::array<U, 0> const&)
+ { return hana::true_c; }
+
+ template <typename T, std::size_t n, typename U, std::size_t m>
+ static constexpr auto apply(std::array<T, n> const&, std::array<U, m> const&)
+ { return hana::false_c; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Orderable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct less_impl<ext::std::array_tag, ext::std::array_tag> {
+ template <typename T, typename U>
+ static constexpr auto apply(std::array<T, 0> const&, std::array<U, 0> const&)
+ { return hana::false_c; }
+
+ template <typename T, std::size_t n, typename U, std::size_t m>
+ static constexpr auto apply(std::array<T, n> const& xs, std::array<U, m> const& ys) {
+ return detail::lexicographical_compare(&xs[0], &xs[0] + n, &ys[0], &ys[0] + m);
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXT_STD_ARRAY_HPP
diff --git a/boost/hana/ext/std/integer_sequence.hpp b/boost/hana/ext/std/integer_sequence.hpp
new file mode 100644
index 0000000000..27d01e3137
--- /dev/null
+++ b/boost/hana/ext/std/integer_sequence.hpp
@@ -0,0 +1,140 @@
+/*!
+@file
+Adapts `std::integer_sequence` for use with Hana.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXT_STD_INTEGER_SEQUENCE_HPP
+#define BOOST_HANA_EXT_STD_INTEGER_SEQUENCE_HPP
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/fast_and.hpp>
+#include <boost/hana/ext/std/integral_constant.hpp>
+#include <boost/hana/fwd/at.hpp>
+#include <boost/hana/fwd/core/tag_of.hpp>
+#include <boost/hana/fwd/drop_front.hpp>
+#include <boost/hana/fwd/equal.hpp>
+#include <boost/hana/fwd/is_empty.hpp>
+#include <boost/hana/fwd/unpack.hpp>
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+namespace std {
+ //! @ingroup group-ext-std
+ //! Adaptation of `std::integer_sequence` for Hana.
+ //!
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! 1. `Comparable`\n
+ //! Two `std::integer_sequence`s are equal if and only if they have the
+ //! same number of elements, and if corresponding elements compare equal.
+ //! The types of the elements held in both `integer_sequence`s may be
+ //! different, as long as they can be compared.
+ //! @include example/ext/std/integer_sequence/comparable.cpp
+ //!
+ //! 2. `Foldable`\n
+ //! Folding an `integer_sequence` is equivalent to folding a sequence of
+ //! `std::integral_constant`s with the corresponding types.
+ //! @include example/ext/std/integer_sequence/foldable.cpp
+ //!
+ //! 3. `Iterable`\n
+ //! Iterating over an `integer_sequence` is equivalent to iterating over
+ //! a sequence of the corresponding `std::integral_constant`s.
+ //! @include example/ext/std/integer_sequence/iterable.cpp
+ //!
+ //! 4. `Searchable`\n
+ //! Searching through an `integer_sequence` is equivalent to searching
+ //! through the corresponding sequence of `std::integral_constant`s.
+ //! @include example/ext/std/integer_sequence/searchable.cpp
+ template <typename T, T ...v>
+ struct integer_sequence { };
+}
+#endif
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace ext { namespace std { struct integer_sequence_tag; }}
+
+ template <typename T, T ...v>
+ struct tag_of<std::integer_sequence<T, v...>> {
+ using type = ext::std::integer_sequence_tag;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Comparable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct equal_impl<ext::std::integer_sequence_tag, ext::std::integer_sequence_tag> {
+ template <typename X, X ...xs, typename Y, Y ...ys>
+ static constexpr hana::bool_<detail::fast_and<(xs == ys)...>::value>
+ apply(std::integer_sequence<X, xs...> const&, std::integer_sequence<Y, ys...> const&)
+ { return {}; }
+
+ template <typename Xs, typename Ys>
+ static constexpr hana::false_ apply(Xs const&, Ys const&, ...)
+ { return {}; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Foldable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct unpack_impl<ext::std::integer_sequence_tag> {
+ template <typename T, T ...v, typename F>
+ static constexpr decltype(auto)
+ apply(std::integer_sequence<T, v...> const&, F&& f) {
+ return static_cast<F&&>(f)(std::integral_constant<T, v>{}...);
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Iterable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct at_impl<ext::std::integer_sequence_tag> {
+ template <typename T, T ...v, typename N>
+ static constexpr auto apply(std::integer_sequence<T, v...> const&, N const&) {
+ constexpr std::size_t n = N::value;
+ constexpr T values[] = {v...};
+ return std::integral_constant<T, values[n]>{};
+ }
+ };
+
+ template <>
+ struct drop_front_impl<ext::std::integer_sequence_tag> {
+ template <std::size_t n, typename T, T ...t, std::size_t ...i>
+ static constexpr auto drop_front_helper(std::integer_sequence<T, t...>,
+ std::index_sequence<i...>)
+ {
+ constexpr T ts[sizeof...(t)+1] = {t...}; // avoid 0-sized array
+ return std::integer_sequence<T, ts[n + i]...>{};
+ }
+
+ template <typename T, T ...t, typename N>
+ static constexpr auto apply(std::integer_sequence<T, t...> ts, N const&) {
+ constexpr std::size_t n = N::value;
+ constexpr std::size_t len = sizeof...(t);
+ return drop_front_helper<n>(ts,
+ std::make_index_sequence<(n < len ? len - n : 0)>{});
+ }
+ };
+
+ template <>
+ struct is_empty_impl<ext::std::integer_sequence_tag> {
+ template <typename T, T ...xs>
+ static constexpr auto apply(std::integer_sequence<T, xs...> const&)
+ { return hana::bool_c<sizeof...(xs) == 0>; }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXT_STD_INTEGER_SEQUENCE_HPP
diff --git a/boost/hana/ext/std/integral_constant.hpp b/boost/hana/ext/std/integral_constant.hpp
new file mode 100644
index 0000000000..28d8f05fb8
--- /dev/null
+++ b/boost/hana/ext/std/integral_constant.hpp
@@ -0,0 +1,96 @@
+/*!
+@file
+Adapts `std::integral_constant` for use with Hana.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXT_STD_INTEGRAL_CONSTANT_HPP
+#define BOOST_HANA_EXT_STD_INTEGRAL_CONSTANT_HPP
+
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/fwd/core/to.hpp>
+#include <boost/hana/fwd/core/tag_of.hpp>
+#include <boost/hana/fwd/integral_constant.hpp>
+
+#include <type_traits>
+
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+namespace std {
+ //! @ingroup group-ext-std
+ //! Adapter for `std::integral_constant`s.
+ //!
+ //! Provided models
+ //! ---------------
+ //! 1. `Constant` and `IntegralConstant`\n
+ //! A `std::integral_constant` is a model of the `IntegralConstant` and
+ //! `Constant` concepts, just like `hana::integral_constant`s are. As a
+ //! consequence, they are also implicitly a model of the concepts provided
+ //! for all models of `Constant`.
+ //! @include example/ext/std/integral_constant.cpp
+ template <typename T, T v>
+ struct integral_constant { };
+}
+#endif
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace ext { namespace std {
+ template <typename T>
+ struct integral_constant_tag { using value_type = T; };
+ }}
+
+ namespace detail {
+ template <typename T, T v>
+ constexpr bool
+ is_std_integral_constant(std::integral_constant<T, v>*)
+ { return true; }
+
+ constexpr bool is_std_integral_constant(...)
+ { return false; }
+
+
+ template <typename T, T v>
+ constexpr bool
+ is_hana_integral_constant(hana::integral_constant<T, v>*)
+ { return true; }
+
+ constexpr bool is_hana_integral_constant(...)
+ { return false; }
+ }
+
+ template <typename T>
+ struct tag_of<T, when<
+ detail::is_std_integral_constant((T*)0) &&
+ !detail::is_hana_integral_constant((T*)0)
+ >> {
+ using type = ext::std::integral_constant_tag<
+ typename hana::tag_of<typename T::value_type>::type
+ >;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Constant/IntegralConstant
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T>
+ struct IntegralConstant<ext::std::integral_constant_tag<T>> {
+ static constexpr bool value = true;
+ };
+
+ template <typename T, typename C>
+ struct to_impl<ext::std::integral_constant_tag<T>, C, when<
+ hana::IntegralConstant<C>::value
+ >> : embedding<is_embedded<typename C::value_type, T>{}> {
+ template <typename N>
+ static constexpr auto apply(N const&) {
+ return std::integral_constant<T, N::value>{};
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXT_STD_INTEGRAL_CONSTANT_HPP
diff --git a/boost/hana/ext/std/pair.hpp b/boost/hana/ext/std/pair.hpp
new file mode 100644
index 0000000000..fc60218e85
--- /dev/null
+++ b/boost/hana/ext/std/pair.hpp
@@ -0,0 +1,91 @@
+/*!
+@file
+Adapts `std::pair` for use with Hana.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXT_STD_PAIR_HPP
+#define BOOST_HANA_EXT_STD_PAIR_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+#include <boost/hana/fwd/core/tag_of.hpp>
+#include <boost/hana/fwd/first.hpp>
+#include <boost/hana/fwd/second.hpp>
+
+#include <utility>
+
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+namespace std {
+ //! @ingroup group-ext-std
+ //! Adaptation of `std::pair` for Hana.
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! A `std::pair` models exactly the same concepts as a `hana::pair`.
+ //! Please refer to the documentation of `hana::pair` for details.
+ //!
+ //! @include example/ext/std/pair.cpp
+ template <typename First, typename Second>
+ struct pair { };
+}
+#endif
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace ext { namespace std { struct pair_tag; }}
+
+ template <typename First, typename Second>
+ struct tag_of<std::pair<First, Second>> {
+ using type = ext::std::pair_tag;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Product
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct make_impl<ext::std::pair_tag> {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y) {
+ return std::make_pair(static_cast<X&&>(x),
+ static_cast<Y&&>(y));
+ }
+ };
+
+ template <>
+ struct first_impl<ext::std::pair_tag> {
+ template <typename T, typename U>
+ static constexpr T const& apply(std::pair<T, U> const& p)
+ { return p.first; }
+
+ template <typename T, typename U>
+ static constexpr T& apply(std::pair<T, U>& p)
+ { return p.first; }
+
+ template <typename T, typename U>
+ static constexpr T&& apply(std::pair<T, U>&& p)
+ { return static_cast<T&&>(p.first); }
+ };
+
+ template <>
+ struct second_impl<ext::std::pair_tag> {
+ template <typename T, typename U>
+ static constexpr U const& apply(std::pair<T, U> const& p)
+ { return p.second; }
+
+ template <typename T, typename U>
+ static constexpr U& apply(std::pair<T, U>& p)
+ { return p.second; }
+
+ template <typename T, typename U>
+ static constexpr U&& apply(std::pair<T, U>&& p)
+ { return static_cast<U&&>(p.second); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXT_STD_PAIR_HPP
diff --git a/boost/hana/ext/std/ratio.hpp b/boost/hana/ext/std/ratio.hpp
new file mode 100644
index 0000000000..a301abd1b6
--- /dev/null
+++ b/boost/hana/ext/std/ratio.hpp
@@ -0,0 +1,164 @@
+/*!
+@file
+Adapts `std::ratio` for use with Hana.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXT_STD_RATIO_HPP
+#define BOOST_HANA_EXT_STD_RATIO_HPP
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/fwd/core/to.hpp>
+#include <boost/hana/fwd/core/tag_of.hpp>
+#include <boost/hana/fwd/div.hpp>
+#include <boost/hana/fwd/equal.hpp>
+#include <boost/hana/fwd/less.hpp>
+#include <boost/hana/fwd/minus.hpp>
+#include <boost/hana/fwd/mod.hpp>
+#include <boost/hana/fwd/mult.hpp>
+#include <boost/hana/fwd/one.hpp>
+#include <boost/hana/fwd/plus.hpp>
+#include <boost/hana/fwd/zero.hpp>
+
+#include <cstdint>
+#include <ratio>
+#include <type_traits>
+
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+namespace std {
+ //! @ingroup group-ext-std
+ //! Adaptation of `std::ratio` for Hana.
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! 1. `Comparable`\n
+ //! `std::ratio`s are compared for equality using `std::ratio_equal`.
+ //! @include example/ext/std/ratio/comparable.cpp
+ //!
+ //! 2. `Orderable`\n
+ //! `std::ratio`s are ordered using `std::ratio_less`.
+ //! @include example/ext/std/ratio/orderable.cpp
+ //!
+ //! 3. `Monoid`, `Group`, `Ring`, and `EuclideanRing`\n
+ //! `std::ratio`s are added, subtracted, multiplied and divided using
+ //! `std::ratio_add`, `std::ratio_subtract`, `std::ratio_multiply` and
+ //! `std::ratio_divide`, respectively. Furthermore, the neutral element
+ //! for the additive operation is `std::ratio<0, 1>{}`, and the neutral
+ //! element for the multiplicative operation is `std::ratio<1, 1>{}`.
+ //! @include example/ext/std/ratio/arithmetic.cpp
+ template <std::intmax_t Num, std::intmax_t Denom>
+ class ratio { };
+}
+#endif
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace ext { namespace std { struct ratio_tag; }}
+
+ template <std::intmax_t num, std::intmax_t den>
+ struct tag_of<std::ratio<num, den>> {
+ using type = ext::std::ratio_tag;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Conversion from IntegralConstants
+ //////////////////////////////////////////////////////////////////////////
+ template <typename C>
+ struct to_impl<ext::std::ratio_tag, C, when<
+ hana::IntegralConstant<C>::value
+ >> {
+ template <typename N>
+ static constexpr auto apply(N const&) {
+ return std::ratio<N::value>{};
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Comparable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct equal_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
+ template <typename R1, typename R2>
+ static constexpr auto apply(R1 const&, R2 const&)
+ { return hana::bool_c<std::ratio_equal<R1, R2>::value>; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Orderable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct less_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
+ template <typename R1, typename R2>
+ static constexpr auto apply(R1 const&, R2 const&)
+ { return hana::bool_c<std::ratio_less<R1, R2>::value>; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Monoid
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct plus_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
+ template <typename R1, typename R2>
+ static constexpr std::ratio_add<R1, R2> apply(R1 const&, R2 const&)
+ { return {}; }
+ };
+
+ template <>
+ struct zero_impl<ext::std::ratio_tag> {
+ static constexpr std::ratio<0> apply()
+ { return {}; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Group
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct minus_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
+ template <typename R1, typename R2>
+ static constexpr std::ratio_subtract<R1, R2> apply(R1 const&, R2 const&)
+ { return {}; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Ring
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct mult_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
+ template <typename R1, typename R2>
+ static constexpr std::ratio_multiply<R1, R2> apply(R1 const&, R2 const&)
+ { return {}; }
+ };
+
+ template <>
+ struct one_impl<ext::std::ratio_tag> {
+ static constexpr std::ratio<1> apply()
+ { return {}; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // EuclideanRing
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct div_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
+ template <typename R1, typename R2>
+ static constexpr std::ratio_divide<R1, R2> apply(R1 const&, R2 const&)
+ { return {}; }
+ };
+
+ template <>
+ struct mod_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
+ template <typename R1, typename R2>
+ static constexpr std::ratio<0> apply(R1 const&, R2 const&)
+ { return {}; }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXT_STD_RATIO_HPP
diff --git a/boost/hana/ext/std/tuple.hpp b/boost/hana/ext/std/tuple.hpp
new file mode 100644
index 0000000000..b2e95d7f30
--- /dev/null
+++ b/boost/hana/ext/std/tuple.hpp
@@ -0,0 +1,190 @@
+/*!
+@file
+Adapts `std::tuple` for use with Hana.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXT_STD_TUPLE_HPP
+#define BOOST_HANA_EXT_STD_TUPLE_HPP
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/fwd/at.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+#include <boost/hana/fwd/core/tag_of.hpp>
+#include <boost/hana/fwd/drop_front.hpp>
+#include <boost/hana/fwd/empty.hpp>
+#include <boost/hana/fwd/flatten.hpp>
+#include <boost/hana/fwd/front.hpp>
+#include <boost/hana/fwd/is_empty.hpp>
+#include <boost/hana/fwd/length.hpp>
+#include <boost/hana/fwd/lift.hpp>
+#include <boost/hana/integral_constant.hpp>
+
+#include <cstddef>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+
+#ifdef BOOST_HANA_CONFIG_HAS_NO_STD_TUPLE_ADAPTER
+# error The adapter for std::tuple is not supported with versions of \
+ libc++ prior to the one shipped with Clang 3.7 because of a bug \
+ in the tuple implementation.
+#endif
+
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+namespace std {
+ //! @ingroup group-ext-std
+ //! Adapter for `std::tuple`s.
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! A `std::tuple` is a model of the `Sequence` concept, and all the
+ //! concepts it refines. That makes it essentially the same as a Hana
+ //! tuple, although the complexity of some operations might differ from
+ //! that of Hana's tuple.
+ //!
+ //! @include example/ext/std/tuple.cpp
+ template <typename ...T>
+ struct tuple { };
+}
+#endif
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace ext { namespace std { struct tuple_tag; }}
+
+ template <typename ...Xs>
+ struct tag_of<std::tuple<Xs...>> {
+ using type = ext::std::tuple_tag;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // make
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct make_impl<ext::std::tuple_tag> {
+ template <typename ...Xs>
+ static constexpr decltype(auto) apply(Xs&& ...xs) {
+ return std::make_tuple(static_cast<Xs&&>(xs)...);
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Applicative
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct lift_impl<ext::std::tuple_tag> {
+ template <typename X>
+ static constexpr auto apply(X&& x) {
+ return std::tuple<typename std::decay<X>::type>{
+ static_cast<X&&>(x)};
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Monad
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct flatten_impl<ext::std::tuple_tag> {
+ template <typename Xs, std::size_t ...i>
+ static constexpr decltype(auto)
+ flatten_helper(Xs&& xs, std::index_sequence<i...>) {
+#if defined(BOOST_HANA_CONFIG_LIBCPP_HAS_BUG_22806)
+ return std::tuple_cat(std::get<i>(xs)...);
+#else
+ return std::tuple_cat(std::get<i>(static_cast<Xs&&>(xs))...);
+#endif
+ }
+
+ template <typename Xs>
+ static constexpr decltype(auto) apply(Xs&& xs) {
+ using Raw = typename std::remove_reference<Xs>::type;
+ constexpr std::size_t Length = std::tuple_size<Raw>::value;
+ return flatten_helper(static_cast<Xs&&>(xs),
+ std::make_index_sequence<Length>{});
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // MonadPlus
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct empty_impl<ext::std::tuple_tag> {
+ static constexpr auto apply()
+ { return std::tuple<>{}; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Iterable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct front_impl<ext::std::tuple_tag> {
+ template <typename Xs>
+ static constexpr decltype(auto) apply(Xs&& xs) {
+ return std::get<0>(static_cast<Xs&&>(xs));
+ }
+ };
+
+ template <>
+ struct drop_front_impl<ext::std::tuple_tag> {
+ template <std::size_t n, typename Xs, std::size_t ...i>
+ static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence<i...>) {
+ return std::make_tuple(
+ hana::at_c<n + i>(static_cast<Xs&&>(xs))...
+ );
+ }
+
+ template <typename Xs, typename N>
+ static constexpr auto apply(Xs&& xs, N const&) {
+ using Raw = typename std::remove_reference<Xs>::type;
+ constexpr std::size_t n = N::value;
+ constexpr auto len = std::tuple_size<Raw>::value;
+ return drop_front_helper<n>(static_cast<Xs&&>(xs),
+ std::make_index_sequence<(n < len ? len - n : 0)>{});
+ }
+ };
+
+ template <>
+ struct is_empty_impl<ext::std::tuple_tag> {
+ template <typename ...Xs>
+ static constexpr auto apply(std::tuple<Xs...> const&)
+ { return hana::bool_c<sizeof...(Xs) == 0>; }
+ };
+
+ template <>
+ struct at_impl<ext::std::tuple_tag> {
+ template <typename Xs, typename N>
+ static constexpr decltype(auto) apply(Xs&& xs, N const&) {
+ constexpr std::size_t index = N::value;
+ return std::get<index>(static_cast<Xs&&>(xs));
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Foldable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct length_impl<ext::std::tuple_tag> {
+ template <typename ...Xs>
+ static constexpr auto apply(std::tuple<Xs...> const&) {
+ return hana::size_c<sizeof...(Xs)>;
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Sequence
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct Sequence<ext::std::tuple_tag> {
+ static constexpr bool value = true;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXT_STD_TUPLE_HPP
diff --git a/boost/hana/ext/std/vector.hpp b/boost/hana/ext/std/vector.hpp
new file mode 100644
index 0000000000..62b808b2ea
--- /dev/null
+++ b/boost/hana/ext/std/vector.hpp
@@ -0,0 +1,110 @@
+/*!
+@file
+Adapts `std::vector` for use with Hana.
+
+@copyright Louis Dionne 2013-2016
+@copyright Gonzalo Brito Gadeschi 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXT_STD_VECTOR_HPP
+#define BOOST_HANA_EXT_STD_VECTOR_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/fwd/core/tag_of.hpp>
+#include <boost/hana/less.hpp>
+
+#include <algorithm>
+#include <iterator>
+#include <memory>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace ext { namespace std { struct vector_tag; }}
+
+ template <typename T, typename Allocator>
+ struct tag_of<std::vector<T, Allocator>> {
+ using type = ext::std::vector_tag;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Comparable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct equal_impl<ext::std::vector_tag, ext::std::vector_tag> {
+ template <typename T1, typename A1, typename T2, typename A2>
+ static bool apply(std::vector<T1, A1> const& v1,
+ std::vector<T2, A2> const& v2)
+ {
+ return std::equal(begin(v1), end(v1),
+ begin(v2), end(v2),
+ hana::equal);
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Orderable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct less_impl<ext::std::vector_tag, ext::std::vector_tag> {
+ template <typename T1, typename A1, typename T2, typename A2>
+ static bool apply(std::vector<T1, A1> const& v1,
+ std::vector<T2, A2> const& v2)
+ {
+ return std::lexicographical_compare(begin(v1), end(v1),
+ begin(v2), end(v2),
+ hana::less);
+ }
+ };
+
+#if 0
+ //////////////////////////////////////////////////////////////////////////
+ // Functor
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct transform_impl<ext::std::vector_tag> {
+ template <typename V, typename F>
+ static auto apply(V&& v, F&& f) {
+ using U = std::remove_cv_t<std::remove_reference_t<
+ decltype(f(*v.begin()))
+ >>;
+ using Alloc = typename std::remove_reference_t<V>::allocator_type;
+ using NewAlloc = typename std::allocator_traits<Alloc>::
+ template rebind_alloc<U>;
+ std::vector<U, NewAlloc> result; result.reserve(v.size());
+
+ std::transform(begin(v), end(v),
+ std::back_inserter(result), std::forward<F>(f));
+ return result;
+ }
+
+ template <typename T, typename Alloc, typename F>
+ static auto apply(std::vector<T, Alloc>&& v, F&& f)
+ -> std::enable_if_t<
+ std::is_same<
+ T,
+ std::remove_cv_t<std::remove_reference_t<
+ decltype(f(*v.begin()))
+ >>
+ >{}
+ , std::vector<T, Alloc>
+ >
+ {
+ // If we receive a rvalue and the function returns elements of
+ // the same type, we modify the vector in-place instead of
+ // returning a new one.
+ std::transform(std::make_move_iterator(begin(v)),
+ std::make_move_iterator(end(v)),
+ begin(v), std::forward<F>(f));
+ return std::move(v);
+ }
+ };
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXT_STD_VECTOR_HPP
diff --git a/boost/hana/extend.hpp b/boost/hana/extend.hpp
new file mode 100644
index 0000000000..c2568e41ec
--- /dev/null
+++ b/boost/hana/extend.hpp
@@ -0,0 +1,50 @@
+/*!
+@file
+Defines `boost::hana::extend`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXTEND_HPP
+#define BOOST_HANA_EXTEND_HPP
+
+#include <boost/hana/fwd/extend.hpp>
+
+#include <boost/hana/concept/comonad.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/duplicate.hpp>
+#include <boost/hana/transform.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename W_, typename F>
+ constexpr decltype(auto) extend_t::operator()(W_&& w, F&& f) const {
+ using W = typename hana::tag_of<W_>::type;
+ using Extend = BOOST_HANA_DISPATCH_IF(extend_impl<W>,
+ hana::Comonad<W>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Comonad<W>::value,
+ "hana::extend(w, f) requires 'w' to be a Comonad");
+ #endif
+
+ return Extend::apply(static_cast<W_&&>(w), static_cast<F&&>(f));
+ }
+ //! @endcond
+
+ template <typename W, bool condition>
+ struct extend_impl<W, when<condition>> : default_ {
+ template <typename X, typename F>
+ static constexpr decltype(auto) apply(X&& x, F&& f) {
+ return hana::transform(hana::duplicate(static_cast<X&&>(x)),
+ static_cast<F&&>(f));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXTEND_HPP
diff --git a/boost/hana/extract.hpp b/boost/hana/extract.hpp
new file mode 100644
index 0000000000..f72ddfce13
--- /dev/null
+++ b/boost/hana/extract.hpp
@@ -0,0 +1,45 @@
+/*!
+@file
+Defines `boost::hana::extract`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_EXTRACT_HPP
+#define BOOST_HANA_EXTRACT_HPP
+
+#include <boost/hana/fwd/extract.hpp>
+
+#include <boost/hana/concept/comonad.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename W_>
+ constexpr decltype(auto) extract_t::operator()(W_&& w) const {
+ using W = typename hana::tag_of<W_>::type;
+ using Extract = BOOST_HANA_DISPATCH_IF(extract_impl<W>,
+ hana::Comonad<W>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Comonad<W>::value,
+ "hana::extract(w) requires 'w' to be a Comonad");
+ #endif
+
+ return Extract::apply(static_cast<W_&&>(w));
+ }
+ //! @endcond
+
+ template <typename W, bool condition>
+ struct extract_impl<W, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...args) = delete;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_EXTRACT_HPP
diff --git a/boost/hana/fill.hpp b/boost/hana/fill.hpp
new file mode 100644
index 0000000000..ce9c95392b
--- /dev/null
+++ b/boost/hana/fill.hpp
@@ -0,0 +1,74 @@
+/*!
+@file
+Defines `boost::hana::fill`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FILL_HPP
+#define BOOST_HANA_FILL_HPP
+
+#include <boost/hana/fwd/fill.hpp>
+
+#include <boost/hana/concept/functor.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/functional/always.hpp>
+#include <boost/hana/transform.hpp>
+#include <boost/hana/unpack.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Value>
+ constexpr auto fill_t::operator()(Xs&& xs, Value&& value) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Fill = BOOST_HANA_DISPATCH_IF(fill_impl<S>,
+ hana::Functor<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Functor<S>::value,
+ "hana::fill(xs, value) requires 'xs' to be a Functor");
+ #endif
+
+ return Fill::apply(static_cast<Xs&&>(xs),
+ static_cast<Value&&>(value));
+ }
+ //! @endcond
+
+ template <typename Fun, bool condition>
+ struct fill_impl<Fun, when<condition>> : default_ {
+ template <typename Xs, typename Value>
+ static constexpr auto apply(Xs&& xs, Value&& v) {
+ return hana::transform(static_cast<Xs&&>(xs),
+ hana::always(static_cast<Value&&>(v))
+ );
+ }
+ };
+
+ template <typename S>
+ struct fill_impl<S, when<Sequence<S>::value>> {
+ //! @cond
+ template <typename V>
+ struct filler {
+ V const& v;
+ template <typename ...Xs>
+ constexpr auto operator()(Xs const& ...xs) const {
+ return hana::make<S>(((void)xs, v)...);
+ }
+ };
+ //! @endcond
+
+ template <typename Xs, typename V>
+ static constexpr auto apply(Xs const& xs, V const& v) {
+ return hana::unpack(xs, filler<V>{v});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FILL_HPP
diff --git a/boost/hana/filter.hpp b/boost/hana/filter.hpp
new file mode 100644
index 0000000000..0a5979dd3b
--- /dev/null
+++ b/boost/hana/filter.hpp
@@ -0,0 +1,135 @@
+/*!
+@file
+Defines `boost::hana::filter`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FILTER_HPP
+#define BOOST_HANA_FILTER_HPP
+
+#include <boost/hana/fwd/filter.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/chain.hpp>
+#include <boost/hana/concept/monad_plus.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/detail/algorithm.hpp>
+#include <boost/hana/detail/array.hpp>
+#include <boost/hana/detail/decay.hpp>
+#include <boost/hana/empty.hpp>
+#include <boost/hana/lift.hpp>
+#include <boost/hana/unpack.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Pred>
+ constexpr auto filter_t::operator()(Xs&& xs, Pred&& pred) const {
+ using M = typename hana::tag_of<Xs>::type;
+ using Filter = BOOST_HANA_DISPATCH_IF(filter_impl<M>,
+ hana::MonadPlus<M>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::MonadPlus<M>::value,
+ "hana::filter(xs, pred) requires 'xs' to be a MonadPlus");
+ #endif
+
+ return Filter::apply(static_cast<Xs&&>(xs),
+ static_cast<Pred&&>(pred));
+ }
+ //! @endcond
+
+ namespace detail {
+ template <typename Pred, typename M>
+ struct lift_or_empty {
+ template <typename X>
+ static constexpr auto helper(X&& x, hana::true_)
+ { return hana::lift<M>(static_cast<X&&>(x)); }
+
+ template <typename X>
+ static constexpr auto helper(X&&, hana::false_)
+ { return hana::empty<M>(); }
+
+ template <typename X>
+ constexpr auto operator()(X&& x) const {
+ constexpr bool cond = decltype(std::declval<Pred>()(x))::value;
+ return helper(static_cast<X&&>(x), hana::bool_c<cond>);
+ }
+ };
+ }
+
+ template <typename M, bool condition>
+ struct filter_impl<M, when<condition>> : default_ {
+ template <typename Xs, typename Pred>
+ static constexpr decltype(auto) apply(Xs&& xs, Pred const&) {
+ return hana::chain(static_cast<Xs&&>(xs),
+ detail::lift_or_empty<Pred, M>{}
+ );
+ }
+ };
+
+ namespace detail {
+ template <bool ...b>
+ struct filter_indices {
+ static constexpr auto compute_indices() {
+ constexpr bool bs[] = {b..., false}; // avoid empty array
+ constexpr std::size_t N = detail::count(bs, bs + sizeof(bs), true);
+ detail::array<std::size_t, N> indices{};
+ std::size_t* keep = &indices[0];
+ for (std::size_t i = 0; i < sizeof...(b); ++i)
+ if (bs[i])
+ *keep++ = i;
+ return indices;
+ }
+
+ static constexpr auto indices = compute_indices();
+ };
+
+ template <typename Pred>
+ struct make_filter_indices {
+ Pred const& pred;
+ template <typename ...X>
+ auto operator()(X&& ...x) const -> filter_indices<
+ static_cast<bool>(detail::decay<
+ decltype(pred(static_cast<X&&>(x)))
+ >::type::value)...
+ > { return {}; }
+ };
+ }
+
+ template <typename S>
+ struct filter_impl<S, when<Sequence<S>::value>> {
+ template <typename Indices, typename Xs, std::size_t ...i>
+ static constexpr auto filter_helper(Xs&& xs, std::index_sequence<i...>) {
+ return hana::make<S>(
+ hana::at_c<Indices::indices[i]>(static_cast<Xs&&>(xs))...
+ );
+ }
+
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs&& xs, Pred const& pred) {
+ using Indices = decltype(
+ hana::unpack(static_cast<Xs&&>(xs),
+ detail::make_filter_indices<Pred>{pred})
+ );
+
+ return filter_impl::filter_helper<Indices>(
+ static_cast<Xs&&>(xs),
+ std::make_index_sequence<Indices::indices.size()>{}
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FILTER_HPP
diff --git a/boost/hana/find.hpp b/boost/hana/find.hpp
new file mode 100644
index 0000000000..b2fe1ca8aa
--- /dev/null
+++ b/boost/hana/find.hpp
@@ -0,0 +1,61 @@
+/*!
+@file
+Defines `boost::hana::find`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FIND_HPP
+#define BOOST_HANA_FIND_HPP
+
+#include <boost/hana/fwd/find.hpp>
+
+#include <boost/hana/concept/searchable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/find_if.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Key>
+ constexpr auto find_t::operator()(Xs&& xs, Key const& key) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Find = BOOST_HANA_DISPATCH_IF(find_impl<S>,
+ hana::Searchable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Searchable<S>::value,
+ "hana::find(xs, key) requires 'xs' to be Searchable");
+ #endif
+
+ return Find::apply(static_cast<Xs&&>(xs), key);
+ }
+ //! @endcond
+
+ namespace detail {
+ template <typename T>
+ struct equal_to {
+ T const& t;
+ template <typename U>
+ constexpr auto operator()(U const& u) const {
+ return hana::equal(t, u);
+ }
+ };
+ }
+
+ template <typename S, bool condition>
+ struct find_impl<S, when<condition>> : default_ {
+ template <typename Xs, typename Key>
+ static constexpr auto apply(Xs&& xs, Key const& key) {
+ return hana::find_if(static_cast<Xs&&>(xs),
+ detail::equal_to<Key>{key});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FIND_HPP
diff --git a/boost/hana/find_if.hpp b/boost/hana/find_if.hpp
new file mode 100644
index 0000000000..4de79e691e
--- /dev/null
+++ b/boost/hana/find_if.hpp
@@ -0,0 +1,177 @@
+/*!
+@file
+Defines `boost::hana::find_if`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FIND_IF_HPP
+#define BOOST_HANA_FIND_IF_HPP
+
+#include <boost/hana/fwd/find_if.hpp>
+
+#include <boost/hana/accessors.hpp>
+#include <boost/hana/at.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/iterable.hpp>
+#include <boost/hana/concept/searchable.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/concept/struct.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/decay.hpp>
+#include <boost/hana/drop_while.hpp>
+#include <boost/hana/first.hpp>
+#include <boost/hana/front.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/is_empty.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/not.hpp>
+#include <boost/hana/optional.hpp>
+#include <boost/hana/second.hpp>
+#include <boost/hana/transform.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Pred>
+ constexpr auto find_if_t::operator()(Xs&& xs, Pred&& pred) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using FindIf = BOOST_HANA_DISPATCH_IF(find_if_impl<S>,
+ hana::Searchable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Searchable<S>::value,
+ "hana::find_if(xs, pred) requires 'xs' to be a Searchable");
+ #endif
+
+ return FindIf::apply(static_cast<Xs&&>(xs), static_cast<Pred&&>(pred));
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct find_if_impl<S, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+
+ namespace detail {
+ template <typename Xs, typename Pred, std::size_t i, std::size_t N, bool Done>
+ struct advance_until;
+
+ template <typename Xs, typename Pred, std::size_t i, std::size_t N>
+ struct advance_until<Xs, Pred, i, N, false>
+ : advance_until<Xs, Pred, i + 1, N, static_cast<bool>(detail::decay<decltype(
+ std::declval<Pred>()(hana::at_c<i>(std::declval<Xs>()))
+ )>::type::value)>
+ { };
+
+ template <typename Xs, typename Pred, std::size_t N>
+ struct advance_until<Xs, Pred, N, N, false> {
+ template <typename Ys>
+ static constexpr auto apply(Ys&&) {
+ return hana::nothing;
+ }
+ };
+
+ template <typename Xs, typename Pred, std::size_t i, std::size_t N>
+ struct advance_until<Xs, Pred, i, N, true> {
+ template <typename Ys>
+ static constexpr auto apply(Ys&& ys) {
+ return hana::just(hana::at_c<i - 1>(static_cast<Ys&&>(ys)));
+ }
+ };
+ }
+
+ template <typename S>
+ struct find_if_impl<S, when<Sequence<S>::value>> {
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs&& xs, Pred&&) {
+ constexpr std::size_t N = decltype(hana::length(xs))::value;
+ return detail::advance_until<Xs&&, Pred&&, 0, N, false>::apply(
+ static_cast<Xs&&>(xs)
+ );
+ }
+ };
+
+ template <typename It>
+ struct find_if_impl<It, when<hana::Iterable<It>::value && !Sequence<It>::value>> {
+ template <typename Xs, typename Pred>
+ static constexpr auto find_if_helper(Xs&& xs, Pred&& pred, hana::true_) {
+ return hana::just(hana::front(
+ hana::drop_while(static_cast<Xs&&>(xs),
+ hana::compose(hana::not_, static_cast<Pred&&>(pred)))
+ ));
+ }
+
+ template <typename Xs, typename Pred>
+ static constexpr auto find_if_helper(Xs&&, Pred&&, hana::false_) {
+ return hana::nothing;
+ }
+
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs&& xs, Pred&& pred) {
+ constexpr bool found = !decltype(
+ hana::is_empty(hana::drop_while(static_cast<Xs&&>(xs),
+ hana::compose(hana::not_, static_cast<Pred&&>(pred))))
+ )::value;
+ return find_if_impl::find_if_helper(static_cast<Xs&&>(xs),
+ static_cast<Pred&&>(pred),
+ hana::bool_<found>{});
+ }
+ };
+
+ template <typename T, std::size_t N>
+ struct find_if_impl<T[N]> {
+ template <typename Xs>
+ static constexpr auto find_if_helper(Xs&&, hana::false_)
+ { return hana::nothing; }
+
+ template <typename Xs>
+ static constexpr auto find_if_helper(Xs&& xs, hana::true_)
+ { return hana::just(static_cast<Xs&&>(xs)[0]); }
+
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs&& xs, Pred&& pred) {
+ return find_if_helper(static_cast<Xs&&>(xs),
+ hana::bool_c<decltype(
+ static_cast<Pred&&>(pred)(static_cast<Xs&&>(xs)[0])
+ )::value>
+ );
+ }
+ };
+
+ namespace struct_detail {
+ template <typename X>
+ struct get_member {
+ X x;
+ template <typename Member>
+ constexpr decltype(auto) operator()(Member&& member) && {
+ return hana::second(static_cast<Member&&>(member))(
+ static_cast<X&&>(x)
+ );
+ }
+ };
+ }
+
+ template <typename S>
+ struct find_if_impl<S, when<hana::Struct<S>::value>> {
+ template <typename X, typename Pred>
+ static constexpr decltype(auto) apply(X&& x, Pred&& pred) {
+ return hana::transform(
+ hana::find_if(hana::accessors<S>(),
+ hana::compose(static_cast<Pred&&>(pred), hana::first)
+ ),
+ struct_detail::get_member<X>{static_cast<X&&>(x)}
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FIND_IF_HPP
diff --git a/boost/hana/first.hpp b/boost/hana/first.hpp
new file mode 100644
index 0000000000..1e7ce828c3
--- /dev/null
+++ b/boost/hana/first.hpp
@@ -0,0 +1,45 @@
+/*!
+@file
+Defines `boost::hana::first`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FIRST_HPP
+#define BOOST_HANA_FIRST_HPP
+
+#include <boost/hana/fwd/first.hpp>
+
+#include <boost/hana/concept/product.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Pair>
+ constexpr decltype(auto) first_t::operator()(Pair&& pair) const {
+ using P = typename hana::tag_of<Pair>::type;
+ using First = BOOST_HANA_DISPATCH_IF(first_impl<P>,
+ hana::Product<P>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Product<P>::value,
+ "hana::first(pair) requires 'pair' to be a Product");
+ #endif
+
+ return First::apply(static_cast<Pair&&>(pair));
+ }
+ //! @endcond
+
+ template <typename P, bool condition>
+ struct first_impl<P, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FIRST_HPP
diff --git a/boost/hana/flatten.hpp b/boost/hana/flatten.hpp
new file mode 100644
index 0000000000..a481c3ae19
--- /dev/null
+++ b/boost/hana/flatten.hpp
@@ -0,0 +1,62 @@
+/*!
+@file
+Defines `boost::hana::flatten`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FLATTEN_HPP
+#define BOOST_HANA_FLATTEN_HPP
+
+#include <boost/hana/fwd/flatten.hpp>
+
+#include <boost/hana/concept/monad.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/detail/unpack_flatten.hpp>
+#include <boost/hana/functional/id.hpp>
+#include <boost/hana/fwd/chain.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs>
+ constexpr auto flatten_t::operator()(Xs&& xs) const {
+ using M = typename hana::tag_of<Xs>::type;
+ using Flatten = BOOST_HANA_DISPATCH_IF(flatten_impl<M>,
+ hana::Monad<M>::value
+ );
+
+#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Monad<M>::value,
+ "hana::flatten(xs) requires 'xs' to be a Monad");
+#endif
+
+ return Flatten::apply(static_cast<Xs&&>(xs));
+ }
+ //! @endcond
+
+ template <typename M, bool condition>
+ struct flatten_impl<M, when<condition>> : default_ {
+ template <typename Xs>
+ static constexpr auto apply(Xs&& xs)
+ { return hana::chain(static_cast<Xs&&>(xs), hana::id); }
+ };
+
+ template <typename S>
+ struct flatten_impl<S, when<Sequence<S>::value>> {
+ template <typename Xs>
+ static constexpr auto apply(Xs&& xs) {
+ return detail::unpack_flatten(static_cast<Xs&&>(xs), hana::make<S>);
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FLATTEN_HPP
diff --git a/boost/hana/fold.hpp b/boost/hana/fold.hpp
new file mode 100644
index 0000000000..55adba06d1
--- /dev/null
+++ b/boost/hana/fold.hpp
@@ -0,0 +1,17 @@
+/*!
+@file
+Defines `boost::hana::fold`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FOLD_HPP
+#define BOOST_HANA_FOLD_HPP
+
+#include <boost/hana/fwd/fold.hpp>
+
+#include <boost/hana/fold_left.hpp>
+
+#endif // !BOOST_HANA_FOLD_HPP
diff --git a/boost/hana/fold_left.hpp b/boost/hana/fold_left.hpp
new file mode 100644
index 0000000000..23fee4035f
--- /dev/null
+++ b/boost/hana/fold_left.hpp
@@ -0,0 +1,97 @@
+/*!
+@file
+Defines `boost::hana::fold_left`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FOLD_LEFT_HPP
+#define BOOST_HANA_FOLD_LEFT_HPP
+
+#include <boost/hana/fwd/fold_left.hpp>
+
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/variadic/foldl1.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/unpack.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename State, typename F>
+ constexpr decltype(auto) fold_left_t::operator()(Xs&& xs, State&& state, F&& f) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using FoldLeft = BOOST_HANA_DISPATCH_IF(fold_left_impl<S>,
+ hana::Foldable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Foldable<S>::value,
+ "hana::fold_left(xs, state, f) requires 'xs' to be Foldable");
+ #endif
+
+ return FoldLeft::apply(static_cast<Xs&&>(xs),
+ static_cast<State&&>(state),
+ static_cast<F&&>(f));
+ }
+
+ template <typename Xs, typename F>
+ constexpr decltype(auto) fold_left_t::operator()(Xs&& xs, F&& f) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using FoldLeft = BOOST_HANA_DISPATCH_IF(fold_left_impl<S>,
+ hana::Foldable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Foldable<S>::value,
+ "hana::fold_left(xs, f) requires 'xs' to be Foldable");
+ #endif
+
+ return FoldLeft::apply(static_cast<Xs&&>(xs), static_cast<F&&>(f));
+ }
+ //! @endcond
+
+ namespace detail {
+ template <typename F, typename State>
+ struct variadic_foldl1 {
+ F& f;
+ State& state;
+ template <typename ...T>
+ constexpr decltype(auto) operator()(T&& ...t) const {
+ return detail::variadic::foldl1(
+ static_cast<F&&>(f),
+ static_cast<State&&>(state),
+ static_cast<T&&>(t)...
+ );
+ }
+ };
+ }
+
+ template <typename T, bool condition>
+ struct fold_left_impl<T, when<condition>> : default_ {
+ // with state
+ template <typename Xs, typename S, typename F>
+ static constexpr decltype(auto) apply(Xs&& xs, S&& s, F&& f) {
+ return hana::unpack(static_cast<Xs&&>(xs),
+ detail::variadic_foldl1<F, S>{f, s}
+ );
+ }
+
+ // without state
+ template <typename Xs, typename F>
+ static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
+ return hana::unpack(static_cast<Xs&&>(xs),
+ hana::partial(
+ detail::variadic::foldl1,
+ static_cast<F&&>(f)
+ )
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FOLD_LEFT_HPP
diff --git a/boost/hana/fold_right.hpp b/boost/hana/fold_right.hpp
new file mode 100644
index 0000000000..60979a9201
--- /dev/null
+++ b/boost/hana/fold_right.hpp
@@ -0,0 +1,97 @@
+/*!
+@file
+Defines `boost::hana::fold_right`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FOLD_RIGHT_HPP
+#define BOOST_HANA_FOLD_RIGHT_HPP
+
+#include <boost/hana/fwd/fold_right.hpp>
+
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/variadic/foldr1.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/fwd/unpack.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename State, typename F>
+ constexpr decltype(auto) fold_right_t::operator()(Xs&& xs, State&& state, F&& f) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using FoldRight = BOOST_HANA_DISPATCH_IF(fold_right_impl<S>,
+ hana::Foldable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Foldable<S>::value,
+ "hana::fold_right(xs, state, f) requires 'xs' to be Foldable");
+ #endif
+
+ return FoldRight::apply(static_cast<Xs&&>(xs),
+ static_cast<State&&>(state),
+ static_cast<F&&>(f));
+ }
+
+ template <typename Xs, typename F>
+ constexpr decltype(auto) fold_right_t::operator()(Xs&& xs, F&& f) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using FoldRight = BOOST_HANA_DISPATCH_IF(fold_right_impl<S>,
+ hana::Foldable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Foldable<S>::value,
+ "hana::fold_right(xs, f) requires 'xs' to be Foldable");
+ #endif
+
+ return FoldRight::apply(static_cast<Xs&&>(xs), static_cast<F&&>(f));
+ }
+ //! @endcond
+
+ namespace detail {
+ template <typename F, typename State>
+ struct variadic_foldr {
+ F& f;
+ State& state;
+ template <typename ...T>
+ constexpr decltype(auto) operator()(T&& ...t) const {
+ return detail::variadic::foldr(
+ static_cast<F&&>(f),
+ static_cast<State&&>(state),
+ static_cast<T&&>(t)...
+ );
+ }
+ };
+ }
+
+ template <typename T, bool condition>
+ struct fold_right_impl<T, when<condition>> : default_ {
+ // with state
+ template <typename Xs, typename S, typename F>
+ static constexpr decltype(auto) apply(Xs&& xs, S&& s, F&& f) {
+ return hana::unpack(static_cast<Xs&&>(xs),
+ detail::variadic_foldr<F, S>{f, s}
+ );
+ }
+
+ // without state
+ template <typename Xs, typename F>
+ static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
+ return hana::unpack(static_cast<Xs&&>(xs),
+ hana::partial(
+ detail::variadic::foldr1,
+ static_cast<F&&>(f)
+ )
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FOLD_RIGHT_HPP
diff --git a/boost/hana/for_each.hpp b/boost/hana/for_each.hpp
new file mode 100644
index 0000000000..091b83c38c
--- /dev/null
+++ b/boost/hana/for_each.hpp
@@ -0,0 +1,62 @@
+/*!
+@file
+Defines `boost::hana::for_each`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FOR_EACH_HPP
+#define BOOST_HANA_FOR_EACH_HPP
+
+#include <boost/hana/fwd/for_each.hpp>
+
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/unpack.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename F>
+ constexpr void for_each_t::operator()(Xs&& xs, F&& f) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using ForEach = BOOST_HANA_DISPATCH_IF(for_each_impl<S>,
+ hana::Foldable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Foldable<S>::value,
+ "hana::for_each(xs, f) requires 'xs' to be Foldable");
+ #endif
+
+ return ForEach::apply(static_cast<Xs&&>(xs), static_cast<F&&>(f));
+ }
+ //! @endcond
+
+ namespace detail {
+ template <typename F>
+ struct on_each {
+ F f;
+ template <typename ...Xs>
+ constexpr void operator()(Xs&& ...xs) const {
+ using Swallow = int[];
+ (void)Swallow{0, ((void)(*f)(static_cast<Xs&&>(xs)), 0)...};
+ }
+ };
+ }
+
+ template <typename T, bool condition>
+ struct for_each_impl<T, when<condition>> : default_ {
+ template <typename Xs, typename F>
+ static constexpr void apply(Xs&& xs, F&& f) {
+ // We use a pointer instead of a reference to avoid a Clang ICE.
+ hana::unpack(static_cast<Xs&&>(xs),
+ detail::on_each<decltype(&f)>{&f});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FOR_EACH_HPP
diff --git a/boost/hana/front.hpp b/boost/hana/front.hpp
new file mode 100644
index 0000000000..e8b53de32d
--- /dev/null
+++ b/boost/hana/front.hpp
@@ -0,0 +1,47 @@
+/*!
+@file
+Defines `boost::hana::front`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FRONT_HPP
+#define BOOST_HANA_FRONT_HPP
+
+#include <boost/hana/fwd/front.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/iterable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs>
+ constexpr decltype(auto) front_t::operator()(Xs&& xs) const {
+ using It = typename hana::tag_of<Xs>::type;
+ using Front = BOOST_HANA_DISPATCH_IF(front_impl<It>,
+ hana::Iterable<It>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Iterable<It>::value,
+ "hana::front(xs) requires 'xs' to be an Iterable");
+ #endif
+
+ return Front::apply(static_cast<Xs&&>(xs));
+ }
+ //! @endcond
+
+ template <typename It, bool condition>
+ struct front_impl<It, when<condition>> : default_ {
+ template <typename Xs>
+ static constexpr decltype(auto) apply(Xs&& xs)
+ { return hana::at_c<0>(static_cast<Xs&&>(xs)); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FRONT_HPP
diff --git a/boost/hana/functional.hpp b/boost/hana/functional.hpp
new file mode 100644
index 0000000000..152cf58bf0
--- /dev/null
+++ b/boost/hana/functional.hpp
@@ -0,0 +1,33 @@
+/*!
+@file
+Defines the @ref group-functional module.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUNCTIONAL_HPP
+#define BOOST_HANA_FUNCTIONAL_HPP
+
+#include <boost/hana/functional/always.hpp>
+#include <boost/hana/functional/apply.hpp>
+#include <boost/hana/functional/arg.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/functional/curry.hpp>
+#include <boost/hana/functional/demux.hpp>
+#include <boost/hana/functional/fix.hpp>
+#include <boost/hana/functional/flip.hpp>
+#include <boost/hana/functional/id.hpp>
+#include <boost/hana/functional/infix.hpp>
+#include <boost/hana/functional/iterate.hpp>
+#include <boost/hana/functional/lockstep.hpp>
+#include <boost/hana/functional/on.hpp>
+#include <boost/hana/functional/overload.hpp>
+#include <boost/hana/functional/overload_linearly.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/functional/placeholder.hpp>
+#include <boost/hana/functional/reverse_partial.hpp>
+
+#endif // !BOOST_HANA_FUNCTIONAL_HPP
diff --git a/boost/hana/functional/always.hpp b/boost/hana/functional/always.hpp
new file mode 100644
index 0000000000..249233d3f2
--- /dev/null
+++ b/boost/hana/functional/always.hpp
@@ -0,0 +1,64 @@
+/*!
+@file
+Defines `boost::hana::always`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUNCTIONAL_ALWAYS_HPP
+#define BOOST_HANA_FUNCTIONAL_ALWAYS_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/create.hpp>
+
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Return a constant function returning `x` regardless of the
+ //! argument(s) it is invoked with.
+ //!
+ //! Specifically, `always(x)` is a function such that
+ //! @code
+ //! always(x)(y...) == x
+ //! @endcode
+ //! for any `y...`. A copy of `x` is made and it is owned by the
+ //! `always(x)` function. When `always(x)` is called, it will return
+ //! a reference to the `x` it owns. This reference is valid as long
+ //! as `always(x)` is in scope.
+ //!
+ //!
+ //! ### Example
+ //! @include example/functional/always.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto always = [](auto&& x) {
+ return [perfect-capture](auto const& ...y) -> decltype(auto) {
+ return forwarded(x);
+ };
+ };
+#else
+ template <typename T>
+ struct _always {
+ T val_;
+
+ template <typename ...Args>
+ constexpr T const& operator()(Args const& ...) const&
+ { return val_; }
+
+ template <typename ...Args>
+ constexpr T& operator()(Args const& ...) &
+ { return val_; }
+
+ template <typename ...Args>
+ constexpr T operator()(Args const& ...) &&
+ { return std::move(val_); }
+ };
+
+ constexpr detail::create<_always> always{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_ALWAYS_HPP
diff --git a/boost/hana/functional/apply.hpp b/boost/hana/functional/apply.hpp
new file mode 100644
index 0000000000..75a7f9483d
--- /dev/null
+++ b/boost/hana/functional/apply.hpp
@@ -0,0 +1,85 @@
+/*!
+@file
+Defines `boost::hana::apply`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUNCTIONAL_APPLY_HPP
+#define BOOST_HANA_FUNCTIONAL_APPLY_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Invokes a Callable with the given arguments.
+ //!
+ //! This is equivalent to [std::invoke][1] that will be added in C++17.
+ //! However, `apply` is a function object instead of a function, which
+ //! makes it possible to pass it to higher-order algorithms.
+ //!
+ //!
+ //! @param f
+ //! A [Callable][2] to be invoked with the given arguments.
+ //!
+ //! @param x...
+ //! The arguments to call `f` with. The number of `x...` must match the
+ //! arity of `f`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/functional/apply.cpp
+ //!
+ //! [1]: http://en.cppreference.com/w/cpp/utility/functional/invoke
+ //! [2]: http://en.cppreference.com/w/cpp/concept/Callable
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto apply = [](auto&& f, auto&& ...x) -> decltype(auto) {
+ return forwarded(f)(forwarded(x)...);
+ };
+#else
+ struct apply_t {
+ template <typename F, typename... Args>
+ constexpr auto operator()(F&& f, Args&&... args) const ->
+ decltype(static_cast<F&&>(f)(static_cast<Args&&>(args)...))
+ {
+ return static_cast<F&&>(f)(static_cast<Args&&>(args)...);
+ }
+
+ template <typename Base, typename T, typename Derived>
+ constexpr auto operator()(T Base::*pmd, Derived&& ref) const ->
+ decltype(static_cast<Derived&&>(ref).*pmd)
+ {
+ return static_cast<Derived&&>(ref).*pmd;
+ }
+
+ template <typename PMD, typename Pointer>
+ constexpr auto operator()(PMD pmd, Pointer&& ptr) const ->
+ decltype((*static_cast<Pointer&&>(ptr)).*pmd)
+ {
+ return (*static_cast<Pointer&&>(ptr)).*pmd;
+ }
+
+ template <typename Base, typename T, typename Derived, typename... Args>
+ constexpr auto operator()(T Base::*pmf, Derived&& ref, Args&&... args) const ->
+ decltype((static_cast<Derived&&>(ref).*pmf)(static_cast<Args&&>(args)...))
+ {
+ return (static_cast<Derived&&>(ref).*pmf)(static_cast<Args&&>(args)...);
+ }
+
+ template <typename PMF, typename Pointer, typename... Args>
+ constexpr auto operator()(PMF pmf, Pointer&& ptr, Args&& ...args) const ->
+ decltype(((*static_cast<Pointer&&>(ptr)).*pmf)(static_cast<Args&&>(args)...))
+ {
+ return ((*static_cast<Pointer&&>(ptr)).*pmf)(static_cast<Args&&>(args)...);
+ }
+ };
+
+ constexpr apply_t apply{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_APPLY_HPP
diff --git a/boost/hana/functional/arg.hpp b/boost/hana/functional/arg.hpp
new file mode 100644
index 0000000000..c9c68f0eae
--- /dev/null
+++ b/boost/hana/functional/arg.hpp
@@ -0,0 +1,141 @@
+/*!
+@file
+Defines `boost::hana::arg`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUNCTIONAL_ARG_HPP
+#define BOOST_HANA_FUNCTIONAL_ARG_HPP
+
+#include <boost/hana/config.hpp>
+
+#include <cstddef>
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Return the `n`th passed argument.
+ //!
+ //! Specifically, `arg<n>(x1, ..., xn, ..., xm)` is equivalent to `xn`.
+ //! Note that indexing starts at 1, so `arg<1>` returns the 1st argument,
+ //! `arg<2>` the 2nd and so on. Using `arg<0>` is an error. Passing
+ //! less than `n` arguments to `arg<n>` is also an error.
+ //!
+ //!
+ //! @tparam n
+ //! An unsigned integer representing the argument to return. `n` must be
+ //! positive (meaning nonzero).
+ //!
+ //! @param x1, ..., xm
+ //! A variadic pack of arguments from which the `n`th one is returned.
+ //!
+ //!
+ //! @internal
+ //! ### Discussion: could `n` be dynamic?
+ //! We could have chosen `arg` to be used like `arg(n)(x...)` instead of
+ //! `arg<n>(x...)`. Provided all the arguments were of the same type, it
+ //! would then be possible for `n` to only be known at runtime. However,
+ //! we would then lose the ability to assert the in-boundedness of `n`
+ //! statically.
+ //!
+ //! ### Rationale for `n` being a non-type template parameter
+ //! I claim that the only interesting use case is with a compile-time
+ //! `n`, which means that the usage would become `arg(int_<n>)(x...)`,
+ //! which is more cumbersome to write than `arg<n>(x...)`. This is open
+ //! for discussion.
+ //! @endinternal
+ //!
+ //! ### Example
+ //! @include example/functional/arg.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <std::size_t n>
+ constexpr auto arg = [](auto&& x1, ..., auto&& xm) -> decltype(auto) {
+ return forwarded(xn);
+ };
+#else
+ template <std::size_t n, typename = void>
+ struct arg_t;
+
+ template <>
+ struct arg_t<1> {
+ template <typename X1, typename ...Xn>
+ constexpr X1 operator()(X1&& x1, Xn&& ...) const
+ { return static_cast<X1&&>(x1); }
+ };
+
+ template <>
+ struct arg_t<2> {
+ template <typename X1, typename X2, typename ...Xn>
+ constexpr X2 operator()(X1&&, X2&& x2, Xn&& ...) const
+ { return static_cast<X2&&>(x2); }
+ };
+
+ template <>
+ struct arg_t<3> {
+ template <typename X1, typename X2, typename X3, typename ...Xn>
+ constexpr X3 operator()(X1&&, X2&&, X3&& x3, Xn&& ...) const
+ { return static_cast<X3&&>(x3); }
+ };
+
+ template <>
+ struct arg_t<4> {
+ template <typename X1, typename X2, typename X3, typename X4, typename ...Xn>
+ constexpr X4 operator()(X1&&, X2&&, X3&&, X4&& x4, Xn&& ...) const
+ { return static_cast<X4&&>(x4); }
+ };
+
+ template <>
+ struct arg_t<5> {
+ template <typename X1, typename X2, typename X3, typename X4,
+ typename X5, typename ...Xn>
+ constexpr X5 operator()(X1&&, X2&&, X3&&, X4&&, X5&& x5, Xn&& ...) const
+ { return static_cast<X5&&>(x5); }
+ };
+
+ template <std::size_t n, typename>
+ struct arg_t {
+ static_assert(n > 0,
+ "invalid usage of boost::hana::arg<n> with n == 0");
+
+ template <typename X1, typename X2, typename X3, typename X4,
+ typename X5, typename ...Xn>
+ constexpr decltype(auto)
+ operator()(X1&&, X2&&, X3&&, X4&&, X5&&, Xn&& ...xn) const {
+ static_assert(sizeof...(xn) >= n - 5,
+ "invalid usage of boost::hana::arg<n> with too few arguments");
+
+ // Since compilers will typically try to continue for a bit after
+ // an error/static assertion, we must avoid sending the compiler
+ // in a very long computation if n == 0.
+ return arg_t<n == 0 ? 1 : n - 5>{}(static_cast<Xn&&>(xn)...);
+ }
+ };
+
+ template <std::size_t n>
+ struct arg_t<n, std::enable_if_t<(n > 25)>> {
+ template <
+ typename X1, typename X2, typename X3, typename X4, typename X5,
+ typename X6, typename X7, typename X8, typename X9, typename X10,
+ typename X11, typename X12, typename X13, typename X14, typename X15,
+ typename X16, typename X17, typename X18, typename X19, typename X20,
+ typename X21, typename X22, typename X23, typename X24, typename X25,
+ typename ...Xn>
+ constexpr decltype(auto)
+ operator()(X1&&, X2&&, X3&&, X4&&, X5&&,
+ X6&&, X7&&, X8&&, X9&&, X10&&,
+ X11&&, X12&&, X13&&, X14&&, X15&&,
+ X16&&, X17&&, X18&&, X19&&, X20&&,
+ X21&&, X22&&, X23&&, X24&&, X25&&, Xn&& ...xn) const
+ { return arg_t<n - 25>{}(static_cast<Xn&&>(xn)...); }
+ };
+
+ template <std::size_t n>
+ constexpr arg_t<n> arg{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_ARG_HPP
diff --git a/boost/hana/functional/capture.hpp b/boost/hana/functional/capture.hpp
new file mode 100644
index 0000000000..0b5a4677d8
--- /dev/null
+++ b/boost/hana/functional/capture.hpp
@@ -0,0 +1,112 @@
+/*!
+@file
+Defines `boost::hana::capture`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUNCTIONAL_CAPTURE_HPP
+#define BOOST_HANA_FUNCTIONAL_CAPTURE_HPP
+
+#include <boost/hana/basic_tuple.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/decay.hpp>
+#include <boost/hana/functional/partial.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Create a function capturing the given variables.
+ //!
+ //! Given 0 or more variables, `capture` creates a closure that can be
+ //! used to partially apply a function. This is very similar to `partial`,
+ //! except that `capture` allows the partially applied function to be
+ //! specified later. Specifically, `capture(vars...)` is a function object
+ //! taking a function `f` and returning `f` partially applied to `vars...`.
+ //! In other words,
+ //! @code
+ //! capture(vars...)(f)(args...) == f(vars..., args...)
+ //! @endcode
+ //!
+ //! @note
+ //! The arity of `f` must match the total number of arguments passed to
+ //! it, i.e. `sizeof...(vars) + sizeof...(args)`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/functional/capture.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto capture = [](auto&& ...variables) {
+ return [perfect-capture](auto&& f) {
+ return [perfect-capture](auto&& ...args) -> decltype(auto) {
+ return forwarded(f)(forwarded(variables)..., forwarded(args)...);
+ };
+ };
+ };
+#else
+ namespace detail {
+ template <typename F, typename Closure, std::size_t ...i>
+ constexpr auto apply_capture(F&& f, Closure&& closure, std::index_sequence<i...>) {
+ return hana::partial(static_cast<F&&>(f),
+ hana::get_impl<i>(static_cast<Closure&&>(closure).storage_)...
+ );
+ }
+ }
+
+ template <typename ...X>
+ struct capture_t;
+
+ struct make_capture_t {
+ struct secret { };
+ template <typename ...X>
+ constexpr capture_t<typename detail::decay<X>::type...>
+ operator()(X&& ...x) const {
+ return {secret{}, static_cast<X&&>(x)...};
+ }
+ };
+
+ template <typename ...X>
+ struct capture_t {
+ template <typename ...Y>
+ constexpr capture_t(make_capture_t::secret, Y&& ...y)
+ : storage_{static_cast<Y&&>(y)...}
+ { }
+
+ basic_tuple<X...> storage_;
+
+ template <typename F>
+ constexpr auto operator()(F&& f) const& {
+ return detail::apply_capture(
+ static_cast<F&&>(f), *this,
+ std::make_index_sequence<sizeof...(X)>{}
+ );
+ }
+
+ template <typename F>
+ constexpr auto operator()(F&& f) & {
+ return detail::apply_capture(
+ static_cast<F&&>(f), *this,
+ std::make_index_sequence<sizeof...(X)>{}
+ );
+ }
+
+ template <typename F>
+ constexpr auto operator()(F&& f) && {
+ return detail::apply_capture(
+ static_cast<F&&>(f), static_cast<capture_t&&>(*this),
+ std::make_index_sequence<sizeof...(X)>{}
+ );
+ }
+ };
+
+ constexpr make_capture_t capture{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_CAPTURE_HPP
diff --git a/boost/hana/functional/compose.hpp b/boost/hana/functional/compose.hpp
new file mode 100644
index 0000000000..3250cee4db
--- /dev/null
+++ b/boost/hana/functional/compose.hpp
@@ -0,0 +1,108 @@
+/*!
+@file
+Defines `boost::hana::compose`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUNCTIONAL_COMPOSE_HPP
+#define BOOST_HANA_FUNCTIONAL_COMPOSE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/create.hpp>
+#include <boost/hana/detail/variadic/foldl1.hpp>
+
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Return the composition of two functions or more.
+ //!
+ //! `compose` is defined inductively. When given more than two functions,
+ //! `compose(f, g, h...)` is equivalent to `compose(f, compose(g, h...))`.
+ //! When given two functions, `compose(f, g)` is a function such that
+ //! @code
+ //! compose(f, g)(x, y...) == f(g(x), y...)
+ //! @endcode
+ //!
+ //! If you need composition of the form `f(g(x, y...))`, use `demux` instead.
+ //!
+ //! @note
+ //! `compose` is an associative operation; `compose(f, compose(g, h))`
+ //! is equivalent to `compose(compose(f, g), h)`.
+ //!
+ //! @internal
+ //! ### Proof of associativity
+ //!
+ //! @code
+ //! compose(f, compose(g, h))(x, xs...) == f(compose(g, h)(x), xs...)
+ //! == f(g(h(x)), xs...)
+ //!
+ //! compose(compose(f, g), h)(x, xs...) == compose(f, g)(h(x), xs...)
+ //! == f(g(h(x)), xs...)
+ //! @endcode
+ //! @endinternal
+ //!
+ //! ### Example
+ //! @include example/functional/compose.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto compose = [](auto&& f1, auto&& f2, ..., auto&& fn) {
+ return [perfect-capture](auto&& x, auto&& ...xs) -> decltype(auto) {
+ return forwarded(f1)(
+ forwarded(f2)(
+ ...
+ forwarded(fn)(forwarded(x))
+ ),
+ forwarded(xs)...
+ );
+ }
+ };
+#else
+ template <typename F, typename G>
+ struct _compose {
+ F f; G g;
+
+ template <typename X, typename ...Xs>
+ constexpr decltype(auto) operator()(X&& x, Xs&& ...xs) const& {
+ return f(
+ g(static_cast<X&&>(x)),
+ static_cast<Xs&&>(xs)...
+ );
+ }
+
+ template <typename X, typename ...Xs>
+ constexpr decltype(auto) operator()(X&& x, Xs&& ...xs) & {
+ return f(
+ g(static_cast<X&&>(x)),
+ static_cast<Xs&&>(xs)...
+ );
+ }
+
+ template <typename X, typename ...Xs>
+ constexpr decltype(auto) operator()(X&& x, Xs&& ...xs) && {
+ return std::move(f)(
+ std::move(g)(static_cast<X&&>(x)),
+ static_cast<Xs&&>(xs)...
+ );
+ }
+ };
+
+ struct _make_compose {
+ template <typename F, typename G, typename ...H>
+ constexpr decltype(auto) operator()(F&& f, G&& g, H&& ...h) const {
+ return detail::variadic::foldl1(detail::create<_compose>{},
+ static_cast<F&&>(f),
+ static_cast<G&&>(g),
+ static_cast<H&&>(h)...
+ );
+ }
+ };
+
+ constexpr _make_compose compose{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_COMPOSE_HPP
diff --git a/boost/hana/functional/curry.hpp b/boost/hana/functional/curry.hpp
new file mode 100644
index 0000000000..23b3694b8c
--- /dev/null
+++ b/boost/hana/functional/curry.hpp
@@ -0,0 +1,169 @@
+/*!
+@file
+Defines `boost::hana::curry`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUNCTIONAL_CURRY_HPP
+#define BOOST_HANA_FUNCTIONAL_CURRY_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/functional/apply.hpp>
+#include <boost/hana/functional/partial.hpp>
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Curry a function up to the given number of arguments.
+ //!
+ //! [Currying][Wikipedia.currying] is a technique in which we consider a
+ //! function taking multiple arguments (or, equivalently, a tuple of
+ //! arguments), and turn it into a function which takes a single argument
+ //! and returns a function to handle the remaining arguments. To help
+ //! visualize, let's denote the type of a function `f` which takes
+ //! arguments of types `X1, ..., Xn` and returns a `R` as
+ //! @code
+ //! (X1, ..., Xn) -> R
+ //! @endcode
+ //!
+ //! Then, currying is the process of taking `f` and turning it into an
+ //! equivalent function (call it `g`) of type
+ //! @code
+ //! X1 -> (X2 -> (... -> (Xn -> R)))
+ //! @endcode
+ //!
+ //! This gives us the following equivalence, where `x1`, ..., `xn` are
+ //! objects of type `X1`, ..., `Xn` respectively:
+ //! @code
+ //! f(x1, ..., xn) == g(x1)...(xn)
+ //! @endcode
+ //!
+ //! Currying can be useful in several situations, especially when working
+ //! with higher-order functions.
+ //!
+ //! This `curry` utility is an implementation of currying in C++.
+ //! Specifically, `curry<n>(f)` is a function such that
+ //! @code
+ //! curry<n>(f)(x1)...(xn) == f(x1, ..., xn)
+ //! @endcode
+ //!
+ //! Note that the `n` has to be specified explicitly because the existence
+ //! of functions with variadic arguments in C++ make it impossible to know
+ //! when currying should stop.
+ //!
+ //! Unlike usual currying, this implementation also allows a curried
+ //! function to be called with several arguments at a time. Hence, the
+ //! following always holds
+ //! @code
+ //! curry<n>(f)(x1, ..., xk) == curry<n - k>(f)(x1)...(xk)
+ //! @endcode
+ //!
+ //! Of course, this requires `k` to be less than or equal to `n`; failure
+ //! to satisfy this will trigger a static assertion. This syntax is
+ //! supported because it makes curried functions usable where normal
+ //! functions are expected.
+ //!
+ //! Another "extension" is that `curry<0>(f)` is supported: `curry<0>(f)`
+ //! is a nullary function; whereas the classical definition for currying
+ //! seems to leave this case undefined, as nullary functions don't make
+ //! much sense in purely functional languages.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/functional/curry.cpp
+ //!
+ //!
+ //! [Wikipedia.currying]: http://en.wikipedia.org/wiki/Currying
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <std::size_t n>
+ constexpr auto curry = [](auto&& f) {
+ return [perfect-capture](auto&& x1) {
+ return [perfect-capture](auto&& x2) {
+ ...
+ return [perfect-capture](auto&& xn) -> decltype(auto) {
+ return forwarded(f)(
+ forwarded(x1), forwarded(x2), ..., forwarded(xn)
+ );
+ };
+ };
+ };
+ };
+#else
+ template <std::size_t n, typename F>
+ struct curry_t;
+
+ template <std::size_t n>
+ struct make_curry_t {
+ template <typename F>
+ constexpr curry_t<n, typename std::decay<F>::type>
+ operator()(F&& f) const { return {static_cast<F&&>(f)}; }
+ };
+
+ template <std::size_t n>
+ constexpr make_curry_t<n> curry{};
+
+ namespace curry_detail {
+ 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 {
+ F f;
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) const& {
+ static_assert(sizeof...(x) <= n,
+ "too many arguments provided to boost::hana::curry");
+ return curry_detail::curry_or_call<n - sizeof...(x)>(
+ partial(f, static_cast<X&&>(x)...)
+ );
+ }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) & {
+ static_assert(sizeof...(x) <= n,
+ "too many arguments provided to boost::hana::curry");
+ return curry_detail::curry_or_call<n - sizeof...(x)>(
+ partial(f, static_cast<X&&>(x)...)
+ );
+ }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) && {
+ static_assert(sizeof...(x) <= n,
+ "too many arguments provided to boost::hana::curry");
+ return curry_detail::curry_or_call<n - sizeof...(x)>(
+ partial(std::move(f), static_cast<X&&>(x)...)
+ );
+ }
+ };
+
+ template <typename F>
+ struct curry_t<0, F> {
+ F f;
+
+ constexpr decltype(auto) operator()() const&
+ { return f(); }
+
+ constexpr decltype(auto) operator()() &
+ { return f(); }
+
+ constexpr decltype(auto) operator()() &&
+ { return std::move(f)(); }
+ };
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_CURRY_HPP
diff --git a/boost/hana/functional/demux.hpp b/boost/hana/functional/demux.hpp
new file mode 100644
index 0000000000..c1ed03634e
--- /dev/null
+++ b/boost/hana/functional/demux.hpp
@@ -0,0 +1,269 @@
+/*!
+@file
+Defines `boost::hana::demux`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUNCTIONAL_DEMUX_HPP
+#define BOOST_HANA_FUNCTIONAL_DEMUX_HPP
+
+#include <boost/hana/basic_tuple.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/decay.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Invoke a function with the results of invoking other functions
+ //! on its arguments.
+ //!
+ //! Specifically, `demux(f)(g...)` is a function such that
+ //! @code
+ //! demux(f)(g...)(x...) == f(g(x...)...)
+ //! @endcode
+ //!
+ //! Each `g` is called with all the arguments, and then `f` is called
+ //! with the result of each `g`. Hence, the arity of `f` must match
+ //! the number of `g`s.
+ //!
+ //! This is called `demux` because of a vague similarity between this
+ //! device and a demultiplexer in signal processing. `demux` takes what
+ //! can be seen as a continuation (`f`), a bunch of functions to split a
+ //! signal (`g...`) and zero or more arguments representing the signal
+ //! (`x...`). Then, it calls the continuation with the result of
+ //! splitting the signal with whatever functions where given.
+ //!
+ //! @note
+ //! When used with two functions only, `demux` is associative. In other
+ //! words (and noting `demux(f, g) = demux(f)(g)` to ease the notation),
+ //! it is true that `demux(demux(f, g), h) == demux(f, demux(g, h))`.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! The signature of `demux` is
+ //! \f[
+ //! \mathtt{demux} :
+ //! (B_1 \times \dotsb \times B_n \to C)
+ //! \to ((A_1 \times \dotsb \times A_n \to B_1)
+ //! \times \dotsb
+ //! \times (A_1 \times \dotsb \times A_n \to B_n))
+ //! \to (A_1 \times \dotsb \times A_n \to C)
+ //! \f]
+ //!
+ //! This can be rewritten more tersely as
+ //! \f[
+ //! \mathtt{demux} :
+ //! \left(\prod_{i=1}^n B_i \to C \right)
+ //! \to \prod_{j=1}^n \left(\prod_{i=1}^n A_i \to B_j \right)
+ //! \to \left(\prod_{i=1}^n A_i \to C \right)
+ //! \f]
+ //!
+ //!
+ //! Link with normal composition
+ //! ----------------------------
+ //! The signature of `compose` is
+ //! \f[
+ //! \mathtt{compose} : (B \to C) \times (A \to B) \to (A \to C)
+ //! \f]
+ //!
+ //! A valid observation is that this coincides exactly with the type
+ //! of `demux` when used with a single unary function. Actually, both
+ //! functions are equivalent:
+ //! @code
+ //! demux(f)(g)(x) == compose(f, g)(x)
+ //! @endcode
+ //!
+ //! However, let's now consider the curried version of `compose`,
+ //! `curry<2>(compose)`:
+ //! \f[
+ //! \mathtt{curry_2(compose)} : (B \to C) \to ((A \to B) \to (A \to C))
+ //! \f]
+ //!
+ //! For the rest of this explanation, we'll just consider the curried
+ //! version of `compose` and so we'll use `compose` instead of
+ //! `curry<2>(compose)` to lighten the notation. With currying, we can
+ //! now consider `compose` applied to itself:
+ //! \f[
+ //! \mathtt{compose(compose, compose)} :
+ //! (B \to C) \to (A_1 \to A_2 \to B) \to (A_1 \to A_2 \to C)
+ //! \f]
+ //!
+ //! If we uncurry deeply the above expression, we obtain
+ //! \f[
+ //! \mathtt{compose(compose, compose)} :
+ //! (B \to C) \times (A_1 \times A_2 \to B) \to (A_1 \times A_2 \to C)
+ //! \f]
+ //!
+ //! This signature is exactly the same as that of `demux` when given a
+ //! single binary function, and indeed they are equivalent definitions.
+ //! We can also generalize this further by considering
+ //! `compose(compose(compose, compose), compose)`:
+ //! \f[
+ //! \mathtt{compose(compose(compose, compose), compose)} :
+ //! (B \to C) \to (A_1 \to A_2 \to A_3 \to B)
+ //! \to (A_1 \to A_2 \to A_3 \to C)
+ //! \f]
+ //!
+ //! which uncurries to
+ //! \f[
+ //! \mathtt{compose(compose(compose, compose), compose)} :
+ //! (B \to C) \times (A_1 \times A_2 \times A_3 \to B)
+ //! \to (A_1 \times A_2 \times A_3 \to C)
+ //! \f]
+ //!
+ //! This signature is exactly the same as that of `demux` when given a
+ //! single ternary function. Hence, for a single n-ary function `g`,
+ //! `demux(f)(g)` is equivalent to the n-times composition of `compose`
+ //! with itself, applied to `g` and `f`:
+ //! @code
+ //! demux(f)(g) == fold_left([compose, ..., compose], id, compose)(g, f)
+ //! // ^^^^^^^^^^^^^^^^^^^^^ n times
+ //! @endcode
+ //!
+ //! More information on this insight can be seen [here][1]. Also, I'm
+ //! not sure how this insight could be generalized to more than one
+ //! function `g`, or if that is even possible.
+ //!
+ //!
+ //! Proof of associativity in the binary case
+ //! -----------------------------------------
+ //! As explained above, `demux` is associative when it is used with
+ //! two functions only. Indeed, given functions `f`, `g` and `h` with
+ //! suitable signatures, we have
+ //! @code
+ //! demux(f)(demux(g)(h))(x...) == f(demux(g)(h)(x...))
+ //! == f(g(h(x...)))
+ //! @endcode
+ //!
+ //! On the other hand, we have
+ //! @code
+ //! demux(demux(f)(g))(h)(x...) == demux(f)(g)(h(x...))
+ //! == f(g(h(x...)))
+ //! @endcode
+ //!
+ //! and hence `demux` is associative in the binary case.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/functional/demux.cpp
+ //!
+ //! [1]: http://stackoverflow.com/q/5821089/627587
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto demux = [](auto&& f) {
+ return [perfect-capture](auto&& ...g) {
+ return [perfect-capture](auto&& ...x) -> decltype(auto) {
+ // x... can't be forwarded unless there is a single g
+ // function, or that could cause double-moves.
+ return forwarded(f)(forwarded(g)(x...)...);
+ };
+ };
+ };
+#else
+ template <typename F>
+ struct pre_demux_t;
+
+ struct make_pre_demux_t {
+ struct secret { };
+ template <typename F>
+ constexpr pre_demux_t<typename detail::decay<F>::type> operator()(F&& f) const {
+ return {static_cast<F&&>(f)};
+ }
+ };
+
+ template <typename Indices, typename F, typename ...G>
+ struct demux_t;
+
+ template <typename F>
+ struct pre_demux_t {
+ F f;
+
+ template <typename ...G>
+ constexpr demux_t<std::make_index_sequence<sizeof...(G)>, F,
+ typename detail::decay<G>::type...>
+ operator()(G&& ...g) const& {
+ return {make_pre_demux_t::secret{}, this->f, static_cast<G&&>(g)...};
+ }
+
+ template <typename ...G>
+ constexpr demux_t<std::make_index_sequence<sizeof...(G)>, F,
+ typename detail::decay<G>::type...>
+ operator()(G&& ...g) && {
+ return {make_pre_demux_t::secret{}, static_cast<F&&>(this->f), static_cast<G&&>(g)...};
+ }
+ };
+
+ template <std::size_t ...n, typename F, typename ...G>
+ struct demux_t<std::index_sequence<n...>, F, G...> {
+ template <typename ...T>
+ constexpr demux_t(make_pre_demux_t::secret, T&& ...t)
+ : storage_{static_cast<T&&>(t)...}
+ { }
+
+ basic_tuple<F, G...> storage_;
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) const& {
+ return hana::get_impl<0>(storage_)(
+ hana::get_impl<n+1>(storage_)(x...)...
+ );
+ }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) & {
+ return hana::get_impl<0>(storage_)(
+ hana::get_impl<n+1>(storage_)(x...)...
+ );
+ }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) && {
+ return static_cast<F&&>(hana::get_impl<0>(storage_))(
+ static_cast<G&&>(hana::get_impl<n+1>(storage_))(x...)...
+ );
+ }
+ };
+
+ template <typename F, typename G>
+ struct demux_t<std::index_sequence<0>, F, G> {
+ template <typename ...T>
+ constexpr demux_t(make_pre_demux_t::secret, T&& ...t)
+ : storage_{static_cast<T&&>(t)...}
+ { }
+
+ basic_tuple<F, G> storage_;
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) const& {
+ return hana::get_impl<0>(storage_)(
+ hana::get_impl<1>(storage_)(static_cast<X&&>(x)...)
+ );
+ }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) & {
+ return hana::get_impl<0>(storage_)(
+ hana::get_impl<1>(storage_)(static_cast<X&&>(x)...)
+ );
+ }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) && {
+ return static_cast<F&&>(hana::get_impl<0>(storage_))(
+ static_cast<G&&>(hana::get_impl<1>(storage_))(static_cast<X&&>(x)...)
+ );
+ }
+ };
+
+ constexpr make_pre_demux_t demux{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_DEMUX_HPP
diff --git a/boost/hana/functional/fix.hpp b/boost/hana/functional/fix.hpp
new file mode 100644
index 0000000000..007ecba1a1
--- /dev/null
+++ b/boost/hana/functional/fix.hpp
@@ -0,0 +1,83 @@
+/*!
+@file
+Defines `boost::hana::fix`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUNCTIONAL_FIX_HPP
+#define BOOST_HANA_FUNCTIONAL_FIX_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/create.hpp>
+
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Return a function computing the fixed point of a function.
+ //!
+ //! `fix` is an implementation of the [Y-combinator][], also called the
+ //! fixed-point combinator. It encodes the idea of recursion, and in fact
+ //! any recursive function can be written in terms of it.
+ //!
+ //! Specifically, `fix(f)` is a function such that
+ //! @code
+ //! fix(f)(x...) == f(fix(f), x...)
+ //! @endcode
+ //!
+ //! This definition allows `f` to use its first argument as a continuation
+ //! to call itself recursively. Indeed, if `f` calls its first argument
+ //! with `y...`, it is equivalent to calling `f(fix(f), y...)` per the
+ //! above equation.
+ //!
+ //! Most of the time, it is more convenient and efficient to define
+ //! recursive functions without using a fixed-point combinator. However,
+ //! there are some cases where `fix` provides either more flexibility
+ //! (e.g. the ability to change the callback inside `f`) or makes it
+ //! possible to write functions that couldn't be defined recursively
+ //! otherwise.
+ //!
+ //! @param f
+ //! A function called as `f(self, x...)`, where `x...` are the arguments
+ //! in the `fix(f)(x...)` expression and `self` is `fix(f)`.
+ //!
+ //! ### Example
+ //! @include example/functional/fix.cpp
+ //!
+ //! [Y-combinator]: http://en.wikipedia.org/wiki/Fixed-point_combinator
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto fix = [](auto&& f) {
+ return [perfect-capture](auto&& ...x) -> decltype(auto) {
+ return forwarded(f)(fix(f), forwarded(x)...);
+ };
+ };
+#else
+ template <typename F>
+ struct fix_t;
+
+ constexpr detail::create<fix_t> fix{};
+
+ template <typename F>
+ struct fix_t {
+ F f;
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) const&
+ { return f(fix(f), static_cast<X&&>(x)...); }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) &
+ { return f(fix(f), static_cast<X&&>(x)...); }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) &&
+ { return std::move(f)(fix(f), static_cast<X&&>(x)...); }
+ };
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_FIX_HPP
diff --git a/boost/hana/functional/flip.hpp b/boost/hana/functional/flip.hpp
new file mode 100644
index 0000000000..3da81eddd7
--- /dev/null
+++ b/boost/hana/functional/flip.hpp
@@ -0,0 +1,73 @@
+/*!
+@file
+Defines `boost::hana::flip`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUNCTIONAL_FLIP_HPP
+#define BOOST_HANA_FUNCTIONAL_FLIP_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/create.hpp>
+
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Invoke a function with its two first arguments reversed.
+ //!
+ //! Specifically, `flip(f)` is a function such that
+ //! @code
+ //! flip(f)(x, y, z...) == f(y, x, z...)
+ //! @endcode
+ //!
+ //! ### Example
+ //! @include example/functional/flip.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto flip = [](auto&& f) {
+ return [perfect-capture](auto&& x, auto&& y, auto&& ...z) -> decltype(auto) {
+ return forwarded(f)(forwarded(y), forwarded(x), forwarded(z)...);
+ };
+ };
+#else
+ template <typename F>
+ struct flip_t {
+ F f;
+
+ template <typename X, typename Y, typename ...Z>
+ constexpr decltype(auto) operator()(X&& x, Y&& y, Z&& ...z) const& {
+ return f(
+ static_cast<Y&&>(y),
+ static_cast<X&&>(x),
+ static_cast<Z&&>(z)...
+ );
+ }
+
+ template <typename X, typename Y, typename ...Z>
+ constexpr decltype(auto) operator()(X&& x, Y&& y, Z&& ...z) & {
+ return f(
+ static_cast<Y&&>(y),
+ static_cast<X&&>(x),
+ static_cast<Z&&>(z)...
+ );
+ }
+
+ template <typename X, typename Y, typename ...Z>
+ constexpr decltype(auto) operator()(X&& x, Y&& y, Z&& ...z) && {
+ return std::move(f)(
+ static_cast<Y&&>(y),
+ static_cast<X&&>(x),
+ static_cast<Z&&>(z)...
+ );
+ }
+ };
+
+ constexpr detail::create<flip_t> flip{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_FLIP_HPP
diff --git a/boost/hana/functional/id.hpp b/boost/hana/functional/id.hpp
new file mode 100644
index 0000000000..e6b4e32b79
--- /dev/null
+++ b/boost/hana/functional/id.hpp
@@ -0,0 +1,38 @@
+/*!
+@file
+Defines `boost::hana::id`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUNCTIONAL_ID_HPP
+#define BOOST_HANA_FUNCTIONAL_ID_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! The identity function -- returns its argument unchanged.
+ //!
+ //! ### Example
+ //! @include example/functional/id.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto id = [](auto&& x) -> decltype(auto) {
+ return forwarded(x);
+ };
+#else
+ struct id_t {
+ template <typename T>
+ constexpr T operator()(T&& t) const {
+ return static_cast<T&&>(t);
+ }
+ };
+
+ constexpr id_t id{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_ID_HPP
diff --git a/boost/hana/functional/infix.hpp b/boost/hana/functional/infix.hpp
new file mode 100644
index 0000000000..471e4f3ac9
--- /dev/null
+++ b/boost/hana/functional/infix.hpp
@@ -0,0 +1,184 @@
+/*!
+@file
+Defines `boost::hana::infix`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUNCTIONAL_INFIX_HPP
+#define BOOST_HANA_FUNCTIONAL_INFIX_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/functional/reverse_partial.hpp>
+
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Return an equivalent function that can also be applied in infix
+ //! notation.
+ //!
+ //! Specifically, `infix(f)` is an object such that:
+ //! @code
+ //! infix(f)(x1, ..., xn) == f(x1, ..., xn)
+ //! x ^infix(f)^ y == f(x, y)
+ //! @endcode
+ //!
+ //! Hence, the returned function can still be applied using the usual
+ //! function call syntax, but it also gains the ability to be applied in
+ //! infix notation. The infix syntax allows a great deal of expressiveness,
+ //! especially when used in combination with some higher order algorithms.
+ //! Since `operator^` is left-associative, `x ^infix(f)^ y` is actually
+ //! parsed as `(x ^infix(f))^ y`. However, for flexibility, the order in
+ //! which both arguments are applied in infix notation does not matter.
+ //! Hence, it is always the case that
+ //! @code
+ //! (x ^ infix(f)) ^ y == x ^ (infix(f) ^ y)
+ //! @endcode
+ //!
+ //! However, note that applying more than one argument in infix
+ //! notation to the same side of the operator will result in a
+ //! compile-time assertion:
+ //! @code
+ //! (infix(f) ^ x) ^ y; // compile-time assertion
+ //! y ^ (x ^ infix(f)); // compile-time assertion
+ //! @endcode
+ //!
+ //! Additionally, a function created with `infix` may be partially applied
+ //! in infix notation. Specifically,
+ //! @code
+ //! (x ^ infix(f))(y1, ..., yn) == f(x, y1, ..., yn)
+ //! (infix(f) ^ y)(x1, ..., xn) == f(x1, ..., xn, y)
+ //! @endcode
+ //!
+ //! @internal
+ //! ### Rationales
+ //! 1. The `^` operator was chosen because it is left-associative and
+ //! has a low enough priority so that most expressions will render
+ //! the expected behavior.
+ //! 2. The operator can't be customimzed because that would require more
+ //! sophistication in the implementation; I want to keep it as simple
+ //! as possible. There is also an advantage in having a uniform syntax
+ //! for infix application.
+ //! @endinternal
+ //!
+ //! @param f
+ //! The function which gains the ability to be applied in infix notation.
+ //! The function must be at least binary; a compile-time error will be
+ //! triggered otherwise.
+ //!
+ //! ### Example
+ //! @include example/functional/infix.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto infix = [](auto f) {
+ return unspecified;
+ };
+#else
+ namespace infix_detail {
+ // This needs to be in the same namespace as `operator^` so it can be
+ // found by ADL.
+ template <bool left, bool right, typename F>
+ struct infix_t {
+ F f;
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) const&
+ { return f(static_cast<X&&>(x)...); }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) &
+ { return f(static_cast<X&&>(x)...); }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) &&
+ { return std::move(f)(static_cast<X&&>(x)...); }
+ };
+
+ template <bool left, bool right>
+ struct make_infix {
+ template <typename F>
+ constexpr infix_t<left, right, typename std::decay<F>::type>
+ operator()(F&& f) const { return {static_cast<F&&>(f)}; }
+ };
+
+ template <bool left, bool right>
+ struct Infix;
+ struct Object;
+
+ template <typename T>
+ struct dispatch { using type = Object; };
+
+ template <bool left, bool right, typename F>
+ struct dispatch<infix_t<left, right, F>> {
+ using type = Infix<left, right>;
+ };
+
+ template <typename, typename>
+ struct bind_infix;
+
+ // infix(f) ^ y
+ template <>
+ struct bind_infix<Infix<false, false>, Object> {
+ template <typename F, typename Y>
+ static constexpr decltype(auto) apply(F&& f, Y&& y) {
+ return make_infix<false, true>{}(
+ hana::reverse_partial(
+ static_cast<F&&>(f), static_cast<Y&&>(y)
+ )
+ );
+ }
+ };
+
+ // (x^infix(f)) ^ y
+ template <>
+ struct bind_infix<Infix<true, false>, Object> {
+ template <typename F, typename Y>
+ static constexpr decltype(auto) apply(F&& f, Y&& y) {
+ return static_cast<F&&>(f)(static_cast<Y&&>(y));
+ }
+ };
+
+ // x ^ infix(f)
+ template <>
+ struct bind_infix<Object, Infix<false, false>> {
+ template <typename X, typename F>
+ static constexpr decltype(auto) apply(X&& x, F&& f) {
+ return make_infix<true, false>{}(
+ hana::partial(static_cast<F&&>(f), static_cast<X&&>(x))
+ );
+ }
+ };
+
+ // x ^ (infix(f)^y)
+ template <>
+ struct bind_infix<Object, Infix<false, true>> {
+ template <typename X, typename F>
+ static constexpr decltype(auto) apply(X&& x, F&& f) {
+ return static_cast<F&&>(f)(static_cast<X&&>(x));
+ }
+ };
+
+ template <typename T>
+ using strip = typename std::remove_cv<
+ typename std::remove_reference<T>::type
+ >::type;
+
+ template <typename X, typename Y>
+ constexpr decltype(auto) operator^(X&& x, Y&& y) {
+ return bind_infix<
+ typename dispatch<strip<X>>::type,
+ typename dispatch<strip<Y>>::type
+ >::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
+ }
+ } // end namespace infix_detail
+
+ constexpr infix_detail::make_infix<false, false> infix{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_INFIX_HPP
diff --git a/boost/hana/functional/iterate.hpp b/boost/hana/functional/iterate.hpp
new file mode 100644
index 0000000000..b2ec27f5ec
--- /dev/null
+++ b/boost/hana/functional/iterate.hpp
@@ -0,0 +1,201 @@
+/*!
+@file
+Defines `boost::hana::iterate`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUNCTIONAL_ITERATE_HPP
+#define BOOST_HANA_FUNCTIONAL_ITERATE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/functional/partial.hpp>
+
+#include <cstddef>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Applies another function `n` times to its argument.
+ //!
+ //! Given a function `f` and an argument `x`, `iterate<n>(f, x)` returns
+ //! the result of applying `f` `n` times to its argument. In other words,
+ //! @code
+ //! iterate<n>(f, x) == f(f( ... f(x)))
+ //! ^^^^^^^^^^ n times total
+ //! @endcode
+ //!
+ //! If `n == 0`, `iterate<n>(f, x)` returns the `x` argument unchanged
+ //! and `f` is never applied. It is important to note that the function
+ //! passed to `iterate<n>` must be a unary function. Indeed, since `f`
+ //! will be called with the result of the previous `f` application, it
+ //! may only take a single argument.
+ //!
+ //! In addition to what's documented above, `iterate` can also be
+ //! partially applied to the function argument out-of-the-box. In
+ //! other words, `iterate<n>(f)` is a function object applying `f`
+ //! `n` times to the argument it is called with, which means that
+ //! @code
+ //! iterate<n>(f)(x) == iterate<n>(f, x)
+ //! @endcode
+ //!
+ //! This is provided for convenience, and it turns out to be especially
+ //! useful in conjunction with higher-order algorithms.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a function \f$ f : T \to T \f$ and `x` and argument of data
+ //! type `T`, the signature is
+ //! \f$
+ //! \mathtt{iterate_n} : (T \to T) \times T \to T
+ //! \f$
+ //!
+ //! @tparam n
+ //! An unsigned integer representing the number of times that `f`
+ //! should be applied to its argument.
+ //!
+ //! @param f
+ //! A function to apply `n` times to its argument.
+ //!
+ //! @param x
+ //! The initial value to call `f` with.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/functional/iterate.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <std::size_t n>
+ constexpr auto iterate = [](auto&& f) {
+ return [perfect-capture](auto&& x) -> decltype(auto) {
+ return f(f( ... f(forwarded(x))));
+ };
+ };
+#else
+ template <std::size_t n, typename = when<true>>
+ struct iterate_t;
+
+ template <>
+ struct iterate_t<0> {
+ template <typename F, typename X>
+ constexpr X operator()(F&&, X&& x) const
+ { return static_cast<X&&>(x); }
+ };
+
+ template <>
+ struct iterate_t<1> {
+ template <typename F, typename X>
+ constexpr decltype(auto) operator()(F&& f, X&& x) const {
+ return f(static_cast<X&&>(x));
+ }
+ };
+
+ template <>
+ struct iterate_t<2> {
+ template <typename F, typename X>
+ constexpr decltype(auto) operator()(F&& f, X&& x) const {
+ return f(f(static_cast<X&&>(x)));
+ }
+ };
+
+ template <>
+ struct iterate_t<3> {
+ template <typename F, typename X>
+ constexpr decltype(auto) operator()(F&& f, X&& x) const {
+ return f(f(f(static_cast<X&&>(x))));
+ }
+ };
+
+ template <>
+ struct iterate_t<4> {
+ template <typename F, typename X>
+ constexpr decltype(auto) operator()(F&& f, X&& x) const {
+ return f(f(f(f(static_cast<X&&>(x)))));
+ }
+ };
+
+ template <>
+ struct iterate_t<5> {
+ template <typename F, typename X>
+ constexpr decltype(auto) operator()(F&& f, X&& x) const {
+ return f(f(f(f(f(static_cast<X&&>(x))))));
+ }
+ };
+
+ template <std::size_t n>
+ struct iterate_t<n, when<(n >= 6) && (n < 12)>> {
+ template <typename F, typename X>
+ constexpr decltype(auto) operator()(F&& f, X&& x) const {
+ return iterate_t<n - 6>{}(f,
+ f(f(f(f(f(f(static_cast<X&&>(x)))))))
+ );
+ }
+ };
+
+ template <std::size_t n>
+ struct iterate_t<n, when<(n >= 12) && (n < 24)>> {
+ template <typename F, typename X>
+ constexpr decltype(auto) operator()(F&& f, X&& x) const {
+ return iterate_t<n - 12>{}(f,
+ f(f(f(f(f(f(f(f(f(f(f(f(
+ static_cast<X&&>(x)
+ ))))))))))))
+ );
+ }
+ };
+
+ template <std::size_t n>
+ struct iterate_t<n, when<(n >= 24) && (n < 48)>> {
+ template <typename F, typename X>
+ constexpr decltype(auto) operator()(F&& f, X&& x) const {
+ return iterate_t<n - 24>{}(f,
+ f(f(f(f(f(f(f(f(f(f(f(f(
+ f(f(f(f(f(f(f(f(f(f(f(f(
+ static_cast<X&&>(x)
+ ))))))))))))
+ ))))))))))))
+ );
+ }
+ };
+
+ template <std::size_t n>
+ struct iterate_t<n, when<(n >= 48)>> {
+ template <typename F, typename X>
+ constexpr decltype(auto) operator()(F&& f, X&& x) const {
+ return iterate_t<n - 48>{}(f,
+ f(f(f(f(f(f(f(f(f(f(f(f(
+ f(f(f(f(f(f(f(f(f(f(f(f(
+ f(f(f(f(f(f(f(f(f(f(f(f(
+ f(f(f(f(f(f(f(f(f(f(f(f(
+ static_cast<X&&>(x)
+ ))))))))))))
+ ))))))))))))
+ ))))))))))))
+ ))))))))))))
+ );
+ }
+ };
+
+ template <std::size_t n>
+ struct make_iterate_t {
+ template <typename F>
+ constexpr decltype(auto) operator()(F&& f) const
+ { return hana::partial(iterate_t<n>{}, static_cast<F&&>(f)); }
+
+ template <typename F, typename X>
+ constexpr decltype(auto) operator()(F&& f, X&& x) const {
+ return iterate_t<n>{}(static_cast<F&&>(f),
+ static_cast<X&&>(x));
+ }
+ };
+
+ template <std::size_t n>
+ constexpr make_iterate_t<n> iterate{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_ITERATE_HPP
diff --git a/boost/hana/functional/lockstep.hpp b/boost/hana/functional/lockstep.hpp
new file mode 100644
index 0000000000..fe4a12c7bd
--- /dev/null
+++ b/boost/hana/functional/lockstep.hpp
@@ -0,0 +1,114 @@
+/*!
+@file
+Defines `boost::hana::lockstep`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUNCTIONAL_LOCKSTEP_HPP
+#define BOOST_HANA_FUNCTIONAL_LOCKSTEP_HPP
+
+#include <boost/hana/basic_tuple.hpp>
+#include <boost/hana/config.hpp>
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Invoke a function with the result of invoking other functions on its
+ //! arguments, in lockstep.
+ //!
+ //! Specifically, `lockstep(f)(g1, ..., gN)` is a function such that
+ //! @code
+ //! lockstep(f)(g1, ..., gN)(x1, ..., xN) == f(g1(x1), ..., gN(xN))
+ //! @endcode
+ //!
+ //! Since each `g` is invoked on its corresponding argument in lockstep,
+ //! the number of arguments must match the number of `g`s.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/functional/lockstep.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto lockstep = [](auto&& f, auto&& ...g) {
+ return [perfect-capture](auto&& ...x) -> decltype(auto) {
+ return forwarded(f)(forwarded(g)(forwarded(x))...);
+ };
+ };
+#else
+ template <typename Indices, typename F, typename ...G>
+ struct lockstep_t;
+
+ template <typename F>
+ struct pre_lockstep_t;
+
+ struct make_pre_lockstep_t {
+ struct secret { };
+ template <typename F>
+ constexpr pre_lockstep_t<typename std::decay<F>::type> operator()(F&& f) const {
+ return {static_cast<F&&>(f)};
+ }
+ };
+
+ template <std::size_t ...n, typename F, typename ...G>
+ struct lockstep_t<std::index_sequence<n...>, F, G...> {
+ template <typename ...T>
+ constexpr lockstep_t(make_pre_lockstep_t::secret, T&& ...t)
+ : storage_{static_cast<T&&>(t)...}
+ { }
+
+ basic_tuple<F, G...> storage_;
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) const& {
+ return hana::get_impl<0>(storage_)(
+ hana::get_impl<n+1>(storage_)(static_cast<X&&>(x))...
+ );
+ }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) & {
+ return hana::get_impl<0>(storage_)(
+ hana::get_impl<n+1>(storage_)(static_cast<X&&>(x))...
+ );
+ }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) && {
+ return static_cast<F&&>(hana::get_impl<0>(storage_))(
+ static_cast<G&&>(hana::get_impl<n+1>(storage_))(static_cast<X&&>(x))...
+ );
+ }
+ };
+
+ template <typename F>
+ struct pre_lockstep_t {
+ F f;
+
+ template <typename ...G>
+ constexpr lockstep_t<std::make_index_sequence<sizeof...(G)>, F,
+ typename std::decay<G>::type...>
+ operator()(G&& ...g) const& {
+ return {make_pre_lockstep_t::secret{}, this->f, static_cast<G&&>(g)...};
+ }
+
+ template <typename ...G>
+ constexpr lockstep_t<std::make_index_sequence<sizeof...(G)>, F,
+ typename std::decay<G>::type...>
+ operator()(G&& ...g) && {
+ return {make_pre_lockstep_t::secret{}, static_cast<F&&>(this->f),
+ static_cast<G&&>(g)...};
+ }
+ };
+
+ constexpr make_pre_lockstep_t lockstep{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_LOCKSTEP_HPP
diff --git a/boost/hana/functional/on.hpp b/boost/hana/functional/on.hpp
new file mode 100644
index 0000000000..ff40c0db5c
--- /dev/null
+++ b/boost/hana/functional/on.hpp
@@ -0,0 +1,83 @@
+/*!
+@file
+Defines `boost::hana::on`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUNCTIONAL_ON_HPP
+#define BOOST_HANA_FUNCTIONAL_ON_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/create.hpp>
+#include <boost/hana/functional/infix.hpp>
+
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Invoke a function with the result of invoking another function on
+ //! each argument.
+ //!
+ //! Specifically, `on(f, g)` is a function such that
+ //! @code
+ //! on(f, g)(x...) == f(g(x)...)
+ //! @endcode
+ //!
+ //! For convenience, `on` also supports infix application as provided
+ //! by `infix`.
+ //!
+ //!
+ //! @note
+ //! `on` is associative, i.e. `on(f, on(g, h))` is equivalent to
+ //! `on(on(f, g), h)`.
+ //!
+ //! @internal
+ //! ### Proof of associativity
+ //!
+ //! @code
+ //! on(f, on(g, h))(xs...) == f(on(g, h)(xs)...)
+ //! == f(g(h(xs))...)
+ //!
+ //! on(on(f, g), h)(xs...) == on(f, g)(h(xs)...)
+ //! == f(g(h(xs))...)
+ //! @endcode
+ //! @endinternal
+ //!
+ //!
+ //! ### Example
+ //! @include example/functional/on.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto on = infix([](auto&& f, auto&& g) {
+ return [perfect-capture](auto&& ...x) -> decltype(auto) {
+ return forwarded(f)(g(forwarded(x))...);
+ };
+ });
+#else
+ template <typename F, typename G>
+ struct on_t {
+ F f; G g;
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) const& {
+ return f(g(static_cast<X&&>(x))...);
+ }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) & {
+ return f(g(static_cast<X&&>(x))...);
+ }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) && {
+ return std::move(f)(g(static_cast<X&&>(x))...);
+ }
+ };
+
+ constexpr auto on = infix(detail::create<on_t>{});
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_ON_HPP
diff --git a/boost/hana/functional/overload.hpp b/boost/hana/functional/overload.hpp
new file mode 100644
index 0000000000..b16c87c915
--- /dev/null
+++ b/boost/hana/functional/overload.hpp
@@ -0,0 +1,88 @@
+/*!
+@file
+Defines `boost::hana::overload`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUNCTIONAL_OVERLOAD_HPP
+#define BOOST_HANA_FUNCTIONAL_OVERLOAD_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/decay.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Pick one of several functions to call based on overload resolution.
+ //!
+ //! Specifically, `overload(f1, f2, ..., fn)` is a function object such
+ //! that
+ //! @code
+ //! overload(f1, f2, ..., fn)(x...) == fk(x...)
+ //! @endcode
+ //!
+ //! where `fk` is the function of `f1, ..., fn` that would be called if
+ //! overload resolution was performed amongst that set of functions only.
+ //! If more than one function `fk` would be picked by overload resolution,
+ //! then the call is ambiguous.
+ //!
+ //! ### Example
+ //! @include example/functional/overload.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto overload = [](auto&& f1, auto&& f2, ..., auto&& fn) {
+ return [perfect-capture](auto&& ...x) -> decltype(auto) {
+ return forwarded(fk)(forwarded(x)...);
+ };
+ };
+#else
+ template <typename F, typename ...G>
+ struct overload_t
+ : overload_t<F>::type
+ , overload_t<G...>::type
+ {
+ using type = overload_t;
+ using overload_t<F>::type::operator();
+ using overload_t<G...>::type::operator();
+
+ template <typename F_, typename ...G_>
+ constexpr explicit overload_t(F_&& f, G_&& ...g)
+ : overload_t<F>::type(static_cast<F_&&>(f))
+ , overload_t<G...>::type(static_cast<G_&&>(g)...)
+ { }
+ };
+
+ template <typename F>
+ struct overload_t<F> { using type = F; };
+
+ template <typename R, typename ...Args>
+ struct overload_t<R(*)(Args...)> {
+ using type = overload_t;
+ R (*fptr_)(Args...);
+
+ explicit constexpr overload_t(R (*fp)(Args...))
+ : fptr_(fp)
+ { }
+
+ constexpr R operator()(Args ...args) const
+ { return fptr_(static_cast<Args&&>(args)...); }
+ };
+
+ struct make_overload_t {
+ template <typename ...F,
+ typename Overload = typename overload_t<
+ typename detail::decay<F>::type...
+ >::type
+ >
+ constexpr Overload operator()(F&& ...f) const {
+ return Overload(static_cast<F&&>(f)...);
+ }
+ };
+
+ constexpr make_overload_t overload{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_OVERLOAD_HPP
diff --git a/boost/hana/functional/overload_linearly.hpp b/boost/hana/functional/overload_linearly.hpp
new file mode 100644
index 0000000000..3695bf2be2
--- /dev/null
+++ b/boost/hana/functional/overload_linearly.hpp
@@ -0,0 +1,105 @@
+/*!
+@file
+Defines `boost::hana::overload_linearly`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUNCTIONAL_OVERLOAD_LINEARLY_HPP
+#define BOOST_HANA_FUNCTIONAL_OVERLOAD_LINEARLY_HPP
+
+#include <boost/hana/config.hpp>
+
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Call the first function that produces a valid call expression.
+ //!
+ //! Given functions `f1, ..., fn`, `overload_linearly(f1, ..., fn)` is
+ //! a new function that calls the first `fk` producing a valid call
+ //! expression with the given arguments. Specifically,
+ //! @code
+ //! overload_linearly(f1, ..., fn)(args...) == fk(args...)
+ //! @endcode
+ //!
+ //! where `fk` is the _first_ function such that `fk(args...)` is a valid
+ //! expression.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/functional/overload_linearly.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto overload_linearly = [](auto&& f1, auto&& f2, ..., auto&& fn) {
+ return [perfect-capture](auto&& ...x) -> decltype(auto) {
+ return forwarded(fk)(forwarded(x)...);
+ };
+ };
+#else
+ template <typename F, typename G>
+ struct overload_linearly_t {
+ F f;
+ G g;
+
+ private:
+ template <typename ...Args, typename =
+ decltype(std::declval<F const&>()(std::declval<Args>()...))>
+ constexpr F const& which(int) const& { return f; }
+
+ template <typename ...Args, typename =
+ decltype(std::declval<F&>()(std::declval<Args>()...))>
+ constexpr F& which(int) & { return f; }
+
+ template <typename ...Args, typename =
+ decltype(std::declval<F&&>()(std::declval<Args>()...))>
+ constexpr F which(int) && { return static_cast<F&&>(f); }
+
+ template <typename ...Args>
+ constexpr G const& which(long) const& { return g; }
+
+ template <typename ...Args>
+ constexpr G& which(long) & { return g; }
+
+ template <typename ...Args>
+ constexpr G which(long) && { return static_cast<G&&>(g); }
+
+ public:
+ template <typename ...Args>
+ constexpr decltype(auto) operator()(Args&& ...args) const&
+ { return which<Args...>(int{})(static_cast<Args&&>(args)...); }
+
+ template <typename ...Args>
+ constexpr decltype(auto) operator()(Args&& ...args) &
+ { return which<Args...>(int{})(static_cast<Args&&>(args)...); }
+
+ template <typename ...Args>
+ constexpr decltype(auto) operator()(Args&& ...args) &&
+ { return which<Args...>(int{})(static_cast<Args&&>(args)...); }
+ };
+
+ struct make_overload_linearly_t {
+ template <typename F, typename G>
+ constexpr overload_linearly_t<
+ typename std::decay<F>::type,
+ typename std::decay<G>::type
+ > operator()(F&& f, G&& g) const {
+ return {static_cast<F&&>(f), static_cast<G&&>(g)};
+ }
+
+ template <typename F, typename G, typename ...H>
+ constexpr decltype(auto) operator()(F&& f, G&& g, H&& ...h) const {
+ return (*this)(static_cast<F&&>(f),
+ (*this)(static_cast<G&&>(g), static_cast<H&&>(h)...));
+ }
+ };
+
+ constexpr make_overload_linearly_t overload_linearly{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_OVERLOAD_LINEARLY_HPP
diff --git a/boost/hana/functional/partial.hpp b/boost/hana/functional/partial.hpp
new file mode 100644
index 0000000000..c84c365bf9
--- /dev/null
+++ b/boost/hana/functional/partial.hpp
@@ -0,0 +1,107 @@
+/*!
+@file
+Defines `boost::hana::partial`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUNCTIONAL_PARTIAL_HPP
+#define BOOST_HANA_FUNCTIONAL_PARTIAL_HPP
+
+#include <boost/hana/basic_tuple.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/decay.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Partially apply a function to some arguments.
+ //!
+ //! Given a function `f` and some arguments, `partial` returns a new
+ //! function corresponding to the partially applied function `f`. This
+ //! allows providing some arguments to a function and letting the rest
+ //! of the arguments be provided later. Specifically, `partial(f, x...)`
+ //! is a function such that
+ //! @code
+ //! partial(f, x...)(y...) == f(x..., y...)
+ //! @endcode
+ //!
+ //! @note
+ //! The arity of `f` must match the total number of arguments passed to
+ //! it, i.e. `sizeof...(x) + sizeof...(y)`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/functional/partial.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto partial = [](auto&& f, auto&& ...x) {
+ return [perfect-capture](auto&& ...y) -> decltype(auto) {
+ return forwarded(f)(forwarded(x)..., forwarded(y)...);
+ };
+ };
+#else
+ template <typename Indices, typename F, typename ...X>
+ struct partial_t;
+
+ struct make_partial_t {
+ struct secret { };
+ template <typename F, typename ...X>
+ constexpr partial_t<
+ std::make_index_sequence<sizeof...(X)>,
+ typename detail::decay<F>::type,
+ typename detail::decay<X>::type...
+ >
+ operator()(F&& f, X&& ...x) const {
+ return {secret{}, static_cast<F&&>(f), static_cast<X&&>(x)...};
+ }
+ };
+
+ template <std::size_t ...n, typename F, typename ...X>
+ struct partial_t<std::index_sequence<n...>, F, X...> {
+ // Not needed in theory; workaround for a bug in libstdc++'s tuple,
+ // which instantiates the default constructor of elements too eagerly.
+ partial_t() = default;
+
+ template <typename ...T>
+ constexpr partial_t(make_partial_t::secret, T&& ...t)
+ : storage_{static_cast<T&&>(t)...}
+ { }
+
+ basic_tuple<F, X...> storage_;
+
+ template <typename ...Y>
+ constexpr decltype(auto) operator()(Y&& ...y) const& {
+ return hana::get_impl<0>(storage_)(
+ hana::get_impl<n+1>(storage_)...,
+ static_cast<Y&&>(y)...
+ );
+ }
+
+ template <typename ...Y>
+ constexpr decltype(auto) operator()(Y&& ...y) & {
+ return hana::get_impl<0>(storage_)(
+ hana::get_impl<n+1>(storage_)...,
+ static_cast<Y&&>(y)...
+ );
+ }
+
+ template <typename ...Y>
+ constexpr decltype(auto) operator()(Y&& ...y) && {
+ return static_cast<F&&>(hana::get_impl<0>(storage_))(
+ static_cast<X&&>(hana::get_impl<n+1>(storage_))...,
+ static_cast<Y&&>(y)...
+ );
+ }
+ };
+
+ constexpr make_partial_t partial{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_PARTIAL_HPP
diff --git a/boost/hana/functional/placeholder.hpp b/boost/hana/functional/placeholder.hpp
new file mode 100644
index 0000000000..71a25389cd
--- /dev/null
+++ b/boost/hana/functional/placeholder.hpp
@@ -0,0 +1,263 @@
+/*!
+@file
+Defines `boost::hana::_`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUNCTIONAL_PLACEHOLDER_HPP
+#define BOOST_HANA_FUNCTIONAL_PLACEHOLDER_HPP
+
+#include <boost/hana/basic_tuple.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/create.hpp>
+#include <boost/hana/detail/decay.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Create simple functions representing C++ operators inline.
+ //!
+ //! Specifically, `_` is an object used as a placeholder to build
+ //! function objects representing calls to C++ operators. It works
+ //! by overloading the operators between `_` and any object so that
+ //! they return a function object which actually calls the corresponding
+ //! operator on its argument(s). Hence, for any supported operator `@`:
+ //! @code
+ //! (_ @ _)(x, y) == x @ y
+ //! @endcode
+ //!
+ //! Operators may also be partially applied to one argument inline:
+ //! @code
+ //! (x @ _)(y) == x @ y
+ //! (_ @ y)(x) == x @ y
+ //! @endcode
+ //!
+ //! When invoked with more arguments than required, functions created with
+ //! `_` will discard the superfluous instead of triggering an error:
+ //! @code
+ //! (_ @ _)(x, y, z...) == x @ y
+ //! @endcode
+ //!
+ //! This makes functions created with `_` easier to use in higher-order
+ //! algorithms, which sometime provide more information than necessary
+ //! to their callbacks.
+ //!
+ //! ### Supported operators
+ //! - Arithmetic: binary `+`, binary `-`, `/`, `*`, `%`, unary `+`, unary `-`
+ //! - Bitwise: `~`, `&`, `|`, `^`, `<<`, `>>`
+ //! - Comparison: `==`, `!=`, `<`, `<=`, `>`, `>=`
+ //! - %Logical: `||`, `&&`, `!`
+ //! - Member access: `*` (dereference), `[]` (array subscript)
+ //! - Other: `()` (function call)
+ //!
+ //! More complex functionality like the ability to compose placeholders
+ //! into larger function objects inline are not supported. This is on
+ //! purpose; you should either use C++14 generic lambdas or a library
+ //! like [Boost.Phoenix][] if you need bigger guns. The goal here is
+ //! to save you a couple of characters in simple situations.
+ //!
+ //! ### Example
+ //! @include example/functional/placeholder.cpp
+ //!
+ //! [Boost.Phoenix]: http://www.boost.org/doc/libs/release/libs/phoenix/doc/html/index.html
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr unspecified _{};
+#else
+ namespace placeholder_detail {
+ template <typename I>
+ struct subscript {
+ I i;
+
+ template <typename Xs, typename ...Z>
+ constexpr auto operator()(Xs&& xs, Z const& ...) const&
+ -> decltype(static_cast<Xs&&>(xs)[i])
+ { return static_cast<Xs&&>(xs)[i]; }
+
+ template <typename Xs, typename ...Z>
+ constexpr auto operator()(Xs&& xs, Z const& ...) &
+ -> decltype(static_cast<Xs&&>(xs)[i])
+ { return static_cast<Xs&&>(xs)[i]; }
+
+ template <typename Xs, typename ...Z>
+ constexpr auto operator()(Xs&& xs, Z const& ...) &&
+ -> decltype(static_cast<Xs&&>(xs)[std::declval<I>()])
+ { return static_cast<Xs&&>(xs)[std::move(i)]; }
+ };
+
+ template <typename F, typename Xs, std::size_t ...i>
+ constexpr decltype(auto) invoke_impl(F&& f, Xs&& xs, std::index_sequence<i...>) {
+ return static_cast<F&&>(f)(hana::get_impl<i>(static_cast<Xs&&>(xs).storage_)...);
+ }
+
+ template <typename ...X>
+ struct invoke;
+
+ struct placeholder {
+ struct secret { };
+
+ template <typename X>
+ constexpr decltype(auto) operator[](X&& x) const
+ { return detail::create<subscript>{}(static_cast<X&&>(x)); }
+
+ template <typename ...X>
+ constexpr invoke<typename detail::decay<X>::type...>
+ operator()(X&& ...x) const {
+ return {secret{}, static_cast<X&&>(x)...};
+ }
+ };
+
+ template <typename ...X>
+ struct invoke {
+ template <typename ...Y>
+ constexpr invoke(placeholder::secret, Y&& ...y)
+ : storage_{static_cast<Y&&>(y)...}
+ { }
+
+ basic_tuple<X...> storage_;
+
+ template <typename F, typename ...Z>
+ constexpr auto operator()(F&& f, Z const& ...) const& -> decltype(
+ static_cast<F&&>(f)(std::declval<X const&>()...)
+ ) {
+ return invoke_impl(static_cast<F&&>(f), *this,
+ std::make_index_sequence<sizeof...(X)>{});
+ }
+
+ template <typename F, typename ...Z>
+ constexpr auto operator()(F&& f, Z const& ...) & -> decltype(
+ static_cast<F&&>(f)(std::declval<X&>()...)
+ ) {
+ return invoke_impl(static_cast<F&&>(f), *this,
+ std::make_index_sequence<sizeof...(X)>{});
+ }
+
+ template <typename F, typename ...Z>
+ constexpr auto operator()(F&& f, Z const& ...) && -> decltype(
+ static_cast<F&&>(f)(std::declval<X&&>()...)
+ ) {
+ return invoke_impl(static_cast<F&&>(f), static_cast<invoke&&>(*this),
+ std::make_index_sequence<sizeof...(X)>{});
+ }
+ };
+
+#define BOOST_HANA_PLACEHOLDER_BINARY_OP(op, op_name) \
+ template <typename X> \
+ struct op_name ## _left { \
+ X x; \
+ \
+ template <typename Y, typename ...Z> \
+ constexpr auto operator()(Y&& y, Z const& ...) const& -> decltype( \
+ std::declval<X const&>() op static_cast<Y&&>(y)) \
+ { return x op static_cast<Y&&>(y); } \
+ \
+ template <typename Y, typename ...Z> \
+ constexpr auto operator()(Y&& y, Z const& ...) & -> decltype( \
+ std::declval<X&>() op static_cast<Y&&>(y)) \
+ { return x op static_cast<Y&&>(y); } \
+ \
+ template <typename Y, typename ...Z> \
+ constexpr auto operator()(Y&& y, Z const& ...) && -> decltype( \
+ std::declval<X>() op static_cast<Y&&>(y)) \
+ { return std::move(x) op static_cast<Y&&>(y); } \
+ }; \
+ \
+ template <typename Y> \
+ struct op_name ## _right { \
+ Y y; \
+ \
+ template <typename X, typename ...Z> \
+ constexpr auto operator()(X&& x, Z const& ...) const& -> decltype( \
+ static_cast<X&&>(x) op std::declval<Y const&>()) \
+ { return static_cast<X&&>(x) op y; } \
+ \
+ template <typename X, typename ...Z> \
+ constexpr auto operator()(X&& x, Z const& ...) & -> decltype( \
+ static_cast<X&&>(x) op std::declval<Y&>()) \
+ { return static_cast<X&&>(x) op y; } \
+ \
+ template <typename X, typename ...Z> \
+ constexpr auto operator()(X&& x, Z const& ...) && -> decltype( \
+ static_cast<X&&>(x) op std::declval<Y>()) \
+ { return static_cast<X&&>(x) op std::move(y); } \
+ }; \
+ \
+ struct op_name { \
+ template <typename X, typename Y, typename ...Z> \
+ constexpr auto operator()(X&& x, Y&& y, Z const& ...) const -> decltype(\
+ static_cast<X&&>(x) op static_cast<Y&&>(y)) \
+ { return static_cast<X&&>(x) op static_cast<Y&&>(y); } \
+ }; \
+ \
+ template <typename X> \
+ constexpr decltype(auto) operator op (X&& x, placeholder) \
+ { return detail::create<op_name ## _left>{}(static_cast<X&&>(x)); } \
+ \
+ template <typename Y> \
+ constexpr decltype(auto) operator op (placeholder, Y&& y) \
+ { return detail::create<op_name ## _right>{}(static_cast<Y&&>(y)); } \
+ \
+ inline constexpr decltype(auto) operator op (placeholder, placeholder) \
+ { return op_name{}; } \
+/**/
+
+#define BOOST_HANA_PLACEHOLDER_UNARY_OP(op, op_name) \
+ struct op_name { \
+ template <typename X, typename ...Z> \
+ constexpr auto operator()(X&& x, Z const& ...) const \
+ -> decltype(op static_cast<X&&>(x)) \
+ { return op static_cast<X&&>(x); } \
+ }; \
+ \
+ inline constexpr decltype(auto) operator op (placeholder) \
+ { return op_name{}; } \
+/**/
+ // Arithmetic
+ BOOST_HANA_PLACEHOLDER_UNARY_OP(+, unary_plus)
+ BOOST_HANA_PLACEHOLDER_UNARY_OP(-, unary_minus)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(+, plus)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(-, minus)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(*, times)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(/, divide)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(%, modulo)
+
+ // Bitwise
+ BOOST_HANA_PLACEHOLDER_UNARY_OP(~, bitwise_not)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(&, bitwise_and)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(|, bitwise_or)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(^, bitwise_xor)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(<<, left_shift)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(>>, right_shift)
+
+ // Comparison
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(==, equal)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(!=, not_equal)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(<, less)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(<=, less_equal)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(>, greater)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(>=, greater_equal)
+
+ // Logical
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(||, logical_or)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(&&, logical_and)
+ BOOST_HANA_PLACEHOLDER_UNARY_OP(!, logical_not)
+
+ // Member access (array subscript is a member function)
+ BOOST_HANA_PLACEHOLDER_UNARY_OP(*, dereference)
+
+ // Other (function call is a member function)
+
+#undef BOOST_HANA_PREFIX_PLACEHOLDER_OP
+#undef BOOST_HANA_BINARY_PLACEHOLDER_OP
+ } // end namespace placeholder_detail
+
+ constexpr placeholder_detail::placeholder _{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_PLACEHOLDER_HPP
diff --git a/boost/hana/functional/reverse_partial.hpp b/boost/hana/functional/reverse_partial.hpp
new file mode 100644
index 0000000000..9a2f63ff23
--- /dev/null
+++ b/boost/hana/functional/reverse_partial.hpp
@@ -0,0 +1,101 @@
+/*!
+@file
+Defines `boost::hana::reverse_partial`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUNCTIONAL_REVERSE_PARTIAL_HPP
+#define BOOST_HANA_FUNCTIONAL_REVERSE_PARTIAL_HPP
+
+#include <boost/hana/basic_tuple.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/decay.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Partially apply a function to some arguments.
+ //!
+ //! Given a function `f` and some arguments, `reverse_partial` returns a
+ //! new function corresponding to `f` whose last arguments are partially
+ //! applied. Specifically, `reverse_partial(f, x...)` is a function such
+ //! that
+ //! @code
+ //! reverse_partial(f, x...)(y...) == f(y..., x...)
+ //! @endcode
+ //!
+ //! @note
+ //! The arity of `f` must match the total number of arguments passed to
+ //! it, i.e. `sizeof...(x) + sizeof...(y)`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/functional/reverse_partial.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto reverse_partial = [](auto&& f, auto&& ...x) {
+ return [perfect-capture](auto&& ...y) -> decltype(auto) {
+ return forwarded(f)(forwarded(y)..., forwarded(x)...);
+ };
+ };
+#else
+ template <typename Indices, typename F, typename ...X>
+ struct reverse_partial_t;
+
+ struct make_reverse_partial_t {
+ struct secret { };
+ template <typename F, typename ...X>
+ constexpr reverse_partial_t<
+ std::make_index_sequence<sizeof...(X)>,
+ typename detail::decay<F>::type,
+ typename detail::decay<X>::type...
+ > operator()(F&& f, X&& ...x) const {
+ return {secret{}, static_cast<F&&>(f), static_cast<X&&>(x)...};
+ }
+ };
+
+ template <std::size_t ...n, typename F, typename ...X>
+ struct reverse_partial_t<std::index_sequence<n...>, F, X...> {
+ template <typename ...T>
+ constexpr reverse_partial_t(make_reverse_partial_t::secret, T&& ...t)
+ : storage_{static_cast<T&&>(t)...}
+ { }
+
+ basic_tuple<F, X...> storage_;
+
+ template <typename ...Y>
+ constexpr decltype(auto) operator()(Y&& ...y) const& {
+ return hana::get_impl<0>(storage_)(
+ static_cast<Y&&>(y)...,
+ hana::get_impl<n+1>(storage_)...
+ );
+ }
+
+ template <typename ...Y>
+ constexpr decltype(auto) operator()(Y&& ...y) & {
+ return hana::get_impl<0>(storage_)(
+ static_cast<Y&&>(y)...,
+ hana::get_impl<n+1>(storage_)...
+ );
+ }
+
+ template <typename ...Y>
+ constexpr decltype(auto) operator()(Y&& ...y) && {
+ return static_cast<F&&>(hana::get_impl<0>(storage_))(
+ static_cast<Y&&>(y)...,
+ static_cast<X&&>(hana::get_impl<n+1>(storage_))...
+ );
+ }
+ };
+
+ constexpr make_reverse_partial_t reverse_partial{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_REVERSE_PARTIAL_HPP
diff --git a/boost/hana/fuse.hpp b/boost/hana/fuse.hpp
new file mode 100644
index 0000000000..0b8829cb30
--- /dev/null
+++ b/boost/hana/fuse.hpp
@@ -0,0 +1,48 @@
+/*!
+@file
+Defines `boost::hana::fuse`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FUSE_HPP
+#define BOOST_HANA_FUSE_HPP
+
+#include <boost/hana/fwd/fuse.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/unpack.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace detail {
+ template <typename F>
+ struct fused {
+ F f;
+ template <typename Xs>
+ constexpr decltype(auto) operator()(Xs&& xs) const&
+ { return hana::unpack(static_cast<Xs&&>(xs), f); }
+
+ template <typename Xs>
+ constexpr decltype(auto) operator()(Xs&& xs) &
+ { return hana::unpack(static_cast<Xs&&>(xs), f); }
+
+ template <typename Xs>
+ constexpr decltype(auto) operator()(Xs&& xs) &&
+ { return hana::unpack(static_cast<Xs&&>(xs), static_cast<F&&>(f)); }
+ };
+ }
+
+ //! @cond
+ template <typename F>
+ constexpr auto fuse_t::operator()(F&& f) const {
+ return detail::fused<typename std::decay<F>::type>{static_cast<F&&>(f)};
+ }
+ //! @endcond
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUSE_HPP
diff --git a/boost/hana/fwd/accessors.hpp b/boost/hana/fwd/accessors.hpp
new file mode 100644
index 0000000000..8ad5f1b131
--- /dev/null
+++ b/boost/hana/fwd/accessors.hpp
@@ -0,0 +1,50 @@
+/*!
+@file
+Forward declares `boost::hana::accessors`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_ACCESSORS_HPP
+#define BOOST_HANA_FWD_ACCESSORS_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns a `Sequence` of pairs representing the accessors of the
+ //! data structure.
+ //! @ingroup group-Struct
+ //!
+ //! Given a `Struct` `S`, `accessors<S>()` is a `Sequence` of `Product`s
+ //! where the first element of each pair is the "name" of a member of
+ //! the `Struct`, and the second element of each pair is a function that
+ //! can be used to access that member when given an object of the proper
+ //! data type. As described in the global documentation for `Struct`, the
+ //! accessor functions in this sequence must be move-independent.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/accessors.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename S>
+ constexpr auto accessors = []() {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct accessors_impl : accessors_impl<S, when<true>> { };
+
+ template <typename S>
+ struct accessors_t;
+
+ template <typename S>
+ constexpr accessors_t<S> accessors{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_ACCESSORS_HPP
diff --git a/boost/hana/fwd/adapt_adt.hpp b/boost/hana/fwd/adapt_adt.hpp
new file mode 100644
index 0000000000..4b8614a612
--- /dev/null
+++ b/boost/hana/fwd/adapt_adt.hpp
@@ -0,0 +1,48 @@
+/*!
+@file
+Documents the `BOOST_HANA_ADAPT_ADT` macro.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_ADAPT_ADT_HPP
+#define BOOST_HANA_FWD_ADAPT_ADT_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ // Note:
+ // The weird definition as a variable seems to exploit a glitch in Doxygen
+ // which makes the macro appear in the related objects of Struct (as we
+ // want it to).
+
+ //! Defines a model of `Struct` with the given accessors.
+ //! @ingroup group-Struct
+ //!
+ //! Using this macro at _global scope_ will define a model of the `Struct`
+ //! concept for the given type. This can be used to easily adapt existing
+ //! user-defined types in a ad-hoc manner. Unlike `BOOST_HANA_ADAPT_STRUCT`,
+ //! this macro requires specifying the way to retrieve each member by
+ //! providing a function that does the extraction.
+ //!
+ //! @note
+ //! This macro only works if the tag of the user-defined type `T` is `T`
+ //! itself. This is the case unless you specifically asked for something
+ //! different; see `tag_of`'s documentation.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/adapt_adt.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ auto BOOST_HANA_ADAPT_ADT(...) = ;
+ #define BOOST_HANA_ADAPT_ADT(Name, ...) see documentation
+#else
+ // defined in <boost/hana/adapt_adt.hpp>
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_ADAPT_ADT_HPP
diff --git a/boost/hana/fwd/adapt_struct.hpp b/boost/hana/fwd/adapt_struct.hpp
new file mode 100644
index 0000000000..691eecaf15
--- /dev/null
+++ b/boost/hana/fwd/adapt_struct.hpp
@@ -0,0 +1,48 @@
+/*!
+@file
+Documents the `BOOST_HANA_ADAPT_STRUCT` macro.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_ADAPT_STRUCT_HPP
+#define BOOST_HANA_FWD_ADAPT_STRUCT_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ // Note:
+ // The weird definition as a variable seems to exploit a glitch in Doxygen
+ // which makes the macro appear in the related objects of Struct (as we
+ // want it to).
+
+ //! Defines a model of `Struct` with the given members.
+ //! @ingroup group-Struct
+ //!
+ //! Using this macro at _global scope_ will define a model of the `Struct`
+ //! concept for the given type. This can be used to easily adapt existing
+ //! user-defined types in a ad-hoc manner. Unlike the
+ //! `BOOST_HANA_DEFINE_STRUCT` macro, this macro does not
+ //! require the types of the members to be specified.
+ //!
+ //! @note
+ //! This macro only works if the tag of the user-defined type `T` is `T`
+ //! itself. This is the case unless you specifically asked for something
+ //! different; see `tag_of`'s documentation.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/adapt_struct.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ auto BOOST_HANA_ADAPT_STRUCT(...) = ;
+ #define BOOST_HANA_ADAPT_STRUCT(Name, ...) see documentation
+#else
+ // defined in <boost/hana/adapt_struct.hpp>
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_ADAPT_STRUCT_HPP
diff --git a/boost/hana/fwd/adjust.hpp b/boost/hana/fwd/adjust.hpp
new file mode 100644
index 0000000000..c4a8783e9f
--- /dev/null
+++ b/boost/hana/fwd/adjust.hpp
@@ -0,0 +1,64 @@
+/*!
+@file
+Forward declares `boost::hana::adjust`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_ADJUST_HPP
+#define BOOST_HANA_FWD_ADJUST_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Apply a function on all the elements of a structure that compare
+ //! equal to some value.
+ //! @ingroup group-Functor
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given `F` a Functor and `U` a type that can be compared with `T`'s,
+ //! the signature is
+ //! \f$
+ //! \mathtt{adjust} : F(T) \times U \times (T \to T) \to F(T)
+ //! \f$
+ //!
+ //! @param xs
+ //! The structure to adjust with `f`.
+ //!
+ //! @param value
+ //! An object that is compared with each element `x` of the structure.
+ //! Elements of the structure that compare equal to `value` are adjusted
+ //! with the `f` function.
+ //!
+ //! @param f
+ //! A function called as `f(x)` on the element(s) of the structure that
+ //! compare equal to `value`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/adjust.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto adjust = [](auto&& xs, auto&& value, auto&& f) {
+ return tag-dispatched;
+ };
+#else
+ template <typename Xs, typename = void>
+ struct adjust_impl : adjust_impl<Xs, when<true>> { };
+
+ struct adjust_t {
+ template <typename Xs, typename Value, typename F>
+ constexpr auto operator()(Xs&& xs, Value&& value, F&& f) const;
+ };
+
+ constexpr adjust_t adjust{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_ADJUST_HPP
diff --git a/boost/hana/fwd/adjust_if.hpp b/boost/hana/fwd/adjust_if.hpp
new file mode 100644
index 0000000000..fac3cbf0e4
--- /dev/null
+++ b/boost/hana/fwd/adjust_if.hpp
@@ -0,0 +1,69 @@
+/*!
+@file
+Forward declares `boost::hana::adjust_if`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_ADJUST_IF_HPP
+#define BOOST_HANA_FWD_ADJUST_IF_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Apply a function on all the elements of a structure satisfying a predicate.
+ //! @ingroup group-Functor
+ //!
+ //! Given a Functor, a predicate `pred` and a function `f`, `adjust_if`
+ //! will _adjust_ the elements of the Functor that satisfy the predicate
+ //! with the function `f`. In other words, `adjust_if` will return a new
+ //! Functor equal to the original one, except that the elements satisfying
+ //! the predicate will be transformed with the given function. Elements
+ //! for which the predicate is not satisfied are left untouched, and they
+ //! are kept as-is in the resulting Functor.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a `Functor` `F` and a `Logical` `Bool`, the signature is
+ //! \f$
+ //! \mathtt{adjust_if} : F(T) \times (T \to Bool) \times (T \to T) \to F(T)
+ //! \f$
+ //!
+ //! @param xs
+ //! The structure to adjust with `f`.
+ //!
+ //! @param pred
+ //! A function called as `pred(x)` for each element of the Functor,
+ //! and returning whether `f` should be applied on that element.
+ //!
+ //! @param f
+ //! A function called as `f(x)` on the element(s) of the Functor that
+ //! satisfy the predicate.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/adjust_if.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto adjust_if = [](auto&& xs, auto const& pred, auto const& f) {
+ return tag-dispatched;
+ };
+#else
+ template <typename Xs, typename = void>
+ struct adjust_if_impl : adjust_if_impl<Xs, when<true>> { };
+
+ struct adjust_if_t {
+ template <typename Xs, typename Pred, typename F>
+ constexpr auto operator()(Xs&& xs, Pred const& pred, F const& f) const;
+ };
+
+ constexpr adjust_if_t adjust_if{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_ADJUST_IF_HPP
diff --git a/boost/hana/fwd/all.hpp b/boost/hana/fwd/all.hpp
new file mode 100644
index 0000000000..eb92a0c1e1
--- /dev/null
+++ b/boost/hana/fwd/all.hpp
@@ -0,0 +1,46 @@
+/*!
+@file
+Forward declares `boost::hana::all`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_ALL_HPP
+#define BOOST_HANA_FWD_ALL_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns whether all the keys of the structure are true-valued.
+ //! @ingroup group-Searchable
+ //!
+ //! The keys of the structure must be `Logical`s. If the structure is not
+ //! finite, a false-valued key must appear at a finite "index" in order
+ //! for this method to finish.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/all.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto all = [](auto&& xs) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct all_impl : all_impl<S, when<true>> { };
+
+ struct all_t {
+ template <typename Xs>
+ constexpr auto operator()(Xs&& xs) const;
+ };
+
+ constexpr all_t all{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_ALL_HPP
diff --git a/boost/hana/fwd/all_of.hpp b/boost/hana/fwd/all_of.hpp
new file mode 100644
index 0000000000..33fcbfc96d
--- /dev/null
+++ b/boost/hana/fwd/all_of.hpp
@@ -0,0 +1,54 @@
+/*!
+@file
+Forward declares `boost::hana::all_of`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_ALL_OF_HPP
+#define BOOST_HANA_FWD_ALL_OF_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns whether all the keys of the structure satisfy the `predicate`.
+ //! @ingroup group-Searchable
+ //!
+ //! If the structure is not finite, `predicate` has to return a false-
+ //! valued `Logical` after looking at a finite number of keys for this
+ //! method to finish.
+ //!
+ //!
+ //! @param xs
+ //! The structure to search.
+ //!
+ //! @param predicate
+ //! A function called as `predicate(k)`, where `k` is a key of the
+ //! structure, and returning a `Logical`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/all_of.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto all_of = [](auto&& xs, auto&& predicate) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct all_of_impl : all_of_impl<S, when<true>> { };
+
+ struct all_of_t {
+ template <typename Xs, typename Pred>
+ constexpr auto operator()(Xs&& xs, Pred&& pred) const;
+ };
+
+ constexpr all_of_t all_of{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_ALL_OF_HPP
diff --git a/boost/hana/fwd/and.hpp b/boost/hana/fwd/and.hpp
new file mode 100644
index 0000000000..df767ebd1f
--- /dev/null
+++ b/boost/hana/fwd/and.hpp
@@ -0,0 +1,53 @@
+/*!
+@file
+Forward declares `boost::hana::and_`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_AND_HPP
+#define BOOST_HANA_FWD_AND_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Return whether all the arguments are true-valued.
+ //! @ingroup group-Logical
+ //!
+ //! `and_` can be called with one argument or more. When called with
+ //! two arguments, `and_` uses tag-dispatching to find the right
+ //! implementation. Otherwise,
+ //! @code
+ //! and_(x) == x
+ //! and_(x, y, ...z) == and_(and_(x, y), z...)
+ //! @endcode
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/and.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto and_ = [](auto&& x, auto&& ...y) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename L, typename = void>
+ struct and_impl : and_impl<L, when<true>> { };
+
+ struct and_t {
+ template <typename X, typename Y>
+ constexpr decltype(auto) operator()(X&& x, Y&& y) const;
+
+ template <typename X, typename ...Y>
+ constexpr decltype(auto) operator()(X&& x, Y&& ...y) const;
+ };
+
+ constexpr and_t and_{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_AND_HPP
diff --git a/boost/hana/fwd/any.hpp b/boost/hana/fwd/any.hpp
new file mode 100644
index 0000000000..2adf3beeee
--- /dev/null
+++ b/boost/hana/fwd/any.hpp
@@ -0,0 +1,46 @@
+/*!
+@file
+Forward declares `boost::hana::any`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_ANY_HPP
+#define BOOST_HANA_FWD_ANY_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns whether any key of the structure is true-valued.
+ //! @ingroup group-Searchable
+ //!
+ //! The keys of the structure must be `Logical`s. If the structure is not
+ //! finite, a true-valued key must appear at a finite "index" in order for
+ //! this method to finish.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/any.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto any = [](auto&& xs) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct any_impl : any_impl<S, when<true>> { };
+
+ struct any_t {
+ template <typename Xs>
+ constexpr auto operator()(Xs&& xs) const;
+ };
+
+ constexpr any_t any{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_ANY_HPP
diff --git a/boost/hana/fwd/any_of.hpp b/boost/hana/fwd/any_of.hpp
new file mode 100644
index 0000000000..a8cf77596d
--- /dev/null
+++ b/boost/hana/fwd/any_of.hpp
@@ -0,0 +1,53 @@
+/*!
+@file
+Forward declares `boost::hana::any_of`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_ANY_OF_HPP
+#define BOOST_HANA_FWD_ANY_OF_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns whether any key of the structure satisfies the `predicate`.
+ //! @ingroup group-Searchable
+ //!
+ //! If the structure is not finite, `predicate` has to be satisfied
+ //! after looking at a finite number of keys for this method to finish.
+ //!
+ //!
+ //! @param xs
+ //! The structure to search.
+ //!
+ //! @param predicate
+ //! A function called as `predicate(k)`, where `k` is a key of the
+ //! structure, and returning a `Logical`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/any_of.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto any_of = [](auto&& xs, auto&& predicate) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct any_of_impl : any_of_impl<S, when<true>> { };
+
+ struct any_of_t {
+ template <typename Xs, typename Pred>
+ constexpr auto operator()(Xs&& xs, Pred&& pred) const;
+ };
+
+ constexpr any_of_t any_of{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_ANY_OF_HPP
diff --git a/boost/hana/fwd/ap.hpp b/boost/hana/fwd/ap.hpp
new file mode 100644
index 0000000000..4d71abadd1
--- /dev/null
+++ b/boost/hana/fwd/ap.hpp
@@ -0,0 +1,82 @@
+/*!
+@file
+Forward declares `boost::hana::ap`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_AP_HPP
+#define BOOST_HANA_FWD_AP_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Lifted application.
+ //! @ingroup group-Applicative
+ //!
+ //! Specifically, `ap` applies a structure containing functions to a
+ //! structure containing values, and returns a new structure containing
+ //! values. The exact way in which the functions are applied to the values
+ //! depends on the `Applicative`.
+ //!
+ //! `ap` can be called with two arguments or more; the functions in the `f`
+ //! structure are curried and then applied to the values in each `x...`
+ //! structure using the binary form of `ap`. Note that this requires the
+ //! 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
+ //! @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.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given an Applicative `A`, the signature is
+ //! @f$ \mathtt{ap} : A(T_1 \times \cdots \times T_n \to U)
+ //! \times A(T_1) \times \cdots \times A(T_n)
+ //! \to A(U) @f$.
+ //!
+ //! @param f
+ //! A structure containing function(s).
+ //!
+ //! @param x...
+ //! Structure(s) containing value(s) and on which `f` is applied. The
+ //! number of structures must match the arity of the functions in the
+ //! `f` structure.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/ap.cpp
+ //!
+ //! @todo
+ //! Consider giving access to all the arguments to the tag-dispatched
+ //! implementation for performance purposes.
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto ap = [](auto&& f, auto&& ...x) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename A, typename = void>
+ struct ap_impl : ap_impl<A, when<true>> { };
+
+ struct ap_t {
+ template <typename F, typename X>
+ constexpr decltype(auto) operator()(F&& f, X&& x) const;
+
+ template <typename F, typename ...Xs>
+ constexpr decltype(auto) operator()(F&& f, Xs&& ...xs) const;
+ };
+
+ constexpr ap_t ap{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_AP_HPP
diff --git a/boost/hana/fwd/append.hpp b/boost/hana/fwd/append.hpp
new file mode 100644
index 0000000000..fd9efc3d53
--- /dev/null
+++ b/boost/hana/fwd/append.hpp
@@ -0,0 +1,68 @@
+/*!
+@file
+Forward declares `boost::hana::append`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_APPEND_HPP
+#define BOOST_HANA_FWD_APPEND_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Append an element to a monadic structure.
+ //! @ingroup group-MonadPlus
+ //!
+ //! Given an element `x` and a monadic structure `xs`, `append` returns a
+ //! new monadic structure which is the result of lifting `x` into the
+ //! monadic structure and then combining that (to the right) with `xs`.
+ //! In other words,
+ //! @code
+ //! append(xs, x) == concat(xs, lift<Xs>(x))
+ //! @endcode
+ //! where `Xs` is the tag of `xs`. For sequences, this has the intuitive
+ //! behavior of simply appending an element to the end of the sequence,
+ //! hence the name.
+ //!
+ //! > #### Rationale for not calling this `push_back`
+ //! > See the rationale for using `prepend` instead of `push_front`.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a MonadPlus `M`, the signature is
+ //! @f$ \mathtt{append} : M(T) \times T \to M(T) @f$.
+ //!
+ //! @param xs
+ //! A monadic structure that will be combined to the left of the element.
+ //!
+ //! @param x
+ //! An element to combine to the right of the monadic structure.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/append.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto append = [](auto&& xs, auto&& x) {
+ return tag-dispatched;
+ };
+#else
+ template <typename M, typename = void>
+ struct append_impl : append_impl<M, when<true>> { };
+
+ struct append_t {
+ template <typename Xs, typename X>
+ constexpr auto operator()(Xs&& xs, X&& x) const;
+ };
+
+ constexpr append_t append{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_APPEND_HPP
diff --git a/boost/hana/fwd/at.hpp b/boost/hana/fwd/at.hpp
new file mode 100644
index 0000000000..d069143c4a
--- /dev/null
+++ b/boost/hana/fwd/at.hpp
@@ -0,0 +1,97 @@
+/*!
+@file
+Forward declares `boost::hana::at` and `boost::hana::at_c`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_AT_HPP
+#define BOOST_HANA_FWD_AT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+#include <cstddef>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns the `n`th element of an iterable.
+ //! @ingroup group-Iterable
+ //!
+ //! Given an `Iterable` and an `IntegralConstant` index, `at` returns the
+ //! element located at the index in the linearization of the iterable.
+ //! Specifically, given an iterable `xs` with a linearization of
+ //! `[x1, ..., xN]`, `at(xs, k)` is equivalent to `xk`.
+ //!
+ //! If the `Iterable` actually stores the elements it contains, `at` is
+ //! required to return a lvalue reference, a lvalue reference to const
+ //! or a rvalue reference to the matching element, where the type of
+ //! reference must match that of the iterable passed to `at`. If the
+ //! `Iterable` does not store the elements it contains (i.e. it generates
+ //! them on demand), this requirement is dropped.
+ //!
+ //!
+ //! @param xs
+ //! The iterable in which an element is retrieved. The iterable must
+ //! contain at least `n + 1` elements.
+ //!
+ //! @param n
+ //! A non-negative `IntegralConstant` representing the 0-based index of
+ //! the element to return. It is an error to call `at` with an index that
+ //! out of bounds of the iterable.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/at.cpp
+ //!
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.at.compile.json">
+ //! </div>
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto at = [](auto&& xs, auto const& n) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename It, typename = void>
+ struct at_impl : at_impl<It, when<true>> { };
+
+ struct at_t {
+ template <typename Xs, typename N>
+ constexpr decltype(auto) operator()(Xs&& xs, N const& n) const;
+ };
+
+ constexpr at_t at{};
+#endif
+
+ //! Equivalent to `at`; provided for convenience.
+ //! @ingroup group-Iterable
+ //!
+ //!
+ //! @note
+ //! `hana::at_c<n>` is an overloaded function, not a function object.
+ //! Hence, it can't be passed to higher-order algorithms. This is done
+ //! for compile-time performance reasons.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/at_c.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <std::size_t n>
+ constexpr auto at_c = [](auto&& xs) {
+ return hana::at(forwarded(xs), hana::size_c<n>);
+ };
+#else
+ template <std::size_t n, typename Xs>
+ constexpr decltype(auto) at_c(Xs&& xs);
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_AT_HPP
diff --git a/boost/hana/fwd/at_key.hpp b/boost/hana/fwd/at_key.hpp
new file mode 100644
index 0000000000..a3045bba0e
--- /dev/null
+++ b/boost/hana/fwd/at_key.hpp
@@ -0,0 +1,75 @@
+/*!
+@file
+Forward declares `boost::hana::at_key`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_AT_KEY_HPP
+#define BOOST_HANA_FWD_AT_KEY_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns the value associated to the given key in a structure, or fail.
+ //! @ingroup group-Searchable
+ //!
+ //! Given a `key` and a `Searchable` structure, `at_key` returns the first
+ //! value whose key is equal to the given `key`, and fails at compile-time
+ //! if no such key exists. This requires the `key` to be compile-time
+ //! `Comparable`, exactly like for `find`. `at_key` satisfies the following:
+ //! @code
+ //! at_key(xs, key) == find(xs, key).value()
+ //! @endcode
+ //!
+ //! If the `Searchable` actually stores the elements it contains, `at_key`
+ //! is required to return a lvalue reference, a lvalue reference to const
+ //! or a rvalue reference to the found value, where the type of reference
+ //! must match that of the structure passed to `at_key`. If the `Searchable`
+ //! does not store the elements it contains (i.e. it generates them on
+ //! demand), this requirement is dropped.
+ //!
+ //!
+ //! @param xs
+ //! The structure to be searched.
+ //!
+ //! @param key
+ //! A key to be searched for in the structure. The key has to be
+ //! `Comparable` with the other keys of the structure. In the current
+ //! version of the library, the comparison of `key` with any other key
+ //! of the structure must return a compile-time `Logical`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/at_key.cpp
+ //!
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.at_key.number_of_lookups.chart.json">
+ //! </div>
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto at_key = [](auto&& xs, auto const& key) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct at_key_impl : at_key_impl<S, when<true>> { };
+
+ struct at_key_t {
+ template <typename Xs, typename Key>
+ constexpr decltype(auto) operator()(Xs&& xs, Key const& key) const;
+ };
+
+ constexpr at_key_t at_key{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_AT_KEY_HPP
diff --git a/boost/hana/fwd/back.hpp b/boost/hana/fwd/back.hpp
new file mode 100644
index 0000000000..197120aff7
--- /dev/null
+++ b/boost/hana/fwd/back.hpp
@@ -0,0 +1,48 @@
+/*!
+@file
+Forward declares `boost::hana::back`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_BACK_HPP
+#define BOOST_HANA_FWD_BACK_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns the last element of a non-empty and finite iterable.
+ //! @ingroup group-Iterable
+ //!
+ //! Given a non-empty and finite iterable `xs` with a linearization of
+ //! `[x1, ..., xN]`, `back(xs)` is equal to `xN`. Equivalently, `back(xs)`
+ //! must be equivalent to `at_c<N-1>(xs)`, and that regardless of the
+ //! value category of `xs` (`back` must respect the reference semantics
+ //! of `at`).
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/back.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto back = [](auto&& xs) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename It, typename = void>
+ struct back_impl : back_impl<It, when<true>> { };
+
+ struct back_t {
+ template <typename Xs>
+ constexpr decltype(auto) operator()(Xs&& xs) const;
+ };
+
+ constexpr back_t back{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_BACK_HPP
diff --git a/boost/hana/fwd/basic_tuple.hpp b/boost/hana/fwd/basic_tuple.hpp
new file mode 100644
index 0000000000..e2e78fbbcf
--- /dev/null
+++ b/boost/hana/fwd/basic_tuple.hpp
@@ -0,0 +1,65 @@
+/*!
+@file
+Forward declares `boost::hana::basic_tuple`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_BASIC_TUPLE_HPP
+#define BOOST_HANA_FWD_BASIC_TUPLE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-datatypes
+ //! Stripped down version of `hana::tuple`.
+ //!
+ //! Whereas `hana::tuple` aims to provide an interface somewhat close to a
+ //! `std::tuple`, `basic_tuple` provides the strict minimum required to
+ //! implement a closure with maximum compile-time efficiency.
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! `Sequence`, and all the concepts it refines
+ template <typename ...Xs>
+ struct basic_tuple;
+
+ //! Tag representing `hana::basic_tuple`.
+ //! @relates hana::basic_tuple
+ struct basic_tuple_tag { };
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ //! Function object for creating a `basic_tuple`.
+ //! @relates hana::basic_tuple
+ //!
+ //! Given zero or more objects `xs...`, `make<basic_tuple_tag>` returns a
+ //! new `basic_tuple` containing those objects. The elements are held by
+ //! value inside the resulting tuple, and they are hence copied or moved
+ //! in. This is analogous to `std::make_tuple` for creating `basic_tuple`s.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/basic_tuple/make.cpp
+ template <>
+ constexpr auto make<basic_tuple_tag> = [](auto&& ...xs) {
+ return basic_tuple<std::decay_t<decltype(xs)>...>{forwarded(xs)...};
+ };
+#endif
+
+ //! Alias to `make<basic_tuple_tag>`; provided for convenience.
+ //! @relates hana::basic_tuple
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/basic_tuple/make.cpp
+ constexpr auto make_basic_tuple = make<basic_tuple_tag>;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_BASIC_TUPLE_HPP
diff --git a/boost/hana/fwd/bool.hpp b/boost/hana/fwd/bool.hpp
new file mode 100644
index 0000000000..1bb712c99e
--- /dev/null
+++ b/boost/hana/fwd/bool.hpp
@@ -0,0 +1,15 @@
+/*!
+@file
+Includes boost/hana/fwd/integral_constant.hpp.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_BOOL_HPP
+#define BOOST_HANA_FWD_BOOL_HPP
+
+#include <boost/hana/fwd/integral_constant.hpp>
+
+#endif // !BOOST_HANA_FWD_BOOL_HPP
diff --git a/boost/hana/fwd/cartesian_product.hpp b/boost/hana/fwd/cartesian_product.hpp
new file mode 100644
index 0000000000..4df7917415
--- /dev/null
+++ b/boost/hana/fwd/cartesian_product.hpp
@@ -0,0 +1,70 @@
+/*!
+@file
+Forward declares `boost::hana::cartesian_product`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CARTESIAN_PRODUCT_HPP
+#define BOOST_HANA_FWD_CARTESIAN_PRODUCT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Computes the cartesian product of a sequence of sequences.
+ //! @ingroup group-Sequence
+ //!
+ //! Given a sequence of sequences, `cartesian_product` returns a new
+ //! sequence of sequences containing the cartesian product of the
+ //! original sequences. For this method to finish, a finite number
+ //! of finite sequences must be provided.
+ //!
+ //! @note
+ //! All the sequences must have the same tag, and that tag must also match
+ //! that of the top-level sequence.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a `Sequence` `S(T)`, the signature is
+ //! \f[
+ //! \mathtt{cartesian\_product} : S(S(T)) \to S(S(T))
+ //! \f]
+ //!
+ //! @param xs
+ //! A sequence of sequences of which the cartesian product is computed.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/cartesian_product.cpp
+ //!
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.cartesian_product.compile.json">
+ //! </div>
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto cartesian_product = [](auto&& xs) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct cartesian_product_impl : cartesian_product_impl<S, when<true>> { };
+
+ struct cartesian_product_t {
+ template <typename Xs>
+ constexpr auto operator()(Xs&& xs) const;
+ };
+
+ constexpr cartesian_product_t cartesian_product{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CARTESIAN_PRODUCT_HPP
diff --git a/boost/hana/fwd/chain.hpp b/boost/hana/fwd/chain.hpp
new file mode 100644
index 0000000000..e6ec0e141f
--- /dev/null
+++ b/boost/hana/fwd/chain.hpp
@@ -0,0 +1,67 @@
+/*!
+@file
+Forward declares `boost::hana::chain`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CHAIN_HPP
+#define BOOST_HANA_FWD_CHAIN_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Feed a monadic value into a monadic computation.
+ //! @ingroup group-Monad
+ //!
+ //! Given a monadic value and a monadic function, `chain` feeds the
+ //! monadic value into the function, thus performing some Monad-specific
+ //! effects, and returns the result. An implementation of `chain` must
+ //! satisfy
+ //! @code
+ //! chain(xs, f) == flatten(transform(xs, f))
+ //! @endcode
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! For a monad `M`, given a monadic value of type `M(A)` and a monadic
+ //! function @f$ f : A \to M(B) @f$, `chain` has the signature
+ //! @f$
+ //! \mathtt{chain} : M(A) \times (A \to M(B)) \to M(B)
+ //! @f$.
+ //!
+ //! @param xs
+ //! A monadic value to be fed to the function `f`.
+ //!
+ //! @param f
+ //! A function taking a normal value in the `xs` structure, and returning
+ //! a monadic value. This function is called as `f(x)`, where `x` is an
+ //! element of the structure `xs`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/chain.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto chain = [](auto&& xs, auto&& f) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename M, typename = void>
+ struct chain_impl : chain_impl<M, when<true>> { };
+
+ struct chain_t {
+ template <typename Xs, typename F>
+ constexpr decltype(auto) operator()(Xs&& xs, F&& f) const;
+ };
+
+ constexpr chain_t chain{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CHAIN_HPP
diff --git a/boost/hana/fwd/comparing.hpp b/boost/hana/fwd/comparing.hpp
new file mode 100644
index 0000000000..c508d48a21
--- /dev/null
+++ b/boost/hana/fwd/comparing.hpp
@@ -0,0 +1,65 @@
+/*!
+@file
+Forward declares `boost::hana::comparing`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_COMPARING_HPP
+#define BOOST_HANA_FWD_COMPARING_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns a function performing `equal` after applying a transformation
+ //! to both arguments.
+ //! @ingroup group-Comparable
+ //!
+ //! `comparing` creates an equivalence relation based on the result of
+ //! applying a function to some objects, which is especially useful in
+ //! conjunction with algorithms that accept a custom predicate that must
+ //! represent an equivalence relation.
+ //!
+ //! Specifically, `comparing` is such that
+ //! @code
+ //! comparing(f) == equal ^on^ f
+ //! @endcode
+ //! or, equivalently,
+ //! @code
+ //! comparing(f)(x, y) == equal(f(x), f(y))
+ //! @endcode
+ //!
+ //! @note
+ //! This is not a tag-dispatched method (hence it can't be customized),
+ //! but just a convenience function provided with the `Comparable` concept.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a Logical `Bool` and a Comparable `B`, the signature is
+ //! @f$ \mathtt{comparing} : (A \to B) \to (A \times A \to Bool) @f$.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/comparing.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto comparing = [](auto&& f) {
+ return [perfect-capture](auto&& x, auto&& y) {
+ return equal(f(forwarded(x)), f(forwarded(y)));
+ };
+ };
+#else
+ struct comparing_t {
+ template <typename F>
+ constexpr auto operator()(F&& f) const;
+ };
+
+ constexpr comparing_t comparing{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_COMPARING_HPP
diff --git a/boost/hana/fwd/concat.hpp b/boost/hana/fwd/concat.hpp
new file mode 100644
index 0000000000..ed87f71ec1
--- /dev/null
+++ b/boost/hana/fwd/concat.hpp
@@ -0,0 +1,63 @@
+/*!
+@file
+Forward declares `boost::hana::concat`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCAT_HPP
+#define BOOST_HANA_FWD_CONCAT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Combine two monadic structures together.
+ //! @ingroup group-MonadPlus
+ //!
+ //! Given two monadic structures, `concat` combines them together and
+ //! returns a new monadic structure. The exact definition of `concat`
+ //! will depend on the exact model of MonadPlus at hand, but for
+ //! sequences it corresponds intuitively to simple concatenation.
+ //!
+ //! Also note that combination is not required to be commutative.
+ //! In other words, there is no requirement that
+ //! @code
+ //! concat(xs, ys) == concat(ys, xs)
+ //! @endcode
+ //! and indeed it does not hold in general.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a `MonadPlus` `M`, the signature of `concat` is
+ //! @f$ \mathtt{concat} : M(T) \times M(T) \to M(T) @f$.
+ //!
+ //! @param xs, ys
+ //! Two monadic structures to combine together.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/concat.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto concat = [](auto&& xs, auto&& ys) {
+ return tag-dispatched;
+ };
+#else
+ template <typename M, typename = void>
+ struct concat_impl : concat_impl<M, when<true>> { };
+
+ struct concat_t {
+ template <typename Xs, typename Ys>
+ constexpr auto operator()(Xs&& xs, Ys&& ys) const;
+ };
+
+ constexpr concat_t concat{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCAT_HPP
diff --git a/boost/hana/fwd/concept/applicative.hpp b/boost/hana/fwd/concept/applicative.hpp
new file mode 100644
index 0000000000..8f5db93042
--- /dev/null
+++ b/boost/hana/fwd/concept/applicative.hpp
@@ -0,0 +1,117 @@
+/*!
+@file
+Forward declares `boost::hana::Applicative`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_APPLICATIVE_HPP
+#define BOOST_HANA_FWD_CONCEPT_APPLICATIVE_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! @defgroup group-Applicative Applicative
+ //! The `Applicative` concept represents `Functor`s with the ability
+ //! to lift values and combine computations.
+ //!
+ //! A `Functor` can only take a normal function and map it over a
+ //! structure containing values to obtain a new structure containing
+ //! values. Intuitively, an `Applicative` can also take a value and
+ //! lift it into the structure. In addition, an `Applicative` can take
+ //! a structure containing functions and apply it to a structure
+ //! containing values to obtain a new structure containing values.
+ //! By currying the function(s) inside the structure, it is then
+ //! also possible to apply n-ary functions to n structures containing
+ //! values.
+ //!
+ //! @note
+ //! This documentation does not go into much details about the nature
+ //! of applicatives. However, the [Typeclassopedia][1] is a nice
+ //! Haskell-oriented resource where such information can be found.
+ //!
+ //!
+ //! Minimal complete definition
+ //! ---------------------------
+ //! `lift` and `ap` satisfying the laws below. An `Applicative` must
+ //! also be a `Functor`.
+ //!
+ //!
+ //! Laws
+ //! ----
+ //! Given an `Applicative` `F`, the following laws must be satisfied:
+ //! 1. Identity\n
+ //! For all objects `xs` of tag `F(A)`,
+ //! @code
+ //! ap(lift<F>(id), xs) == xs
+ //! @endcode
+ //!
+ //! 2. Composition\n
+ //! For all objects `xs` of tag `F(A)` and functions-in-an-applicative
+ //! @f$ fs : F(B \to C) @f$,
+ //! @f$ gs : F(A \to B) @f$,
+ //! @code
+ //! ap(ap(lift<F>(compose), fs, gs), xs) == ap(fs, ap(gs, xs))
+ //! @endcode
+ //!
+ //! 3. Homomorphism\n
+ //! For all objects `x` of tag `A` and functions @f$ f : A \to B @f$,
+ //! @code
+ //! ap(lift<F>(f), lift<F>(x)) == lift<F>(f(x))
+ //! @endcode
+ //!
+ //! 4. Interchange\n
+ //! For all objects `x` of tag `A` and functions-in-an-applicative
+ //! @f$ fs : F(A \to B) @f$,
+ //! @code
+ //! ap(fs, lift<F>(x)) == ap(lift<F>(apply(-, x)), fs)
+ //! @endcode
+ //! where `apply(-, x)` denotes the partial application of the `apply`
+ //! function from the @ref group-functional module to the `x` argument.
+ //!
+ //! As a consequence of these laws, the model of `Functor` for `F` will
+ //! satisfy the following for all objects `xs` of tag `F(A)` and functions
+ //! @f$ f : A \to B @f$:
+ //! @code
+ //! transform(xs, f) == ap(lift<F>(f), xs)
+ //! @endcode
+ //!
+ //!
+ //! Refined concept
+ //! ---------------
+ //! 1. `Functor` (free model)\n
+ //! As a consequence of the laws, any `Applicative F` can be made a
+ //! `Functor` by setting
+ //! @code
+ //! transform(xs, f) = ap(lift<F>(f), xs)
+ //! @endcode
+ //!
+ //!
+ //! Concrete models
+ //! ---------------
+ //! `hana::lazy`, `hana::optional`, `hana::tuple`
+ //!
+ //!
+ //! @anchor applicative-transformation
+ //! Structure-preserving functions
+ //! ------------------------------
+ //! An _applicative transformation_ is a function @f$ t : F(X) \to G(X) @f$
+ //! between two Applicatives `F` and `G`, where `X` can be any tag, and
+ //! which preserves the operations of an Applicative. In other words, for
+ //! all objects `x` of tag `X`, functions-in-an-applicative
+ //! @f$ fs : F(X \to Y) @f$ and objects `xs` of tag `F(X)`,
+ //! @code
+ //! t(lift<F>(x)) == lift<G>(x)
+ //! t(ap(fs, xs)) == ap(t(fs), t(xs))
+ //! @endcode
+ //!
+ //! [1]: https://wiki.haskell.org/Typeclassopedia#Applicative
+ template <typename A>
+ struct Applicative;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_APPLICATIVE_HPP
diff --git a/boost/hana/fwd/concept/comonad.hpp b/boost/hana/fwd/concept/comonad.hpp
new file mode 100644
index 0000000000..0c3627576b
--- /dev/null
+++ b/boost/hana/fwd/concept/comonad.hpp
@@ -0,0 +1,111 @@
+/*!
+@file
+Forward declares `boost::hana::Comonad`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_COMONAD_HPP
+#define BOOST_HANA_FWD_CONCEPT_COMONAD_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ // Note: We use a multiline C++ comment because there's a double backslash
+ // symbol in the documentation (for LaTeX), which triggers
+ // warning: multi-line comment [-Wcomment]
+ // on GCC.
+
+ /*!
+ @ingroup group-concepts
+ @defgroup group-Comonad Comonad
+ The `Comonad` concept represents context-sensitive computations and
+ data.
+
+ Formally, the Comonad concept is dual to the Monad concept.
+ But unless you're a mathematician, you don't care about that and it's
+ fine. So intuitively, a Comonad represents context sensitive values
+ and computations. First, Comonads make it possible to extract
+ context-sensitive values from their context with `extract`.
+ In contrast, Monads make it possible to wrap raw values into
+ a given context with `lift` (from Applicative).
+
+ Secondly, Comonads make it possible to apply context-sensitive values
+ to functions accepting those, and to return the result as a
+ context-sensitive value using `extend`. In contrast, Monads make
+ it possible to apply a monadic value to a function accepting a normal
+ value and returning a monadic value, and to return the result as a
+ monadic value (with `chain`).
+
+ Finally, Comonads make it possible to wrap a context-sensitive value
+ into an extra layer of context using `duplicate`, while Monads make
+ it possible to take a value with an extra layer of context and to
+ strip it with `flatten`.
+
+ Whereas `lift`, `chain` and `flatten` from Applicative and Monad have
+ signatures
+ \f{align*}{
+ \mathtt{lift}_M &: T \to M(T) \\
+ \mathtt{chain} &: M(T) \times (T \to M(U)) \to M(U) \\
+ \mathtt{flatten} &: M(M(T)) \to M(T)
+ \f}
+
+ `extract`, `extend` and `duplicate` from Comonad have signatures
+ \f{align*}{
+ \mathtt{extract} &: W(T) \to T \\
+ \mathtt{extend} &: W(T) \times (W(T) \to U) \to W(U) \\
+ \mathtt{duplicate} &: W(T) \to W(W(T))
+ \f}
+
+ Notice how the "arrows" are reversed. This symmetry is essentially
+ what we mean by Comonad being the _dual_ of Monad.
+
+ @note
+ The [Typeclassopedia][1] is a nice Haskell-oriented resource for further
+ reading about Comonads.
+
+
+ Minimal complete definition
+ ---------------------------
+ `extract` and (`extend` or `duplicate`) satisfying the laws below.
+ A `Comonad` must also be a `Functor`.
+
+
+ Laws
+ ----
+ For all Comonads `w`, the following laws must be satisfied:
+ @code
+ extract(duplicate(w)) == w
+ transform(duplicate(w), extract) == w
+ duplicate(duplicate(w)) == transform(duplicate(w), duplicate)
+ @endcode
+
+ @note
+ There are several equivalent ways of defining Comonads, and this one
+ is just one that was picked arbitrarily for simplicity.
+
+
+ Refined concept
+ ---------------
+ 1. Functor\n
+ Every Comonad is also required to be a Functor. At first, one might think
+ that it should instead be some imaginary concept CoFunctor. However, it
+ turns out that a CoFunctor is the same as a `Functor`, hence the
+ requirement that a `Comonad` also is a `Functor`.
+
+
+ Concrete models
+ ---------------
+ `hana::lazy`
+
+ [1]: https://wiki.haskell.org/Typeclassopedia#Comonad
+
+ */
+ template <typename W>
+ struct Comonad;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_COMONAD_HPP
diff --git a/boost/hana/fwd/concept/comparable.hpp b/boost/hana/fwd/concept/comparable.hpp
new file mode 100644
index 0000000000..1d4df7d635
--- /dev/null
+++ b/boost/hana/fwd/concept/comparable.hpp
@@ -0,0 +1,161 @@
+/*!
+@file
+Forward declares `boost::hana::Comparable`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_COMPARABLE_HPP
+#define BOOST_HANA_FWD_CONCEPT_COMPARABLE_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! @defgroup group-Comparable Comparable
+ //! The `Comparable` concept defines equality and inequality.
+ //!
+ //! Intuitively, `Comparable` objects must define a binary predicate named
+ //! `equal` that returns whether both objects represent the same abstract
+ //! value. In other words, `equal` must check for deep equality. Since
+ //! "representing the same abstract value" is difficult to express
+ //! formally, the exact meaning of equality is partially left to
+ //! interpretation by the programmer with the following guidelines:\n
+ //! 1. Equality should be compatible with copy construction; copy
+ //! constructing a value yields an `equal` value.
+ //! 2. Equality should be independent of representation; an object
+ //! representing a fraction as `4/8` should be `equal` to an object
+ //! representing a fraction as `2/4`, because they both represent
+ //! the mathematical object `1/2`.
+ //!
+ //! Moreover, `equal` must exhibit properties that make it intuitive to
+ //! use for determining the equivalence of objects, which is formalized
+ //! by the laws for `Comparable`.
+ //!
+ //!
+ //! Minimal complete definition
+ //! ---------------------------
+ //! 1. `equal`\n
+ //! When `equal` is defined, `not_equal` is implemented by default as its
+ //! complement. For all objects `x`, `y` of a `Comparable` tag,
+ //! @code
+ //! not_equal(x, y) == not_(equal(x, y))
+ //! @endcode
+ //!
+ //!
+ //! Laws
+ //! ----
+ //! `equal` must define an [equivalence relation][1], and `not_equal` must
+ //! be its complement. In other words, for all objects `a`, `b`, `c` of a
+ //! `Comparable` tag, the following must be true (where `x == y` and
+ //! `x != y` denote `equal(x, y)` and `not_equal(x, y)`, respectively):
+ //! @code
+ //! a == a // Reflexivity
+ //! if a == b then b == a // Symmetry
+ //! if a == b && b == c then a == c // Transitivity
+ //! a != b is equivalent to !(a == b)
+ //! @endcode
+ //!
+ //!
+ //! Concrete models
+ //! ---------------
+ //! `hana::integral_constant`, `hana::map`, `hana::optional`, `hana::pair`,
+ //! `hana::range`, `hana::set`, `hana::string`, `hana::tuple`,
+ //! `hana::type`
+ //!
+ //!
+ //! Free model for `EqualityComparable` data types
+ //! ----------------------------------------------
+ //! Two data types `T` and `U` that model the cross-type EqualityComparable
+ //! concept presented in [N3351][2] automatically model the `Comparable`
+ //! concept by setting
+ //! @code
+ //! equal(x, y) = (x == y)
+ //! @endcode
+ //! Note that this also makes EqualityComparable types in the
+ //! [usual sense][3] models of `Comparable` in the same way.
+ //!
+ //!
+ //! Equality-preserving functions
+ //! -----------------------------
+ //! Let `A` and `B` be two `Comparable` tags. A function @f$f : A \to B@f$
+ //! is said to be equality-preserving if it preserves the structure of the
+ //! `Comparable` concept, which can be rigorously stated as follows. For
+ //! all objects `x`, `y` of tag `A`,
+ //! @code
+ //! if equal(x, y) then equal(f(x), f(y))
+ //! @endcode
+ //! Equivalently, we simply require that `f` is a function in the usual
+ //! mathematical sense. Another property is [injectivity][4], which can be
+ //! viewed as being a "lossless" mapping. This property can be stated as
+ //! @code
+ //! if equal(f(x), f(y)) then equal(x, y)
+ //! @endcode
+ //! This is equivalent to saying that `f` maps distinct elements to
+ //! distinct elements, hence the "lossless" analogy. In other words, `f`
+ //! will not collapse distinct elements from its domain into a single
+ //! element in its image, thus losing information.
+ //!
+ //! These functions are very important, especially equality-preserving
+ //! ones, because they allow us to reason simply about programs. Also
+ //! note that the property of being equality-preserving is taken for
+ //! granted in mathematics because it is part of the definition of a
+ //! function. We feel it is important to make the distinction here
+ //! because programming has evolved differently and as a result
+ //! programmers are used to work with functions that do not preserve
+ //! equality.
+ //!
+ //!
+ //! Cross-type version of the methods
+ //! ---------------------------------
+ //! The `equal` and `not_equal` methods are "overloaded" to handle
+ //! distinct tags with certain properties. Specifically, they are
+ //! defined for _distinct_ tags `A` and `B` such that
+ //! 1. `A` and `B` share a common tag `C`, as determined by the
+ //! `common` metafunction
+ //! 2. `A`, `B` and `C` are all `Comparable` when taken individually
+ //! 3. @f$ \mathtt{to<C>} : A \to C @f$ and @f$\mathtt{to<C>} : B \to C@f$
+ //! are both equality-preserving and injective (i.e. they are embeddings),
+ //! as determined by the `is_embedding` metafunction.
+ //!
+ //! The method definitions for tags satisfying the above properties are
+ //! @code
+ //! equal(x, y) = equal(to<C>(x), to<C>(y))
+ //! not_equal(x, y) = not_equal(to<C>(x), to<C>(y))
+ //! @endcode
+ //!
+ //!
+ //! Important note: special behavior of `equal`
+ //! -------------------------------------------
+ //! In the context of programming with heterogeneous values, it is useful
+ //! to have unrelated objects compare `false` instead of triggering an
+ //! error. For this reason, `equal` adopts a special behavior for
+ //! unrelated objects of tags `T` and `U` that do not satisfy the above
+ //! requirements for the cross-type overloads. Specifically, when `T` and
+ //! `U` are unrelated (i.e. `T` can't be converted to `U` and vice-versa),
+ //! comparing objects with those tags yields a compile-time false value.
+ //! This has the effect that unrelated objects like `float` and
+ //! `std::string` will compare false, while comparing related objects that
+ //! can not be safely embedded into the same super structure (like
+ //! `long long` and `float` because of the precision loss) will trigger a
+ //! compile-time assertion. Also note that for any tag `T` for which the
+ //! minimal complete definition of `Comparable` is not provided, a
+ //! compile-time assertion will also be triggered because `T` and `T`
+ //! trivially share the common tag `T`, which is the expected behavior.
+ //! This design choice aims to provide more flexibility for comparing
+ //! objects, while still rejecting usage patterns that are most likely
+ //! programming errors.
+ //!
+ //!
+ //! [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
+ //! [4]: http://en.wikipedia.org/wiki/Injective_function
+ template <typename T>
+ struct Comparable;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_COMPARABLE_HPP
diff --git a/boost/hana/fwd/concept/constant.hpp b/boost/hana/fwd/concept/constant.hpp
new file mode 100644
index 0000000000..a9c1467dbc
--- /dev/null
+++ b/boost/hana/fwd/concept/constant.hpp
@@ -0,0 +1,210 @@
+/*!
+@file
+Forward declares `boost::hana::Constant`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_CONSTANT_HPP
+#define BOOST_HANA_FWD_CONCEPT_CONSTANT_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! @defgroup group-Constant Constant
+ //! The `Constant` concept represents data that can be manipulated at
+ //! compile-time.
+ //!
+ //! At its core, `Constant` is simply a generalization of the principle
+ //! behind `std::integral_constant` to all types that can be constructed
+ //! at compile-time, i.e. to all types with a `constexpr` constructor
+ //! (also called [Literal types][1]). More specifically, a `Constant` is
+ //! an object from which a `constexpr` value may be obtained (through the
+ //! `value` method) regardless of the `constexpr`ness of the object itself.
+ //!
+ //! All `Constant`s must be somewhat equivalent, in the following sense.
+ //! Let `C(T)` and `D(U)` denote the tags of `Constant`s holding objects
+ //! of type `T` and `U`, respectively. Then, an object with tag `D(U)`
+ //! must be convertible to an object with tag `C(T)` whenever `U` is
+ //! convertible to `T`, has determined by `is_convertible`. The
+ //! interpretation here is that a `Constant` is just a box holding
+ //! an object of some type, and it should be possible to swap between
+ //! boxes whenever the objects inside the boxes can be swapped.
+ //!
+ //! Because of this last requirement, one could be tempted to think that
+ //! specialized "boxes" like `std::integral_constant` are prevented from
+ //! being `Constant`s because they are not able to hold objects of any
+ //! type `T` (`std::integral_constant` may only hold integral types).
+ //! This is false; the requirement should be interpreted as saying that
+ //! whenever `C(T)` is _meaningful_ (e.g. only when `T` is integral for
+ //! `std::integral_constant`) _and_ there exists a conversion from `U`
+ //! to `T`, then a conversion from `D(U)` to `C(T)` should also exist.
+ //! The precise requirements for being a `Constant` are embodied in the
+ //! following laws.
+ //!
+ //!
+ //! Minimal complete definition
+ //! ---------------------------
+ //! `value` and `to`, satisfying the laws below.
+ //!
+ //!
+ //! Laws
+ //! ----
+ //! Let `c` be an object of with tag `C`, which represents a `Constant`
+ //! holding an object with tag `T`. The first law ensures that the value
+ //! of the wrapped object is always a constant expression by requiring
+ //! the following to be well-formed:
+ //! @code
+ //! constexpr auto x = hana::value<decltype(x)>();
+ //! @endcode
+ //!
+ //! This means that the `value` function must return an object that can
+ //! be constructed at compile-time. It is important to note how `value`
+ //! only receives the type of the object and not the object itself.
+ //! This is the core of the `Constant` concept; it means that the only
+ //! information required to implement `value` must be stored in the _type_
+ //! of its argument, and hence be available statically.
+ //!
+ //! The second law that must be satisfied ensures that `Constant`s are
+ //! basically dumb boxes, which makes it possible to provide models for
+ //! many concepts without much work from the user. The law simply asks
+ //! for the following expression to be valid:
+ //! @code
+ //! to<C>(i)
+ //! @endcode
+ //! where, `i` is an _arbitrary_ `Constant` holding an internal value
+ //! with a tag that can be converted to `T`, as determined by the
+ //! `hana::is_convertible` metafunction. In other words, whenever `U` is
+ //! convertible to `T`, a `Constant` holding a `U` is convertible to
+ //! a `Constant` holding a `T`, if such a `Constant` can be created.
+ //!
+ //! Finally, the tag `C` must provide a nested `value_type` alias to `T`,
+ //! which allows us to query the tag of the inner value held by objects
+ //! with tag `C`. In other words, the following must be true for any
+ //! object `c` with tag `C`:
+ //! @code
+ //! std::is_same<
+ //! C::value_type,
+ //! tag_of<decltype(hana::value(c))>::type
+ //! >::value
+ //! @endcode
+ //!
+ //!
+ //! Refined concepts
+ //! ----------------
+ //! In certain cases, a `Constant` can automatically be made a model of
+ //! another concept. In particular, if a `Constant` `C` is holding an
+ //! object of tag `T`, and if `T` models a concept `X`, then `C` may
+ //! in most cases model `X` by simply performing whatever operation is
+ //! required on its underlying value, and then wrapping the result back
+ //! in a `C`.
+ //!
+ //! More specifically, if a `Constant` `C` has an underlying value
+ //! (`C::value_type`) which is a model of `Comparable`, `Orderable`,
+ //! `Logical`, or `Monoid` up to `EuclideanRing`, then `C` must also
+ //! be a model of those concepts. In other words, when `C::value_type`
+ //! models one of the listed concepts, `C` itself must also model that
+ //! concept. However, note that free models are provided for all of
+ //! those concepts, so no additional work must be done.
+ //!
+ //! While it would be possible in theory to provide models for concepts
+ //! like `Foldable` too, only a couple of concepts are useful to have as
+ //! `Constant` in practice. Providing free models for the concepts listed
+ //! above is useful because it allows various types of integral constants
+ //! (`std::integral_constant`, `mpl::integral_c`, etc...) to easily have
+ //! models for them just by defining the `Constant` concept.
+ //!
+ //! @remark
+ //! An interesting observation is that `Constant` is actually the
+ //! canonical embedding of the subcategory of `constexpr` things
+ //! into the Hana category, which contains everything in this library.
+ //! Hence, whatever is true in that subcategory is also true here, via
+ //! this functor. This is why we can provide models of any concept that
+ //! works on `constexpr` things for Constants, by simply passing them
+ //! through that embedding.
+ //!
+ //!
+ //! Concrete models
+ //! ---------------
+ //! `hana::integral_constant`
+ //!
+ //!
+ //! Provided conversion to the tag of the underlying value
+ //! ------------------------------------------------------
+ //! Any `Constant` `c` holding an underlying value of tag `T` is
+ //! convertible to any tag `U` such that `T` is convertible to `U`.
+ //! Specifically, the conversion is equivalent to
+ //! @code
+ //! to<U>(c) == to<U>(value<decltype(c)>())
+ //! @endcode
+ //!
+ //! Also, those conversions are marked as an embedding whenever the
+ //! conversion of underlying types is an embedding. This is to allow
+ //! Constants to inter-operate with `constexpr` objects easily:
+ //! @code
+ //! plus(int_<1>, 1) == 2
+ //! @endcode
+ //!
+ //! Strictly speaking, __this is sometimes a violation__ of what it means
+ //! to be an embedding. Indeed, while there exists an embedding from any
+ //! Constant to a `constexpr` object (since Constant is just the canonical
+ //! inclusion), there is no embedding from a Constant to a runtime
+ //! object since we would lose the ability to define the `value` method
+ //! (the `constexpr`ness of the object would have been lost). Since there
+ //! is no way to distinguish `constexpr` and non-`constexpr` objects based
+ //! on their type, Hana has no way to know whether the conversion is to a
+ //! `constexpr` object of not. In other words, the `to` method has no way
+ //! to differentiate between
+ //! @code
+ //! constexpr int i = hana::to<int>(int_<1>);
+ //! @endcode
+ //! which is an embedding, and
+ //! @code
+ //! int i = hana::to<int>(int_<1>);
+ //! @endcode
+ //!
+ //! which isn't. To be on the safer side, we could mark the conversion
+ //! as not-an-embedding. However, if e.g. the conversion from
+ //! `integral_constant_tag<int>` to `int` was not marked as an embedding,
+ //! we would have to write `plus(to<int>(int_<1>), 1)` instead of just
+ //! `plus(int_<1>, 1)`, which is cumbersome. Hence, the conversion is
+ //! marked as an embedding, but this also means that code like
+ //! @code
+ //! int i = 1;
+ //! plus(int_<1>, i);
+ //! @endcode
+ //! will be considered valid, which implicitly loses the fact that
+ //! `int_<1>` is a Constant, and hence does not follow the usual rules
+ //! for cross-type operations in Hana.
+ //!
+ //!
+ //! Provided common data type
+ //! -------------------------
+ //! Because of the requirement that `Constant`s be interchangeable when
+ //! their contents are compatible, two `Constant`s `A` and `B` will have
+ //! a common data type whenever `A::value_type` and `B::value_type` have
+ //! one. Their common data type is an unspecified `Constant` `C` such
+ //! that `C::value_type` is exactly `common_t<A::value_type, B::value_type>`.
+ //! A specialization of the `common` metafunction is provided for
+ //! `Constant`s to reflect this.
+ //!
+ //! In the same vein, a common data type is also provided from any
+ //! constant `A` to a type `T` such that `A::value_type` and `T` share
+ //! a common type. The common type between `A` and `T` is obviously the
+ //! common type between `A::value_type` and `T`. As explained above in
+ //! the section on conversions, this is sometimes a violation of the
+ //! definition of a common type, because there must be an embedding
+ //! to the common type, which is not always the case. For the same
+ //! reasons as explained above, this common type is still provided.
+ //!
+ //!
+ //! [1]: http://en.cppreference.com/w/cpp/concept/LiteralType
+ template <typename C>
+ struct Constant;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_CONSTANT_HPP
diff --git a/boost/hana/fwd/concept/euclidean_ring.hpp b/boost/hana/fwd/concept/euclidean_ring.hpp
new file mode 100644
index 0000000000..b33d8b565c
--- /dev/null
+++ b/boost/hana/fwd/concept/euclidean_ring.hpp
@@ -0,0 +1,117 @@
+/*!
+@file
+Forward declares `boost::hana::EuclideanRing`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_EUCLIDEAN_RING_HPP
+#define BOOST_HANA_FWD_CONCEPT_EUCLIDEAN_RING_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! @defgroup group-EuclideanRing Euclidean Ring
+ //! The `EuclideanRing` concept represents a commutative `Ring` that
+ //! can also be endowed with a division algorithm.
+ //!
+ //! A Ring defines a binary operation often called _multiplication_ that
+ //! can be used to combine two elements of the ring into a new element of
+ //! the ring. An [Euclidean ring][1], also called an Euclidean domain, adds
+ //! the ability to define a special function that generalizes the Euclidean
+ //! division of integers.
+ //!
+ //! However, an Euclidean ring must also satisfy one more property, which
+ //! is that of having no non-zero zero divisors. In a Ring `(R, +, *)`, it
+ //! follows quite easily from the axioms that `x * 0 == 0` for any ring
+ //! element `x`. However, there is nothing that mandates `0` to be the
+ //! only ring element sending other elements to `0`. Hence, in some Rings,
+ //! it is possible to have elements `x` and `y` such that `x * y == 0`
+ //! while not having `x == 0` nor `y == 0`. We call these elements divisors
+ //! of zero, or zero divisors. For example, this situation arises in the
+ //! Ring of integers modulo 4 (the set `{0, 1, 2, 3}`) with addition and
+ //! multiplication `mod 4` as binary operations. In this case, we have that
+ //! @code
+ //! 2 * 2 == 4
+ //! == 0 (mod 4)
+ //! @endcode
+ //! even though `2 != 0 (mod 4)`.
+ //!
+ //! Following this line of thought, an Euclidean ring requires its only
+ //! zero divisor is zero itself. In other words, the multiplication in an
+ //! Euclidean won't send two non-zero elements to zero. Also note that
+ //! since multiplication in a `Ring` is not necessarily commutative, it
+ //! is not always the case that
+ //! @code
+ //! x * y == 0 implies y * x == 0
+ //! @endcode
+ //! To be rigorous, we should then distinguish between elements that are
+ //! zero divisors when multiplied to the right and to the left.
+ //! Fortunately, the concept of an Euclidean ring requires the Ring
+ //! multiplication to be commutative. Hence,
+ //! @code
+ //! x * y == y * x
+ //! @endcode
+ //! and we do not have to distinguish between left and right zero divisors.
+ //!
+ //! Typical examples of Euclidean rings include integers and polynomials
+ //! over a field. The method names used here refer to the Euclidean ring
+ //! of integers under the usual addition, multiplication and division
+ //! operations.
+ //!
+ //!
+ //! Minimal complete definition
+ //! ---------------------------
+ //! `div` and `mod` satisfying the laws below
+ //!
+ //!
+ //! Laws
+ //! ----
+ //! To simplify the reading, we will use the `+`, `*`, `/` and `%`
+ //! operators with infix notation to denote the application of the
+ //! corresponding methods in Monoid, Group, Ring and EuclideanRing.
+ //! For all objects `a` and `b` of an `EuclideanRing` `R`, the
+ //! following laws must be satisfied:
+ //! @code
+ //! a * b == b * a // commutativity
+ //! (a / b) * b + a % b == a if b is non-zero
+ //! zero<R>() % b == zero<R>() if b is non-zero
+ //! @endcode
+ //!
+ //!
+ //! Refined concepts
+ //! ----------------
+ //! `Monoid`, `Group`, `Ring`
+ //!
+ //!
+ //! Concrete models
+ //! ---------------
+ //! `hana::integral_constant`
+ //!
+ //!
+ //! Free model for non-boolean integral data types
+ //! ----------------------------------------------
+ //! A data type `T` is integral if `std::is_integral<T>::%value` is true.
+ //! For a non-boolean integral data type `T`, a model of `EuclideanRing`
+ //! is automatically defined by using the `Ring` model provided for
+ //! arithmetic data types and setting
+ //! @code
+ //! div(x, y) = (x / y)
+ //! mod(x, y) = (x % y)
+ //! @endcode
+ //!
+ //! @note
+ //! The rationale for not providing an EuclideanRing model for `bool` is
+ //! the same as for not providing Monoid, Group and Ring models.
+ //!
+ //!
+ //! [1]: https://en.wikipedia.org/wiki/Euclidean_domain
+ template <typename R>
+ struct EuclideanRing;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_EUCLIDEAN_RING_HPP
diff --git a/boost/hana/fwd/concept/foldable.hpp b/boost/hana/fwd/concept/foldable.hpp
new file mode 100644
index 0000000000..6e460ad435
--- /dev/null
+++ b/boost/hana/fwd/concept/foldable.hpp
@@ -0,0 +1,141 @@
+/*!
+@file
+Forward declares `boost::hana::Foldable`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_FOLDABLE_HPP
+#define BOOST_HANA_FWD_CONCEPT_FOLDABLE_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! @defgroup group-Foldable Foldable
+ //! The `Foldable` concept represents data structures that can be reduced
+ //! to a single value.
+ //!
+ //! Generally speaking, folding refers to the concept of summarizing a
+ //! complex structure as a single value, by successively applying a
+ //! binary operation which reduces two elements of the structure to a
+ //! single value. Folds come in many flavors; left folds, right folds,
+ //! folds with and without an initial reduction state, and their monadic
+ //! variants. This concept is able to express all of these fold variants.
+ //!
+ //! Another way of seeing `Foldable` is as data structures supporting
+ //! internal iteration with the ability to accumulate a result. By
+ //! internal iteration, we mean that the _loop control_ is in the hand
+ //! of the structure, not the caller. Hence, it is the structure who
+ //! decides when the iteration stops, which is normally when the whole
+ //! structure has been consumed. Since C++ is an eager language, this
+ //! requires `Foldable` structures to be finite, or otherwise one would
+ //! need to loop indefinitely to consume the whole structure.
+ //!
+ //! @note
+ //! While the fact that `Foldable` only works for finite structures may
+ //! seem overly restrictive in comparison to the Haskell definition of
+ //! `Foldable`, a finer grained separation of the concepts should
+ //! mitigate the issue. For iterating over possibly infinite data
+ //! structures, see the `Iterable` concept. For searching a possibly
+ //! infinite data structure, see the `Searchable` concept.
+ //!
+ //!
+ //! Minimal complete definition
+ //! ---------------------------
+ //! `fold_left` or `unpack`
+ //!
+ //! However, please note that a minimal complete definition provided
+ //! through `unpack` will be much more compile-time efficient than one
+ //! provided through `fold_left`.
+ //!
+ //!
+ //! Concrete models
+ //! ---------------
+ //! `hana::map`, `hana::optional`, `hana::pair`, `hana::set`,
+ //! `hana::range`, `hana::tuple`
+ //!
+ //!
+ //! @anchor Foldable-lin
+ //! The linearization of a `Foldable`
+ //! ---------------------------------
+ //! Intuitively, for a `Foldable` structure `xs`, the _linearization_ of
+ //! `xs` is the sequence of all the elements in `xs` as if they had been
+ //! put in a list:
+ //! @code
+ //! linearization(xs) = [x1, x2, ..., xn]
+ //! @endcode
+ //!
+ //! Note that it is always possible to produce such a linearization
+ //! for a finite `Foldable` by setting
+ //! @code
+ //! linearization(xs) = fold_left(xs, [], flip(prepend))
+ //! @endcode
+ //! for an appropriate definition of `[]` and `prepend`. The notion of
+ //! linearization is useful for expressing various properties of
+ //! `Foldable` structures, and is used across the documentation. Also
+ //! note that `Iterable`s define an [extended version](@ref Iterable-lin)
+ //! of this allowing for infinite structures.
+ //!
+ //!
+ //! Compile-time Foldables
+ //! ----------------------
+ //! A compile-time `Foldable` is a `Foldable` whose total length is known
+ //! at compile-time. In other words, it is a `Foldable` whose `length`
+ //! method returns a `Constant` of an unsigned integral type. When
+ //! folding a compile-time `Foldable`, the folding can be unrolled,
+ //! because the final number of steps of the algorithm is known at
+ //! compile-time.
+ //!
+ //! Additionally, the `unpack` method is only available to compile-time
+ //! `Foldable`s. This is because the return _type_ of `unpack` depends
+ //! on the number of objects in the structure. Being able to resolve
+ //! `unpack`'s return type at compile-time hence requires the length of
+ //! the structure to be known at compile-time too.
+ //!
+ //! __In the current version of the library, only compile-time `Foldable`s
+ //! are supported.__ While it would be possible in theory to support
+ //! runtime `Foldable`s too, doing so efficiently requires more research.
+ //!
+ //!
+ //! Provided conversion to `Sequence`s
+ //! ----------------------------------
+ //! Given a tag `S` which is a `Sequence`, an object whose tag is a model
+ //! of the `Foldable` concept can be converted to an object of tag `S`.
+ //! In other words, a `Foldable` can be converted to a `Sequence` `S`, by
+ //! simply taking the linearization of the `Foldable` and creating the
+ //! sequence with that. More specifically, given a `Foldable` `xs` with a
+ //! linearization of `[x1, ..., xn]` and a `Sequence` tag `S`, `to<S>(xs)`
+ //! is equivalent to `make<S>(x1, ..., xn)`.
+ //! @include example/foldable/to.cpp
+ //!
+ //!
+ //! Free model for builtin arrays
+ //! -----------------------------
+ //! Builtin arrays whose size is known can be folded as-if they were
+ //! homogeneous tuples. However, note that builtin arrays can't be
+ //! made more than `Foldable` (e.g. `Iterable`) because they can't
+ //! be empty and they also can't be returned from functions.
+ //!
+ //!
+ //! @anchor monadic-folds
+ //! Primer on monadic folds
+ //! -----------------------
+ //! A monadic fold is a fold in which subsequent calls to the binary
+ //! function are chained with the monadic `chain` operator of the
+ //! corresponding Monad. This allows a structure to be folded in a
+ //! custom monadic context. For example, performing a monadic fold with
+ //! the `hana::optional` monad would require the binary function to return
+ //! the result as a `hana::optional`, and the fold would abort and return
+ //! `nothing` whenever one of the accumulation step would fail (i.e.
+ //! return `nothing`). If, however, all the reduction steps succeed,
+ //! then `just` the result would be returned. Different monads will of
+ //! course result in different effects.
+ template <typename T>
+ struct Foldable;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_FOLDABLE_HPP
diff --git a/boost/hana/fwd/concept/functor.hpp b/boost/hana/fwd/concept/functor.hpp
new file mode 100644
index 0000000000..6d2ea170f6
--- /dev/null
+++ b/boost/hana/fwd/concept/functor.hpp
@@ -0,0 +1,139 @@
+/*!
+@file
+Forward declares `boost::hana::Functor`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_FUNCTOR_HPP
+#define BOOST_HANA_FWD_CONCEPT_FUNCTOR_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! @defgroup group-Functor Functor
+ //! The `Functor` concept represents types that can be mapped over.
+ //!
+ //! Intuitively, a [Functor][1] is some kind of box that can hold generic
+ //! data and map a function over this data to create a new, transformed
+ //! box. Because we are only interested in mapping a function over the
+ //! contents of a black box, the only real requirement for being a functor
+ //! is to provide a function which can do the mapping, along with a couple
+ //! of guarantees that the mapping is well-behaved. Those requirements are
+ //! made precise in the laws below. The pattern captured by `Functor` is
+ //! very general, which makes it widely useful. A lot of objects can be
+ //! made `Functor`s in one way or another, the most obvious example being
+ //! sequences with the usual mapping of the function on each element.
+ //! While this documentation will not go into much more details about
+ //! the nature of functors, the [Typeclassopedia][2] is a nice
+ //! Haskell-oriented resource for such information.
+ //!
+ //! Functors are parametric data types which are parameterized over the
+ //! data type of the objects they contain. Like everywhere else in Hana,
+ //! this parametricity is only at the documentation level and it is not
+ //! enforced.
+ //!
+ //! In this library, the mapping function is called `transform` after the
+ //! `std::transform` algorithm, but other programming languages have given
+ //! it different names (usually `map`).
+ //!
+ //! @note
+ //! The word _functor_ comes from functional programming, where the
+ //! concept has been used for a while, notably in the Haskell programming
+ //! language. Haskell people borrowed the term from [category theory][3],
+ //! which, broadly speaking, is a field of mathematics dealing with
+ //! abstract structures and transformations between those structures.
+ //!
+ //!
+ //! Minimal complete definitions
+ //! ----------------------------
+ //! 1. `transform`\n
+ //! When `transform` is specified, `adjust_if` is defined analogously to
+ //! @code
+ //! adjust_if(xs, pred, f) = transform(xs, [](x){
+ //! if pred(x) then f(x) else x
+ //! })
+ //! @endcode
+ //!
+ //! 2. `adjust_if`\n
+ //! When `adjust_if` is specified, `transform` is defined analogously to
+ //! @code
+ //! transform(xs, f) = adjust_if(xs, always(true), f)
+ //! @endcode
+ //!
+ //!
+ //! Laws
+ //! ----
+ //! Let `xs` be a Functor with tag `F(A)`,
+ //! \f$ f : A \to B \f$ and
+ //! \f$ g : B \to C \f$.
+ //! The following laws must be satisfied:
+ //! @code
+ //! transform(xs, id) == xs
+ //! transform(xs, compose(g, f)) == transform(transform(xs, f), g)
+ //! @endcode
+ //! The first line says that mapping the identity function should not do
+ //! anything, which precludes the functor from doing something nasty
+ //! behind the scenes. The second line states that mapping the composition
+ //! of two functions is the same as mapping the first function, and then
+ //! the second on the result. While the usual functor laws are usually
+ //! restricted to the above, this library includes other convenience
+ //! methods and they should satisfy the following equations.
+ //! Let `xs` be a Functor with tag `F(A)`,
+ //! \f$ f : A \to A \f$,
+ //! \f$ \mathrm{pred} : A \to \mathrm{Bool} \f$
+ //! for some `Logical` `Bool`, and `oldval`, `newval`, `value` objects
+ //! of tag `A`. Then,
+ //! @code
+ //! adjust(xs, value, f) == adjust_if(xs, equal.to(value), f)
+ //! adjust_if(xs, pred, f) == transform(xs, [](x){
+ //! if pred(x) then f(x) else x
+ //! })
+ //! replace_if(xs, pred, value) == adjust_if(xs, pred, always(value))
+ //! replace(xs, oldval, newval) == replace_if(xs, equal.to(oldval), newval)
+ //! fill(xs, value) == replace_if(xs, always(true), value)
+ //! @endcode
+ //! The default definition of the methods will satisfy these equations.
+ //!
+ //!
+ //! Concrete models
+ //! ---------------
+ //! `hana::lazy`, `hana::optional`, `hana::tuple`
+ //!
+ //!
+ //! Structure-preserving functions for Functors
+ //! -------------------------------------------
+ //! A mapping between two functors which also preserves the functor
+ //! laws is called a natural transformation (the term comes from
+ //! category theory). A natural transformation is a function `f`
+ //! from a functor `F` to a functor `G` such that for every other
+ //! function `g` with an appropriate signature and for every object
+ //! `xs` of tag `F(X)`,
+ //! @code
+ //! f(transform(xs, g)) == transform(f(xs), g)
+ //! @endcode
+ //!
+ //! There are several examples of such transformations, like `to<tuple_tag>`
+ //! when applied to an optional value. Indeed, for any function `g` and
+ //! `hana::optional` `opt`,
+ //! @code
+ //! to<tuple_tag>(transform(opt, g)) == transform(to<tuple_tag>(opt), g)
+ //! @endcode
+ //!
+ //! Of course, natural transformations are not limited to the `to<...>`
+ //! functions. However, note that any conversion function between Functors
+ //! should be natural for the behavior of the conversion to be intuitive.
+ //!
+ //!
+ //! [1]: http://en.wikipedia.org/wiki/Functor
+ //! [2]: https://wiki.haskell.org/Typeclassopedia#Functor
+ //! [3]: http://en.wikipedia.org/wiki/Category_theory
+ template <typename F>
+ struct Functor;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_FUNCTOR_HPP
diff --git a/boost/hana/fwd/concept/group.hpp b/boost/hana/fwd/concept/group.hpp
new file mode 100644
index 0000000000..a7ec238d54
--- /dev/null
+++ b/boost/hana/fwd/concept/group.hpp
@@ -0,0 +1,111 @@
+/*!
+@file
+Forward declares `boost::hana::Group`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_GROUP_HPP
+#define BOOST_HANA_FWD_CONCEPT_GROUP_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! @defgroup group-Group Group
+ //! The `Group` concept represents `Monoid`s where all objects have
+ //! an inverse w.r.t. the `Monoid`'s binary operation.
+ //!
+ //! A [Group][1] is an algebraic structure built on top of a `Monoid`
+ //! which adds the ability to invert the action of the `Monoid`'s binary
+ //! operation on any element of the set. Specifically, a `Group` is a
+ //! `Monoid` `(S, +)` such that every element `s` in `S` has an inverse
+ //! (say `s'`) which is such that
+ //! @code
+ //! s + s' == s' + s == identity of the Monoid
+ //! @endcode
+ //!
+ //! There are many examples of `Group`s, one of which would be the
+ //! additive `Monoid` on integers, where the inverse of any integer
+ //! `n` is the integer `-n`. The method names used here refer to
+ //! exactly this model.
+ //!
+ //!
+ //! Minimal complete definitions
+ //! ----------------------------
+ //! 1. `minus`\n
+ //! When `minus` is specified, the `negate` method is defaulted by setting
+ //! @code
+ //! negate(x) = minus(zero<G>(), x)
+ //! @endcode
+ //!
+ //! 2. `negate`\n
+ //! When `negate` is specified, the `minus` method is defaulted by setting
+ //! @code
+ //! minus(x, y) = plus(x, negate(y))
+ //! @endcode
+ //!
+ //!
+ //! Laws
+ //! ----
+ //! For all objects `x` of a `Group` `G`, the following laws must be
+ //! satisfied:
+ //! @code
+ //! plus(x, negate(x)) == zero<G>() // right inverse
+ //! plus(negate(x), x) == zero<G>() // left inverse
+ //! @endcode
+ //!
+ //!
+ //! Refined concept
+ //! ---------------
+ //! `Monoid`
+ //!
+ //!
+ //! Concrete models
+ //! ---------------
+ //! `hana::integral_constant`
+ //!
+ //!
+ //! Free model for non-boolean arithmetic data types
+ //! ------------------------------------------------
+ //! A data type `T` is arithmetic if `std::is_arithmetic<T>::%value` is
+ //! true. For a non-boolean arithmetic data type `T`, a model of `Group`
+ //! is automatically defined by setting
+ //! @code
+ //! minus(x, y) = (x - y)
+ //! negate(x) = -x
+ //! @endcode
+ //!
+ //! @note
+ //! The rationale for not providing a Group model for `bool` is the same
+ //! as for not providing a `Monoid` model.
+ //!
+ //!
+ //! Structure-preserving functions
+ //! ------------------------------
+ //! Let `A` and `B` be two `Group`s. A function `f : A -> B` is said to
+ //! be a [Group morphism][2] if it preserves the group structure between
+ //! `A` and `B`. Rigorously, for all objects `x, y` of data type `A`,
+ //! @code
+ //! f(plus(x, y)) == plus(f(x), f(y))
+ //! @endcode
+ //! Because of the `Group` structure, it is easy to prove that the
+ //! following will then also be satisfied:
+ //! @code
+ //! f(negate(x)) == negate(f(x))
+ //! f(zero<A>()) == zero<B>()
+ //! @endcode
+ //! Functions with these properties interact nicely with `Group`s, which
+ //! is why they are given such a special treatment.
+ //!
+ //!
+ //! [1]: http://en.wikipedia.org/wiki/Group_(mathematics)
+ //! [2]: http://en.wikipedia.org/wiki/Group_homomorphism
+ template <typename G>
+ struct Group;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_GROUP_HPP
diff --git a/boost/hana/fwd/concept/hashable.hpp b/boost/hana/fwd/concept/hashable.hpp
new file mode 100644
index 0000000000..2fc4977ba9
--- /dev/null
+++ b/boost/hana/fwd/concept/hashable.hpp
@@ -0,0 +1,68 @@
+/*!
+@file
+Forward declares `boost::hana::Hashable`.
+
+@copyright Louis Dionne 2016
+@copyright Jason Rice 2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_HASHABLE_HPP
+#define BOOST_HANA_FWD_CONCEPT_HASHABLE_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! @defgroup group-Hashable Hashable
+ //! The `Hashable` concept represents objects that can be normalized to
+ //! a type-level hash.
+ //!
+ //! In day to day programming, hashes are very important as a way to
+ //! efficiently lookup objects in maps. While the implementation of
+ //! maps is very different, the same idea of using hashes for efficient
+ //! lookup applies in metaprogramming. The `Hashable` concept represents
+ //! objects that can be summarized (possibly with loss of information) to
+ //! a type, in a way suitable for use in hash-based data structures. Of
+ //! course, in order for a hash to be well-behaved, it must obey some laws
+ //! that are explained below.
+ //!
+ //!
+ //! Minimal complete definition
+ //! ---------------------------
+ //! `hash`, satisfying the laws below
+ //!
+ //!
+ //! Laws
+ //! ----
+ //! First, `hana::hash` must return a `hana::type`. Furthermore, for any
+ //! two `Hashable` objects `x` and `y`, it must be the case that
+ //! @code
+ //! x == y implies hash(x) == hash(y)
+ //! @endcode
+ //!
+ //! where `==` denotes `hana::equal`. In other words, any two objects that
+ //! compare equal (with `hana::equal`) must also have the same hash.
+ //! However, the reverse is not true, and two different objects may have
+ //! the same hash. This situation of two different objects having the same
+ //! hash is called a _collision_.
+ //!
+ //!
+ //! Concrete models
+ //! ---------------
+ //! `hana::integral_constant`, `hana::type`, `hana::string`
+ //!
+ //!
+ //! Free model for `IntegralConstant`s
+ //! ----------------------------------
+ //! Any `IntegralConstant` is `Hashable`, by normalizing its value to a
+ //! `hana::integral_constant`. The type of the value held in the normalized
+ //! `integral_constant` is `unsigned long long` for unsigned integral
+ //! types, and `signed long long` for signed integral types.
+ template <typename T>
+ struct Hashable;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_HASHABLE_HPP
diff --git a/boost/hana/fwd/concept/integral_constant.hpp b/boost/hana/fwd/concept/integral_constant.hpp
new file mode 100644
index 0000000000..ba82c52931
--- /dev/null
+++ b/boost/hana/fwd/concept/integral_constant.hpp
@@ -0,0 +1,73 @@
+/*!
+@file
+Forward declares `boost::hana::IntegralConstant`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_INTEGRAL_CONSTANT_HPP
+#define BOOST_HANA_FWD_CONCEPT_INTEGRAL_CONSTANT_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! The `IntegralConstant` concept represents compile-time integral values.
+ //!
+ //! The `IntegralConstant` concept represents objects that hold a
+ //! `constexpr` value of an integral type. In other words, it describes
+ //! the essential functionality provided by `std::integral_constant`.
+ //! An `IntegralConstant` is also just a special kind of `Constant`
+ //! whose inner value is of an integral type.
+ //!
+ //!
+ //! Minimal complete definition
+ //! ---------------------------
+ //! The requirements for being an `IntegralConstant` are quite simple.
+ //! First, an `IntegralConstant` `C` must be a `Constant` such that
+ //! `Tag::value_type` is an integral type, where `Tag` is the tag of `C`.
+ //!
+ //! Secondly, `C` must have a nested `static constexpr` member named
+ //! `value`, such that the following code is valid:
+ //! @code
+ //! constexpr auto v = C::value;
+ //! @endcode
+ //! Because of the requirement that `Tag::value_type` be an integral type,
+ //! it follows that `C::value` must be an integral value.
+ //!
+ //! Finally, it is necessary to specialize the `IntegralConstant` template
+ //! in the `boost::hana` namespace to tell Hana that a type is a model
+ //! of `IntegralConstant`:
+ //! @code
+ //! namespace boost { namespace hana {
+ //! template <>
+ //! struct IntegralConstant<your_custom_tag> {
+ //! static constexpr bool value = true;
+ //! };
+ //! }}
+ //! @endcode
+ //!
+ //!
+ //! Refined concept
+ //! ---------------
+ //! 1. `Constant` (free implementation of `value`)\n
+ //! The `value` function required to be a `Constant` can be implemented
+ //! as follows for `IntegralConstant`s:
+ //! @code
+ //! value<C>() == C::value
+ //! @endcode
+ //! The `to` function must still be provided explicitly for the model
+ //! of `Constant` to be complete.
+ //!
+ //!
+ //! Concrete models
+ //! ---------------
+ //! `hana::integral_constant`
+ template <typename C>
+ struct IntegralConstant;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_INTEGRAL_CONSTANT_HPP
diff --git a/boost/hana/fwd/concept/iterable.hpp b/boost/hana/fwd/concept/iterable.hpp
new file mode 100644
index 0000000000..f406b2186b
--- /dev/null
+++ b/boost/hana/fwd/concept/iterable.hpp
@@ -0,0 +1,149 @@
+/*!
+@file
+Forward declares `boost::hana::Iterable`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_ITERABLE_HPP
+#define BOOST_HANA_FWD_CONCEPT_ITERABLE_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! @defgroup group-Iterable Iterable
+ //! The `Iterable` concept represents data structures supporting external
+ //! iteration.
+ //!
+ //! Intuitively, an `Iterable` can be seen as a kind of container whose
+ //! elements can be pulled out one at a time. An `Iterable` also provides
+ //! a way to know when the _container_ is empty, i.e. when there are no
+ //! more elements to pull out.
+ //!
+ //! Whereas `Foldable` represents data structures supporting internal
+ //! iteration with the ability to accumulate a result, the `Iterable`
+ //! concept allows inverting the control of the iteration. This is more
+ //! flexible than `Foldable`, since it allows iterating over only some
+ //! part of the structure. This, in turn, allows `Iterable` to work on
+ //! infinite structures, while trying to fold such a structure would
+ //! never finish.
+ //!
+ //!
+ //! Minimal complete definition
+ //! ---------------------------
+ //! `at`, `drop_front` and `is_empty`
+ //!
+ //!
+ //! @anchor Iterable-lin
+ //! The linearization of an `Iterable`
+ //! ----------------------------------
+ //! Intuitively, for an `Iterable` structure `xs`, the _linearization_ of
+ //! `xs` is the sequence of all the elements in `xs` as if they had been
+ //! put in a (possibly infinite) list:
+ //! @code
+ //! linearization(xs) = [x1, x2, x3, ...]
+ //! @endcode
+ //!
+ //! The `n`th element of the linearization of an `Iterable` can be
+ //! accessed with the `at` function. In other words, `at(xs, n) == xn`.
+ //!
+ //! Note that this notion is precisely the extension of the [linearization]
+ //! (@ref Foldable-lin) notion of `Foldable`s to the infinite case. This
+ //! notion is useful for expressing various properties of `Iterable`s,
+ //! and is used for that elsewhere in the documentation.
+ //!
+ //!
+ //! Compile-time `Iterable`s
+ //! ------------------------
+ //! A _compile-time_ `Iterable` is an `Iterable` for which `is_empty`
+ //! returns a compile-time `Logical`. These structures allow iteration
+ //! to be done at compile-time, in the sense that the "loop" doing the
+ //! iteration can be unrolled because the total length of the structure
+ //! is kown at compile-time.
+ //!
+ //! In particular, note that being a compile-time `Iterable` has nothing
+ //! to do with being finite or infinite. For example, it would be possible
+ //! to create a sequence representing the Pythagorean triples as
+ //! `integral_constant`s. Such a sequence would be infinite, but iteration
+ //! on the sequence would still be done at compile-time. However, if one
+ //! tried to iterate over _all_ the elements of the sequence, the compiler
+ //! would loop indefinitely, in contrast to your program looping
+ //! indefinitely if the sequence was a runtime one.
+ //!
+ //! __In the current version of the library, only compile-time `Iterable`s
+ //! are supported.__ While it would be possible in theory to support
+ //! runtime `Iterable`s, doing it efficiently is the subject of some
+ //! research. In particular, follow [this issue][1] for the current
+ //! status of runtime `Iterable`s.
+ //!
+ //!
+ //! Laws
+ //! ----
+ //! First, we require the equality of two `Iterable`s to be related to the
+ //! equality of the elements in their linearizations. More specifically,
+ //! if `xs` and `ys` are two `Iterable`s of data type `It`, then
+ //! @code
+ //! xs == ys => at(xs, i) == at(ys, i) for all i
+ //! @endcode
+ //!
+ //! This conveys that two `Iterable`s must have the same linearization
+ //! in order to be considered equal.
+ //!
+ //! Secondly, since every `Iterable` is also a `Searchable`, we require
+ //! the models of `Iterable` and `Searchable` to be consistent. This is
+ //! made precise by the following laws. For any `Iterable` `xs` with a
+ //! linearization of `[x1, x2, x3, ...]`,
+ //! @code
+ //! any_of(xs, equal.to(z)) <=> xi == z
+ //! @endcode
+ //! for some _finite_ index `i`. Furthermore,
+ //! @code
+ //! find_if(xs, pred) == just(the first xi such that pred(xi) is satisfied)
+ //! @endcode
+ //! or `nothing` if no such `xi` exists.
+ //!
+ //!
+ //! Refined concepts
+ //! ----------------
+ //! 1. `Searchable` (free model)\n
+ //! Any `Iterable` gives rise to a model of `Searchable`, where the keys
+ //! and the values are both the elements in the structure. Searching for
+ //! a key is just doing a linear search through the elements of the
+ //! structure.
+ //! @include example/iterable/searchable.cpp
+ //!
+ //! 2. `Foldable` for finite `Iterable`s\n
+ //! Every finite `Iterable` gives rise to a model of `Foldable`. For
+ //! these models to be consistent, we require the models of both `Foldable`
+ //! and `Iterable` to have the same linearization.
+ //!
+ //! @note
+ //! As explained above, `Iterable`s are also `Searchable`s and their
+ //! models have to be consistent. By the laws presented here, it also
+ //! means that the `Foldable` model for finite `Iterable`s has to be
+ //! consistent with the `Searchable` model.
+ //!
+ //! For convenience, finite `Iterable`s must only provide a definition of
+ //! `length` to model the `Foldable` concept; defining the more powerful
+ //! `unpack` or `fold_left` is not necessary (but still possible). The
+ //! default implementation of `unpack` derived from `Iterable` + `length`
+ //! uses the fact that `at(xs, i)` denotes the `i`th element of `xs`'s
+ //! linearization, and that the linearization of a finite `Iterable` must
+ //! be the same as its linearization as a `Foldable`.
+ //!
+ //!
+ //! Concrete models
+ //! ---------------
+ //! `hana::tuple`, `hana::string`, `hana::range`
+ //!
+ //!
+ //! [1]: https://github.com/boostorg/hana/issues/40
+ template <typename It>
+ struct Iterable;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_ITERABLE_HPP
diff --git a/boost/hana/fwd/concept/logical.hpp b/boost/hana/fwd/concept/logical.hpp
new file mode 100644
index 0000000000..7eecf9d857
--- /dev/null
+++ b/boost/hana/fwd/concept/logical.hpp
@@ -0,0 +1,166 @@
+/*!
+@file
+Forward declares `boost::hana::Logical`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_LOGICAL_HPP
+#define BOOST_HANA_FWD_CONCEPT_LOGICAL_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! @defgroup group-Logical Logical
+ //! The `Logical` concept represents types with a truth value.
+ //!
+ //! Intuitively, a `Logical` is just a `bool`, or something that can act
+ //! like one. However, in the context of programming with heterogeneous
+ //! objects, it becomes extremely important to distinguish between those
+ //! objects whose truth value is known at compile-time, and those whose
+ //! truth value is only known at runtime. The reason why this is so
+ //! important is because it is possible to branch at compile-time on
+ //! a condition whose truth value is known at compile-time, and hence
+ //! the return type of the enclosing function can depend on that truth
+ //! value. However, if the truth value is only known at runtime, then
+ //! the compiler has to compile both branches (because any or both of
+ //! them may end up being used), which creates the additional requirement
+ //! that both branches must evaluate to the same type.
+ //!
+ //! More specifically, `Logical` (almost) represents a [boolean algebra][1],
+ //! which is a mathematical structure encoding the usual properties that
+ //! allow us to reason with `bool`. The exact properties that must be
+ //! satisfied by any model of `Logical` are rigorously stated in the laws
+ //! below.
+ //!
+ //!
+ //! Truth, falsity and logical equivalence
+ //! --------------------------------------
+ //! A `Logical` `x` is said to be _true-valued_, or sometimes also just
+ //! _true_ as an abuse of notation, if
+ //! @code
+ //! if_(x, true, false) == true
+ //! @endcode
+ //!
+ //! Similarly, `x` is _false-valued_, or sometimes just _false_, if
+ //! @code
+ //! if_(x, true, false) == false
+ //! @endcode
+ //!
+ //! This provides a standard way of converting any `Logical` to a straight
+ //! `bool`. The notion of truth value suggests another definition, which
+ //! is that of logical equivalence. We will say that two `Logical`s `x`
+ //! and `y` are _logically equivalent_ if they have the same truth value.
+ //! To denote that some expressions `p` and `q` of a Logical data type are
+ //! logically equivalent, we will sometimes also write
+ //! @code
+ //! p if and only if q
+ //! @endcode
+ //! which is very common in mathematics. The intuition behind this notation
+ //! is that whenever `p` is true-valued, then `q` should be; but when `p`
+ //! is false-valued, then `q` should be too. Hence, `p` should be
+ //! true-valued when (and only when) `q` is true-valued.
+ //!
+ //!
+ //! Minimal complete definition
+ //! ---------------------------
+ //! `eval_if`, `not_` and `while_`
+ //!
+ //! All the other functions can be defined in those terms:
+ //! @code
+ //! if_(cond, x, y) = eval_if(cond, lazy(x), lazy(y))
+ //! and_(x, y) = if_(x, y, x)
+ //! or_(x, y) = if_(x, x, y)
+ //! etc...
+ //! @endcode
+ //!
+ //!
+ //! Laws
+ //! ----
+ //! As outlined above, the `Logical` concept almost represents a boolean
+ //! algebra. The rationale for this laxity is to allow things like integers
+ //! to act like `Logical`s, which is aligned with C++, even though they do
+ //! not form a boolean algebra. Even though we depart from the usual
+ //! axiomatization of boolean algebras, we have found through experience
+ //! that the definition of a Logical given here is largely compatible with
+ //! intuition.
+ //!
+ //! The following laws must be satisfied for any data type `L` modeling
+ //! the `Logical` concept. Let `a`, `b` and `c` be objects of a `Logical`
+ //! data type, and let `t` and `f` be arbitrary _true-valued_ and
+ //! _false-valued_ `Logical`s of that data type, respectively. Then,
+ //! @code
+ //! // associativity
+ //! or_(a, or_(b, c)) == or_(or_(a, b), c)
+ //! and_(a, and_(b, c)) == and_(and_(a, b), c)
+ //!
+ //! // equivalence through commutativity
+ //! or_(a, b) if and only if or_(b, a)
+ //! and_(a, b) if and only if and_(b, a)
+ //!
+ //! // absorption
+ //! or_(a, and_(a, b)) == a
+ //! and_(a, or_(a, b)) == a
+ //!
+ //! // left identity
+ //! or_(a, f) == a
+ //! and_(a, t) == a
+ //!
+ //! // distributivity
+ //! or_(a, and_(b, c)) == and_(or_(a, b), or_(a, c))
+ //! and_(a, or_(b, c)) == or_(and_(a, b), and_(a, c))
+ //!
+ //! // complements
+ //! or_(a, not_(a)) is true-valued
+ //! and_(a, not_(a)) is false-valued
+ //! @endcode
+ //!
+ //! > #### Why is the above not a boolean algebra?
+ //! > If you look closely, you will find that we depart from the usual
+ //! > boolean algebras because:
+ //! > 1. we do not require the elements representing truth and falsity to
+ //! > be unique
+ //! > 2. we do not enforce commutativity of the `and_` and `or_` operations
+ //! > 3. because we do not enforce commutativity, the identity laws become
+ //! > left-identity laws
+ //!
+ //!
+ //! Concrete models
+ //! ---------------
+ //! `hana::integral_constant`
+ //!
+ //!
+ //! Free model for arithmetic data types
+ //! ------------------------------------
+ //! A data type `T` is arithmetic if `std::is_arithmetic<T>::%value` is
+ //! true. For an arithmetic data type `T`, a model of `Logical` is
+ //! provided automatically by using the result of the builtin implicit
+ //! conversion to `bool` as a truth value. Specifically, the minimal
+ //! complete definition for those data types is
+ //! @code
+ //! eval_if(cond, then, else_) = cond ? then(id) : else(id)
+ //! not_(cond) = static_cast<T>(cond ? false : true)
+ //! while_(pred, state, f) = equivalent to a normal while loop
+ //! @endcode
+ //!
+ //! > #### Rationale for not providing a model for all contextually convertible to bool data types
+ //! > The `not_` method can not be implemented in a meaningful way for all
+ //! > of those types. For example, one can not cast a pointer type `T*`
+ //! > to bool and then back again to `T*` in a meaningful way. With an
+ //! > arithmetic type `T`, however, it is possible to cast from `T` to
+ //! > bool and then to `T` again; the result will be `0` or `1` depending
+ //! > on the truth value. If you want to use a pointer type or something
+ //! > similar in a conditional, it is suggested to explicitly convert it
+ //! > to bool by using `to<bool>`.
+ //!
+ //!
+ //! [1]: http://en.wikipedia.org/wiki/Boolean_algebra_(structure)
+ template <typename L>
+ struct Logical;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_LOGICAL_HPP
diff --git a/boost/hana/fwd/concept/metafunction.hpp b/boost/hana/fwd/concept/metafunction.hpp
new file mode 100644
index 0000000000..00efc049e3
--- /dev/null
+++ b/boost/hana/fwd/concept/metafunction.hpp
@@ -0,0 +1,99 @@
+/*!
+@file
+Forward declares `boost::hana::Metafunction`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_METAFUNCTION_HPP
+#define BOOST_HANA_FWD_CONCEPT_METAFUNCTION_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! @defgroup group-Metafunction Metafunction
+ //! A `Metafunction` is a function that takes `hana::type`s as inputs and
+ //! returns a `hana::type` as output.
+ //!
+ //! A `Metafunction` is an object satisfying the [FunctionObject][1]
+ //! concept, but with additional requirements. First, it must be possible
+ //! to apply a `Metafunction` to arguments whose tag is `type_tag`, and
+ //! the result of such an application must be an object whose tag is also
+ //! `type_tag`. Note that `hana::type` and `hana::basic_type` are the
+ //! only such types.
+ //!
+ //! Secondly, a `Metafunction` must provide a nested `::%apply` template
+ //! which allows performing the same type-level computation as is done by
+ //! the call operator. In Boost.MPL parlance, a `Metafunction` `F` is
+ //! hence a [MetafunctionClass][2] in addition to being a `FunctionObject`.
+ //! Rigorously, the following must be satisfied by any object `f` of type
+ //! `F` which is a `Metafunction`, and for arbitrary types `T...`:
+ //! @code
+ //! f(hana::type_c<T>...) == hana::type_c<F::apply<T...>::type>
+ //! @endcode
+ //!
+ //! Thirdly, to ease the inter-operation of values and types,
+ //! `Metafunction`s must also allow being called with arguments that
+ //! are not `hana::type`s. In that case, the result is equivalent to
+ //! calling the metafunction on the types of the arguments. Rigorously,
+ //! this means that for arbitrary objects `x...`,
+ //! @code
+ //! f(x...) == f(hana::type_c<decltype(x)>...)
+ //! @endcode
+ //!
+ //!
+ //! Minimal complete definition
+ //! ---------------------------
+ //! The `Metafunction` concept does not have a minimal complete definition
+ //! in terms of tag-dispatched methods. Instead, the syntactic requirements
+ //! documented above should be satisfied, and the `Metafunction` struct
+ //! should be specialized explicitly in Hana's namespace.
+ //!
+ //!
+ //! Concrete models
+ //! ---------------
+ //! `hana::metafunction`, `hana::metafunction_class`, `hana::template_`
+ //!
+ //!
+ //! Rationale: Why aren't `Metafunction`s `Comparable`?
+ //! ---------------------------------------------------
+ //! When seeing `hana::template_`, a question that naturally arises is
+ //! whether `Metafunction`s should be made `Comparable`. Indeed, it
+ //! would seem to make sense to compare two templates `F` and `G` with
+ //! `template_<F> == template_<G>`. However, in the case where `F` and/or
+ //! `G` are alias templates, it makes sense to talk about two types of
+ //! comparisons. The first one is _shallow_ comparison, and it determines
+ //! that two alias templates are equal if they are the same alias
+ //! template. The second one is _deep_ comparison, and it determines
+ //! that two template aliases are equal if they alias the same type for
+ //! any template argument. For example, given `F` and `G` defined as
+ //! @code
+ //! template <typename T>
+ //! using F = void;
+ //!
+ //! template <typename T>
+ //! using G = void;
+ //! @endcode
+ //!
+ //! shallow comparison would determine that `F` and `G` are different
+ //! because they are two different template aliases, while deep comparison
+ //! would determine that `F` and `G` are equal because they always
+ //! expand to the same type, `void`. Unfortunately, deep comparison is
+ //! impossible to implement because one would have to check `F` and `G`
+ //! on all possible types. On the other hand, shallow comparison is not
+ //! satisfactory because `Metafunction`s are nothing but functions on
+ //! `type`s, and the equality of two functions is normally defined with
+ //! deep comparison. Hence, we adopt a conservative stance and avoid
+ //! providing comparison for `Metafunction`s.
+ //!
+ //! [1]: http://en.cppreference.com/w/cpp/concept/FunctionObject
+ //! [2]: http://www.boost.org/doc/libs/release/libs/mpl/doc/refmanual/metafunction-class.html
+ template <typename F>
+ struct Metafunction;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_METAFUNCTION_HPP
diff --git a/boost/hana/fwd/concept/monad.hpp b/boost/hana/fwd/concept/monad.hpp
new file mode 100644
index 0000000000..1dee78331d
--- /dev/null
+++ b/boost/hana/fwd/concept/monad.hpp
@@ -0,0 +1,198 @@
+/*!
+@file
+Forward declares `boost::hana::Monad`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_MONAD_HPP
+#define BOOST_HANA_FWD_CONCEPT_MONAD_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! @defgroup group-Monad Monad
+ //! The `Monad` concept represents `Applicative`s with the ability to
+ //! flatten nested levels of structure.
+ //!
+ //! Historically, Monads are a construction coming from category theory,
+ //! an abstract branch of mathematics. The functional programming
+ //! community eventually discovered how Monads could be used to
+ //! formalize several useful things like side effects, which led
+ //! to the wide adoption of Monads in that community. However, even
+ //! in a multi-paradigm language like C++, there are several constructs
+ //! which turn out to be Monads, like `std::optional`, `std::vector` and
+ //! others.
+ //!
+ //! Everybody tries to introduce `Monad`s with a different analogy, and
+ //! most people fail. This is called the [Monad tutorial fallacy][1]. We
+ //! will try to avoid this trap by not presenting a specific intuition,
+ //! and we will instead present what monads are mathematically.
+ //! For specific intuitions, we will let readers who are new to this
+ //! concept read one of the many excellent tutorials available online.
+ //! Understanding Monads might take time at first, but once you get it,
+ //! a lot of patterns will become obvious Monads; this enlightening will
+ //! be your reward for the hard work.
+ //!
+ //! There are different ways of defining a Monad; Haskell uses a function
+ //! called `bind` (`>>=`) and another one called `return` (it has nothing
+ //! to do with C++'s `return` statement). They then introduce relationships
+ //! that must be satisfied for a type to be a Monad with those functions.
+ //! Mathematicians sometimes use a function called `join` and another one
+ //! called `unit`, or they also sometimes use other category theoretic
+ //! constructions like functor adjunctions and the Kleisli category.
+ //!
+ //! This library uses a composite approach. First, we use the `flatten`
+ //! function (equivalent to `join`) along with the `lift` function from
+ //! `Applicative` (equivalent to `unit`) to introduce the notion of
+ //! monadic function composition. We then write the properties that must
+ //! be satisfied by a Monad using this monadic composition operator,
+ //! because we feel it shows the link between Monads and Monoids more
+ //! clearly than other approaches.
+ //!
+ //! Roughly speaking, we will say that a `Monad` is an `Applicative` which
+ //! also defines a way to compose functions returning a monadic result,
+ //! as opposed to only being able to compose functions returning a normal
+ //! result. We will then ask for this composition to be associative and to
+ //! have a neutral element, just like normal function composition. For
+ //! usual composition, the neutral element is the identity function `id`.
+ //! For monadic composition, the neutral element is the `lift` function
+ //! defined by `Applicative`. This construction is made clearer in the
+ //! laws below.
+ //!
+ //! @note
+ //! Monads are known to be a big chunk to swallow. However, it is out of
+ //! the scope of this documentation to provide a full-blown explanation
+ //! of the concept. The [Typeclassopedia][2] is a nice Haskell-oriented
+ //! resource where more information about Monads can be found.
+ //!
+ //!
+ //! Minimal complete definitions
+ //! ----------------------------
+ //! First, a `Monad` must be both a `Functor` and an `Applicative`.
+ //! Also, an implementation of `flatten` or `chain` satisfying the
+ //! laws below for monadic composition must be provided.
+ //!
+ //! @note
+ //! The `ap` method for `Applicatives` may be derived from the minimal
+ //! complete definition of `Monad` and `Functor`; see below for more
+ //! information.
+ //!
+ //!
+ //! Laws
+ //! ----
+ //! To simplify writing the laws, we use the comparison between functions.
+ //! For two functions `f` and `g`, we define
+ //! @code
+ //! f == g if and only if f(x) == g(x) for all x
+ //! @endcode
+ //!
+ //! With the usual composition of functions, we are given two functions
+ //! @f$ f : A \to B @f$ and @f$ g : B \to C @f$, and we must produce a
+ //! new function @f$ compose(g, f) : A \to C @f$. This composition of
+ //! functions is associative, which means that
+ //! @code
+ //! compose(h, compose(g, f)) == compose(compose(h, g), f)
+ //! @endcode
+ //!
+ //! Also, this composition has an identity element, which is the identity
+ //! function. This simply means that
+ //! @code
+ //! compose(f, id) == compose(id, f) == f
+ //! @endcode
+ //!
+ //! This is probably nothing new if you are reading the `Monad` laws.
+ //! Now, we can observe that the above is equivalent to saying that
+ //! functions with the composition operator form a `Monoid`, where the
+ //! neutral element is the identity function.
+ //!
+ //! Given an `Applicative` `F`, what if we wanted to compose two functions
+ //! @f$ f : A \to F(B) @f$ and @f$ g : B \to F(C) @f$? When the
+ //! `Applicative` `F` is also a `Monad`, such functions taking normal
+ //! values but returning monadic values are called _monadic functions_.
+ //! To compose them, we obviously can't use normal function composition,
+ //! since the domains and codomains of `f` and `g` do not match properly.
+ //! Instead, we'll need a new operator -- let's call it `monadic_compose`:
+ //! @f[
+ //! \mathtt{monadic\_compose} :
+ //! (B \to F(C)) \times (A \to F(B)) \to (A \to F(C))
+ //! @f]
+ //!
+ //! How could we go about implementing this function? Well, since we know
+ //! `F` is an `Applicative`, the only functions we have are `transform`
+ //! (from `Functor`), and `lift` and `ap` (from `Applicative`). Hence,
+ //! the only thing we can do at this point while respecting the signatures
+ //! of `f` and `g` is to set (for `x` of type `A`)
+ //! @code
+ //! monadic_compose(g, f)(x) = transform(f(x), g)
+ //! @endcode
+ //!
+ //! Indeed, `f(x)` is of type `F(B)`, so we can map `g` (which takes `B`'s)
+ //! on it. Doing so will leave us with a result of type `F(F(C))`, but what
+ //! we wanted was a result of type `F(C)` to respect the signature of
+ //! `monadic_compose`. If we had a joker of type @f$ F(F(C)) \to F(C) @f$,
+ //! we could simply set
+ //! @code
+ //! monadic_compose(g, f)(x) = joker(transform(f(x), g))
+ //! @endcode
+ //!
+ //! and we would be happy. It turns out that `flatten` is precisely this
+ //! joker. Now, we'll want our joker to satisfy some properties to make
+ //! sure this composition is associative, just like our normal composition
+ //! was. These properties are slightly cumbersome to specify, so we won't
+ //! do it here. Also, we'll need some kind of neutral element for the
+ //! composition. This neutral element can't be the usual identity function,
+ //! because it does not have the right type: our neutral element needs to
+ //! be a function of type @f$ X \to F(X) @f$ but the identity function has
+ //! type @f$ X \to X @f$. It is now the right time to observe that `lift`
+ //! from `Applicative` has exactly the right signature, and so we'll take
+ //! this for our neutral element.
+ //!
+ //! We are now ready to formulate the `Monad` laws using this composition
+ //! operator. For a `Monad` `M` and functions @f$ f : A \to M(B) @f$,
+ //! @f$ g : B \to M(C) @f$ and @f$ h : C \to M(D) @f$, the following
+ //! must be satisfied:
+ //! @code
+ //! // associativity
+ //! monadic_compose(h, monadic_compose(g, f)) == monadic_compose(monadic_compose(h, g), f)
+ //!
+ //! // right identity
+ //! monadic_compose(f, lift<M(A)>) == f
+ //!
+ //! // left identity
+ //! monadic_compose(lift<M(B)>, f) == f
+ //! @endcode
+ //!
+ //! which is to say that `M` along with monadic composition is a Monoid
+ //! where the neutral element is `lift`.
+ //!
+ //!
+ //! Refined concepts
+ //! ----------------
+ //! 1. `Functor`
+ //! 2. `Applicative` (free implementation of `ap`)\n
+ //! When the minimal complete definition for `Monad` and `Functor` are
+ //! both satisfied, it is possible to implement `ap` by setting
+ //! @code
+ //! ap(fs, xs) = chain(fs, [](auto f) {
+ //! return transform(xs, f);
+ //! })
+ //! @endcode
+ //!
+ //!
+ //! Concrete models
+ //! ---------------
+ //! `hana::lazy`, `hana::optional`, `hana::tuple`
+ //!
+ //!
+ //! [1]: https://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy/
+ //! [2]: https://wiki.haskell.org/Typeclassopedia#Monad
+ template <typename M>
+ struct Monad;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_MONAD_HPP
diff --git a/boost/hana/fwd/concept/monad_plus.hpp b/boost/hana/fwd/concept/monad_plus.hpp
new file mode 100644
index 0000000000..a7ac03c4d3
--- /dev/null
+++ b/boost/hana/fwd/concept/monad_plus.hpp
@@ -0,0 +1,89 @@
+/*!
+@file
+Forward declares `boost::hana::MonadPlus`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_MONAD_PLUS_HPP
+#define BOOST_HANA_FWD_CONCEPT_MONAD_PLUS_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! @defgroup group-MonadPlus MonadPlus
+ //! The `MonadPlus` concept represents Monads with a monoidal structure.
+ //!
+ //! Intuitively, whereas a Monad can be seen as some kind of container
+ //! or context, a MonadPlus can be seen as a container or a context that
+ //! can be concatenated with other containers or contexts. There must
+ //! also be an identity element for this combining operation. For example,
+ //! a tuple is a MonadPlus, because tuples can be concatenated and the
+ //! empty tuple would act as an identity for concatenation. How is this
+ //! different from a Monad which is also a Monoid? The answer is that the
+ //! monoidal structure on a MonadPlus must _not_ depend of the contents
+ //! of the structure; it must not require the contents to be a Monoid
+ //! in order to work.
+ //!
+ //! While sequences are not the only possible model for MonadPlus, the
+ //! method names used here refer to the MonadPlus of sequences under
+ //! concatenation. Several useful functions generalizing operations on
+ //! sequences are included with this concept, like `append`, `prepend`
+ //! and `filter`.
+ //!
+ //! @note
+ //! This documentation does not go into much details about the nature
+ //! of the MonadPlus concept. However, there is a nice Haskell-oriented
+ //! [WikiBook][1] going into further details.
+ //!
+ //!
+ //! Minimal complete definition
+ //! ---------------------------
+ //! `concat` and `empty`
+ //!
+ //!
+ //! Laws
+ //! ----
+ //! First, a MonadPlus is required to have a monoidal structure. Hence, it
+ //! is no surprise that for any MonadPlus `M`, we require `M(T)` to be a
+ //! valid monoid. However, we do not enforce that `M(T)` actually models
+ //! the Monoid concept provided by Hana. Further, for all objects `a, b, c`
+ //! of data type `M(T)`,
+ //! @code
+ //! // identity
+ //! concat(empty<M(T)>(), a) == a
+ //! concat(a, empty<M(T)>()) == a
+ //!
+ //! // associativity
+ //! concat(a, concat(b, c)) == concat(concat(a, b), c)
+ //! @endcode
+ //!
+ //! Secondly, a MonadPlus is also required to obey the following laws,
+ //! which represent the fact that `empty<M(T)>()` must be some kind of
+ //! absorbing element for the `chain` operation. For all objects `a` of
+ //! data type `M(T)` and functions @f$ f : T \to M(U) @f$,
+ //! @code
+ //! chain(empty<M(T)>(), f) == empty<M(U)>()
+ //! chain(a, always(empty<M(T)>())) == empty<M(U)>()
+ //! @endcode
+ //!
+ //!
+ //! Refined concepts
+ //! ----------------
+ //! `Functor`, `Applicative` and `Monad`
+ //!
+ //!
+ //! Concrete models
+ //! ---------------
+ //! `hana::optional`, `hana::tuple`
+ //!
+ //! [1]: https://en.wikibooks.org/wiki/Haskell/MonadPlus
+ template <typename M>
+ struct MonadPlus;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_MONAD_PLUS_HPP
diff --git a/boost/hana/fwd/concept/monoid.hpp b/boost/hana/fwd/concept/monoid.hpp
new file mode 100644
index 0000000000..5486d3d1d8
--- /dev/null
+++ b/boost/hana/fwd/concept/monoid.hpp
@@ -0,0 +1,101 @@
+/*!
+@file
+Forward declares `boost::hana::Monoid`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_MONOID_HPP
+#define BOOST_HANA_FWD_CONCEPT_MONOID_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! @defgroup group-Monoid Monoid
+ //! The `Monoid` concept represents data types with an associative
+ //! binary operation that has an identity.
+ //!
+ //! Specifically, a [Monoid][1] is a basic algebraic structure typically
+ //! used in mathematics to construct more complex algebraic structures
+ //! like `Group`s, `Ring`s and so on. They are useful in several contexts,
+ //! notably to define the properties of numbers in a granular way. At its
+ //! core, a `Monoid` is a set `S` of objects along with a binary operation
+ //! (let's say `+`) that is associative and that has an identity in `S`.
+ //! There are many examples of `Monoid`s:
+ //! - strings with concatenation and the empty string as the identity
+ //! - integers with addition and `0` as the identity
+ //! - integers with multiplication and `1` as the identity
+ //! - many others...
+ //!
+ //! As you can see with the integers, there are some sets that can be
+ //! viewed as a monoid in more than one way, depending on the choice
+ //! of the binary operation and identity. The method names used here
+ //! refer to the monoid of integers under addition; `plus` is the binary
+ //! operation and `zero` is the identity element of that operation.
+ //!
+ //!
+ //! Minimal complete definition
+ //! ---------------------------
+ //! `plus` and `zero` satisfying the laws
+ //!
+ //!
+ //! Laws
+ //! ----
+ //! For all objects `x`, `y` and `z` of a `Monoid` `M`, the following
+ //! laws must be satisfied:
+ //! @code
+ //! plus(zero<M>(), x) == x // left zero
+ //! plus(x, zero<M>()) == x // right zero
+ //! plus(x, plus(y, z)) == plus(plus(x, y), z) // associativity
+ //! @endcode
+ //!
+ //!
+ //! Concrete models
+ //! ---------------
+ //! `hana::integral_constant`
+ //!
+ //!
+ //! Free model for non-boolean arithmetic data types
+ //! ------------------------------------------------
+ //! A data type `T` is arithmetic if `std::is_arithmetic<T>::%value` is
+ //! true. For a non-boolean arithmetic data type `T`, a model of `Monoid`
+ //! is automatically defined by setting
+ //! @code
+ //! plus(x, y) = (x + y)
+ //! zero<T>() = static_cast<T>(0)
+ //! @endcode
+ //!
+ //! > #### Rationale for not making `bool` a `Monoid` by default
+ //! > First, it makes no sense whatsoever to define an additive `Monoid`
+ //! > over the `bool` type. Also, it could make sense to define a `Monoid`
+ //! > with logical conjunction or disjunction. However, C++ allows `bool`s
+ //! > to be added, and the method names of this concept really suggest
+ //! > addition. In line with the principle of least surprise, no model
+ //! > is provided by default.
+ //!
+ //!
+ //! Structure-preserving functions
+ //! ------------------------------
+ //! Let `A` and `B` be two `Monoid`s. A function `f : A -> B` is said
+ //! to be a [Monoid morphism][2] if it preserves the monoidal structure
+ //! between `A` and `B`. Rigorously, for all objects `x, y` of data
+ //! type `A`,
+ //! @code
+ //! f(plus(x, y)) == plus(f(x), f(y))
+ //! f(zero<A>()) == zero<B>()
+ //! @endcode
+ //! Functions with these properties interact nicely with `Monoid`s, which
+ //! is why they are given such a special treatment.
+ //!
+ //!
+ //! [1]: http://en.wikipedia.org/wiki/Monoid
+ //! [2]: http://en.wikipedia.org/wiki/Monoid#Monoid_homomorphisms
+ template <typename M>
+ struct Monoid;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_MONOID_HPP
diff --git a/boost/hana/fwd/concept/orderable.hpp b/boost/hana/fwd/concept/orderable.hpp
new file mode 100644
index 0000000000..ed381de94a
--- /dev/null
+++ b/boost/hana/fwd/concept/orderable.hpp
@@ -0,0 +1,187 @@
+/*!
+@file
+Forward declares `boost::hana::Orderable`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_ORDERABLE_HPP
+#define BOOST_HANA_FWD_CONCEPT_ORDERABLE_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! @defgroup group-Orderable Orderable
+ //! The `Orderable` concept represents totally ordered data types.
+ //!
+ //! Intuitively, `Orderable` objects must define a binary predicate named
+ //! `less` returning whether the first argument is to be considered less
+ //! than the second argument. The word "total" means that _distinct_
+ //! objects must always be ordered; if `a` and `b` are not equal, then
+ //! exactly one of `less(a, b)` and `less(b, a)` must be true. This is
+ //! a contrast with weaker kinds of orders that would allow some objects
+ //! to be incomparable (neither less than nor greater than). Also note
+ //! that a non-strict total order may always be obtained from a strict
+ //! total order (and vice-versa) by setting
+ //! @code
+ //! a <= b = !(b < a)
+ //! a < b = !(b <= a)
+ //! @endcode
+ //! The non-strict version is used in the description of the laws because
+ //! it makes them easier to parse for humans, but they could be formulated
+ //! equivalently using the strict order.
+ //!
+ //!
+ //! Minimal complete definition
+ //! ---------------------------
+ //! `less`
+ //!
+ //! When `less` is defined, the other methods are defined from it using
+ //! the same definition as mandated in the laws below.
+ //!
+ //!
+ //! Laws
+ //! ----
+ //! Rigorously speaking, a [total order][1] `<=` on a set `S` is a binary
+ //! predicate @f$ <= \;: S \times S \to bool @f$ such that for all
+ //! `a`, `b`, `c` in `S`,
+ //! @code
+ //! if a <= b and b <= a then a == b // Antisymmetry
+ //! if a <= b and b <= c then a <= c // Transitivity
+ //! either a <= b or b <= a // Totality
+ //! @endcode
+ //! Additionally, the `less`, `greater` and `greater_equal` methods should
+ //! have the following intuitive meanings:
+ //! @code
+ //! a < b if and only if !(b <= a)
+ //! a > b if and only if b < a
+ //! a >= b if and only if !(a < b)
+ //! @endcode
+ //!
+ //!
+ //! Refined concept
+ //! ---------------
+ //! 1. `Comparable` (free model)\n
+ //! Since `Orderable` requires `less_equal` to be a total order, a model
+ //! of `Comparable` may always be obtained by setting
+ //! @code
+ //! equal(x, y) = less_equal(x, y) && less_equal(y, x)
+ //! @endcode
+ //!
+ //!
+ //! Concrete models
+ //! ---------------
+ //! `hana::integral_constant`, `hana::optional`, `hana::pair`,
+ //! `hana::string`, `hana::tuple`
+ //!
+ //!
+ //! Free model for `LessThanComparable` data types
+ //! ----------------------------------------------
+ //! Two data types `T` and `U` that model the cross-type version of the
+ //! usual [LessThanComparable][2] C++ concept are automatically a model
+ //! of `Orderable` by setting
+ //! @code
+ //! less(x, y) = (x < y)
+ //! @endcode
+ //! The cross-type version of the LessThanComparable concept is analogous
+ //! to the cross-type version of the EqualityComparable concept presented
+ //! in [N3351][3], which is compatible with the usual single type
+ //! definition.
+ //! However, note that the LessThanComparable concept only requires `<`
+ //! to be a [strict weak ordering][4], which is a weaker requirement
+ //! than being a total order. Hence, if `less` is used with objects
+ //! of a LessThanComparable data type that do not define a total order,
+ //! some algorithms may have an unexpected behavior. It is the author's
+ //! opinion that defining `operator<` as a non-total order is a bad idea,
+ //! but this is debatable and so the design choice of providing a model
+ //! for LessThanComparable data types is open to debate. Waiting for
+ //! some user input.
+ //!
+ //!
+ //! Order-preserving functions
+ //! --------------------------
+ //! Let `A` and `B` be two `Orderable` data types. A function
+ //! @f$ f : A \to B@f$ is said to be order-preserving (also called
+ //! monotone) if it preserves the structure of the `Orderable` concept,
+ //! which can be rigorously stated as follows. For all objects `x`, `y`
+ //! of data type `A`,
+ //! @code
+ //! if less(x, y) then less(f(x), f(y))
+ //! @endcode
+ //! Another important property is that of being order-reflecting, which
+ //! can be stated as
+ //! @code
+ //! if less(f(x), f(y)) then less(x, y)
+ //! @endcode
+ //! We say that a function is an order-embedding if it is both
+ //! order-preserving and order-reflecting, i.e. if
+ //! @code
+ //! less(x, y) if and only if less(f(x), f(y))
+ //! @endcode
+ //!
+ //!
+ //! Cross-type version of the methods
+ //! ---------------------------------
+ //! The comparison methods (`less`, `less_equal`, `greater` and
+ //! `greater_equal`) are "overloaded" to handle distinct data types
+ //! with certain properties. Specifically, they are defined for
+ //! _distinct_ data types `A` and `B` such that
+ //! 1. `A` and `B` share a common data type `C`, as determined by the
+ //! `common` metafunction
+ //! 2. `A`, `B` and `C` are all `Orderable` when taken individually
+ //! 3. @f$\mathrm{to<C>} : A \to C@f$ and @f$\mathrm{to<C>} : B \to C@f$
+ //! are both order-embeddings as determined by the `is_embedding`
+ //! metafunction.
+ //!
+ //! The method definitions for data types satisfying the above
+ //! properties are
+ //! @code
+ //! less(x, y) = less(to<C>(x), to<C>(y))
+ //! less_equal(x, y) = less_equal(to<C>(x), to<C>(y))
+ //! greater_equal(x, y) = greater_equal(to<C>(x), to<C>(y))
+ //! greater(x, y) = greater(to<C>(x), to<C>(y))
+ //! @endcode
+ //!
+ //!
+ //! Partial application of the methods
+ //! ----------------------------------
+ //! The `less`, `greater`, `less_equal` and `greater_equal` methods can
+ //! be called in two different ways. First, they can be called like
+ //! normal functions:
+ //! @code
+ //! less(x, y)
+ //! greater(x, y)
+ //!
+ //! less_equal(x, y)
+ //! greater_equal(x, y)
+ //! @endcode
+ //!
+ //! However, they may also be partially applied to an argument as follows:
+ //! @code
+ //! less.than(x)(y) == less(y, x)
+ //! greater.than(x)(y) == greater(y, x)
+ //!
+ //! less_equal.than(x)(y) == less_equal(y, x)
+ //! greater_equal.than(x)(y) == greater_equal(y, x)
+ //! @endcode
+ //!
+ //! Take good note that the order of the arguments is reversed, so
+ //! for example `less.than(x)(y)` is equivalent to `less(y, x)`, not
+ //! `less(x, y)`. This is because those variants are meant to be used
+ //! with higher order algorithms, where the chosen application order
+ //! makes sense.
+ //!
+ //!
+ //! [1]: http://en.wikipedia.org/wiki/Total_order
+ //! [2]: http://en.cppreference.com/w/cpp/concept/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>
+ struct Orderable;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_ORDERABLE_HPP
diff --git a/boost/hana/fwd/concept/product.hpp b/boost/hana/fwd/concept/product.hpp
new file mode 100644
index 0000000000..f3b2feb705
--- /dev/null
+++ b/boost/hana/fwd/concept/product.hpp
@@ -0,0 +1,103 @@
+/*!
+@file
+Forward declares `boost::hana::Product`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_PRODUCT_HPP
+#define BOOST_HANA_FWD_CONCEPT_PRODUCT_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! @defgroup group-Product Product
+ //! Represents types that are generic containers of two elements.
+ //!
+ //! This concept basically represents types that are like `std::pair`.
+ //! The motivation for making such a precise concept is similar to the
+ //! motivation behind the `Sequence` concept; there are many different
+ //! implementations of `std::pair` in different libraries, and we would
+ //! like to manipulate any of them generically.
+ //!
+ //! Since a `Product` is basically a pair, it is unsurprising that the
+ //! operations provided by this concept are getting the first and second
+ //! element of a pair, creating a pair from two elements and other
+ //! simmilar operations.
+ //!
+ //! @note
+ //! Mathematically, this concept represents types that are category
+ //! theoretical [products][1]. This is also where the name comes
+ //! from.
+ //!
+ //!
+ //! Minimal complete definition
+ //! ---------------------------
+ //! `first`, `second` and `make`
+ //!
+ //! `first` and `second` must obviously return the first and the second
+ //! element of the pair, respectively. `make` must take two arguments `x`
+ //! and `y` representing the first and the second element of the pair,
+ //! and return a pair `p` such that `first(p) == x` and `second(p) == y`.
+ //! @include example/product/make.cpp
+ //!
+ //!
+ //! Laws
+ //! ----
+ //! For a model `P` of `Product`, the following laws must be satisfied.
+ //! For every data types `X` and `Y`, there must be a unique function
+ //! @f$ \mathtt{make} : X \times Y \to P @f$ such that for every `x`, `y`,
+ //! @code
+ //! x == first(make<P>(x, y))
+ //! y == second(make<P>(x, y))
+ //! @endcode
+ //!
+ //! @note
+ //! This law is less general than the universal property typically used to
+ //! define category theoretical products, but it is vastly enough for what
+ //! we need.
+ //!
+ //! This is basically saying that a `Product` must be the most general
+ //! object able to contain a pair of objects `(P1, P2)`, but nothing
+ //! more. Since the categorical product is defined by a universal
+ //! property, all the models of this concept are isomorphic, and
+ //! the isomorphism is unique. In other words, there is one and only
+ //! one way to convert one `Product` to another.
+ //!
+ //! Another property that must be satisfied by `first` and `second` is
+ //! that of @ref move-independence, which ensures that we can optimally
+ //! decompose a `Product` into its two members without making redundant
+ //! copies.
+ //!
+ //!
+ //! Refined concepts
+ //! ----------------
+ //! 1. `Comparable` (free model)\n
+ //! Two products `x` and `y` are equal iff they are equal element-wise,
+ //! by comparing the first element before the second element.
+ //! @include example/product/comparable.cpp
+ //!
+ //! 2. `Orderable` (free model)\n
+ //! Products are ordered using a lexicographical ordering as-if they
+ //! were 2-element tuples.
+ //!
+ //! 3. `Foldable` (free model)\n
+ //! Folding a `Product` `p` is equivalent to folding a list containing
+ //! `first(p)` and `second(p)`, in that order.
+ //!
+ //!
+ //! Concrete models
+ //! ---------------
+ //! `hana::pair`
+ //!
+ //!
+ //! [1]: http://en.wikipedia.org/wiki/Product_(category_theory)
+ template <typename P>
+ struct Product;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_PRODUCT_HPP
diff --git a/boost/hana/fwd/concept/ring.hpp b/boost/hana/fwd/concept/ring.hpp
new file mode 100644
index 0000000000..91d150214e
--- /dev/null
+++ b/boost/hana/fwd/concept/ring.hpp
@@ -0,0 +1,106 @@
+/*!
+@file
+Forward declares `boost::hana::Ring`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_RING_HPP
+#define BOOST_HANA_FWD_CONCEPT_RING_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! @defgroup group-Ring Ring
+ //! The `Ring` concept represents `Group`s that also form a `Monoid`
+ //! under a second binary operation that distributes over the first.
+ //!
+ //! A [Ring][1] is an algebraic structure built on top of a `Group`
+ //! which requires a monoidal structure with respect to a second binary
+ //! operation. This second binary operation must distribute over the
+ //! first one. Specifically, a `Ring` is a triple `(S, +, *)` such that
+ //! `(S, +)` is a `Group`, `(S, *)` is a `Monoid` and `*` distributes
+ //! over `+`, i.e.
+ //! @code
+ //! x * (y + z) == (x * y) + (x * z)
+ //! @endcode
+ //!
+ //! The second binary operation is often written `*` with its identity
+ //! written `1`, in reference to the `Ring` of integers under
+ //! multiplication. The method names used here refer to this exact ring.
+ //!
+ //!
+ //! Minimal complete definintion
+ //! ----------------------------
+ //! `one` and `mult` satisfying the laws
+ //!
+ //!
+ //! Laws
+ //! ----
+ //! For all objects `x`, `y`, `z` of a `Ring` `R`, the following laws must
+ //! be satisfied:
+ //! @code
+ //! mult(x, mult(y, z)) == mult(mult(x, y), z) // associativity
+ //! mult(x, one<R>()) == x // right identity
+ //! mult(one<R>(), x) == x // left identity
+ //! mult(x, plus(y, z)) == plus(mult(x, y), mult(x, z)) // distributivity
+ //! @endcode
+ //!
+ //!
+ //! Refined concepts
+ //! ----------------
+ //! `Monoid`, `Group`
+ //!
+ //!
+ //! Concrete models
+ //! ---------------
+ //! `hana::integral_constant`
+ //!
+ //!
+ //! Free model for non-boolean arithmetic data types
+ //! ------------------------------------------------
+ //! A data type `T` is arithmetic if `std::is_arithmetic<T>::%value` is
+ //! true. For a non-boolean arithmetic data type `T`, a model of `Ring` is
+ //! automatically defined by using the provided `Group` model and setting
+ //! @code
+ //! mult(x, y) = (x * y)
+ //! one<T>() = static_cast<T>(1)
+ //! @endcode
+ //!
+ //! @note
+ //! The rationale for not providing a Ring model for `bool` is the same
+ //! as for not providing Monoid and Group models.
+ //!
+ //!
+ //! Structure-preserving functions
+ //! ------------------------------
+ //! Let `A` and `B` be two `Ring`s. A function `f : A -> B` is said to
+ //! be a [Ring morphism][2] if it preserves the ring structure between
+ //! `A` and `B`. Rigorously, for all objects `x, y` of data type `A`,
+ //! @code
+ //! f(plus(x, y)) == plus(f(x), f(y))
+ //! f(mult(x, y)) == mult(f(x), f(y))
+ //! f(one<A>()) == one<B>()
+ //! @endcode
+ //! Because of the `Ring` structure, it is easy to prove that the
+ //! following will then also be satisfied:
+ //! @code
+ //! f(zero<A>()) == zero<B>()
+ //! f(negate(x)) == negate(f(x))
+ //! @endcode
+ //! which is to say that `f` will then also be a `Group` morphism.
+ //! Functions with these properties interact nicely with `Ring`s,
+ //! which is why they are given such a special treatment.
+ //!
+ //!
+ //! [1]: http://en.wikipedia.org/wiki/Ring_(mathematics)
+ //! [2]: http://en.wikipedia.org/wiki/Ring_homomorphism
+ template <typename R>
+ struct Ring;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_RING_HPP
diff --git a/boost/hana/fwd/concept/searchable.hpp b/boost/hana/fwd/concept/searchable.hpp
new file mode 100644
index 0000000000..8a0491b2ec
--- /dev/null
+++ b/boost/hana/fwd/concept/searchable.hpp
@@ -0,0 +1,143 @@
+/*!
+@file
+Forward declares `boost::hana::Searchable`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_SEARCHABLE_HPP
+#define BOOST_HANA_FWD_CONCEPT_SEARCHABLE_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! @defgroup group-Searchable Searchable
+ //! The `Searchable` concept represents structures that can be searched.
+ //!
+ //! Intuitively, a `Searchable` is any structure, finite or infinite,
+ //! containing elements that can be searched using a predicate. Sometimes,
+ //! `Searchable`s will associate keys to values; one can search for a key
+ //! with a predicate, and the value associated to it is returned. This
+ //! gives rise to map-like data structures. Other times, the elements of
+ //! the structure that are searched (i.e. those to which the predicate is
+ //! applied) are the same that are returned, which gives rise to set-like
+ //! data structures. In general, we will refer to the _keys_ of a
+ //! `Searchable` structure as those elements that are used for searching,
+ //! and to the _values_ of a `Searchable` as those elements that are
+ //! returned when a search is successful. As was explained, there is no
+ //! requirement that both notions differ, and it is often useful to have
+ //! keys and values coincide (think about `std::set`).
+ //!
+ //! Some methods like `any_of`, `all_of` and `none_of` allow simple queries
+ //! to be performed on the keys of the structure, while other methods like
+ //! `find` and `find_if` make it possible to find the value associated
+ //! to a key. The most specific method should always be used if one
+ //! cares about performance, because it is usually the case that heavy
+ //! optimizations can be performed in more specific methods. For example,
+ //! an associative data structure implemented as a hash table will be much
+ //! faster to access using `find` than `find_if`, because in the second
+ //! case it will have to do a linear search through all the entries.
+ //! Similarly, using `contains` will likely be much faster than `any_of`
+ //! with an equivalent predicate.
+ //!
+ //! > __Insight__\n
+ //! > In a lazy evaluation context, any `Foldable` can also become a model
+ //! > of `Searchable` because we can search lazily through the structure
+ //! > with `fold_right`. However, in the context of C++, some `Searchable`s
+ //! > can not be folded; think for example of an infinite set.
+ //!
+ //!
+ //! Minimal complete definition
+ //! ---------------------------
+ //! `find_if` and `any_of`
+ //!
+ //! When `find_if` and `any_of` are provided, the other functions are
+ //! implemented according to the laws explained below.
+ //!
+ //! @note
+ //! We could implement `any_of(xs, pred)` by checking whether
+ //! `find_if(xs, pred)` is an empty `optional` or not, and then reduce
+ //! the minimal complete definition to `find_if`. However, this is not
+ //! done because that implementation requires the predicate of `any_of`
+ //! to return a compile-time `Logical`, which is more restrictive than
+ //! what we have right now.
+ //!
+ //!
+ //! Laws
+ //! ----
+ //! In order for the semantics of the methods to be consistent, some
+ //! properties must be satisfied by any model of the `Searchable` concept.
+ //! Rigorously, for any `Searchable`s `xs` and `ys` and any predicate `p`,
+ //! the following laws should be satisfied:
+ //! @code
+ //! any_of(xs, p) <=> !all_of(xs, negated p)
+ //! <=> !none_of(xs, p)
+ //!
+ //! contains(xs, x) <=> any_of(xs, equal.to(x))
+ //!
+ //! find(xs, x) == find_if(xs, equal.to(x))
+ //! find_if(xs, always(false_)) == nothing
+ //!
+ //! is_subset(xs, ys) <=> all_of(xs, [](auto x) { return contains(ys, x); })
+ //! is_disjoint(xs, ys) <=> none_of(xs, [](auto x) { return contains(ys, x); })
+ //! @endcode
+ //!
+ //! Additionally, if all the keys of the `Searchable` are `Logical`s,
+ //! the following laws should be satisfied:
+ //! @code
+ //! any(xs) <=> any_of(xs, id)
+ //! all(xs) <=> all_of(xs, id)
+ //! none(xs) <=> none_of(xs, id)
+ //! @endcode
+ //!
+ //!
+ //! Concrete models
+ //! ---------------
+ //! `hana::map`, `hana::optional`, `hana::range`, `hana::set`,
+ //! `hana::string`, `hana::tuple`
+ //!
+ //!
+ //! Free model for builtin arrays
+ //! -----------------------------
+ //! Builtin arrays whose size is known can be searched as-if they were
+ //! homogeneous tuples. However, since arrays can only hold objects of
+ //! a single type and the predicate to `find_if` must return a compile-time
+ //! `Logical`, the `find_if` method is fairly useless. For similar reasons,
+ //! the `find` method is also fairly useless. This model is provided mainly
+ //! because of the `any_of` method & friends, which are both useful and
+ //! compile-time efficient.
+ //!
+ //!
+ //! Structure preserving functions
+ //! ------------------------------
+ //! Given two `Searchables` `S1` and `S2`, a function
+ //! @f$ f : S_1(X) \to S_2(X) @f$ is said to preserve the `Searchable`
+ //! structure if for all `xs` of data type `S1(X)` and predicates
+ //! @f$ \mathtt{pred} : X \to Bool @f$ (for a `Logical` `Bool`),
+ //! @code
+ //! any_of(xs, pred) if and only if any_of(f(xs), pred)
+ //! find_if(xs, pred) == find_if(f(xs), pred)
+ //! @endcode
+ //!
+ //! This is really just a generalization of the following, more intuitive
+ //! requirements. For all `xs` of data type `S1(X)` and `x` of data type
+ //! `X`,
+ //! @code
+ //! x ^in^ xs if and only if x ^in^ f(xs)
+ //! find(xs, x) == find(f(xs), x)
+ //! @endcode
+ //!
+ //! These requirements can be understood as saying that `f` does not
+ //! change the content of `xs`, although it may reorder elements.
+ //! As usual, such a structure-preserving transformation is said to
+ //! be an embedding if it is also injective, i.e. if it is a lossless
+ //! transformation.
+ template <typename S>
+ struct Searchable;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_SEARCHABLE_HPP
diff --git a/boost/hana/fwd/concept/sequence.hpp b/boost/hana/fwd/concept/sequence.hpp
new file mode 100644
index 0000000000..7f9df2e39d
--- /dev/null
+++ b/boost/hana/fwd/concept/sequence.hpp
@@ -0,0 +1,165 @@
+/*!
+@file
+Forward declares `boost::hana::Sequence`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_SEQUENCE_HPP
+#define BOOST_HANA_FWD_CONCEPT_SEQUENCE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! @defgroup group-Sequence Sequence
+ //! The `Sequence` concept represents generic index-based sequences.
+ //!
+ //! Compared to other abstract concepts, the Sequence concept is very
+ //! specific. It represents generic index-based sequences. The reason
+ //! why such a specific concept is provided is because there are a lot
+ //! of models that behave exactly the same while being implemented in
+ //! wildly different ways. It is useful to regroup all those data types
+ //! under the same umbrella for the purpose of generic programming.
+ //!
+ //! In fact, models of this concept are not only _similar_. They are
+ //! actually _isomorphic_, in a sense that we define below, which is
+ //! a fancy way of rigorously saying that they behave exactly the same
+ //! to an external observer.
+ //!
+ //!
+ //! Minimal complete definition
+ //! ---------------------------
+ //! `Iterable`, `Foldable`, and `make`
+ //!
+ //! The `Sequence` concept does not provide basic methods that could be
+ //! used as a minimal complete definition; instead, it borrows methods
+ //! from other concepts and add laws to them. For this reason, it is
+ //! necessary to specialize the `Sequence` metafunction in Hana's
+ //! namespace to tell Hana that a type is indeed a `Sequence`. Explicitly
+ //! specializing the `Sequence` metafunction can be seen like a seal
+ //! saying "this data type satisfies the additional laws of a `Sequence`",
+ //! since those can't be checked by Hana automatically.
+ //!
+ //!
+ //! Laws
+ //! ----
+ //! The laws for being a `Sequence` are simple, and their goal is to
+ //! restrict the semantics that can be associated to the functions
+ //! provided by other concepts. First, a `Sequence` must be a finite
+ //! `Iterable` (thus a `Foldable` too). Secondly, for a `Sequence` tag
+ //! `S`, `make<S>(x1, ..., xn)` must be an object of tag `S` and whose
+ //! linearization is `[x1, ..., xn]`. This basically ensures that objects
+ //! of tag `S` are equivalent to their linearization, and that they can
+ //! be created from such a linearization (with `make`).
+ //!
+ //! While it would be possible in theory to handle infinite sequences,
+ //! doing so complicates the implementation of many algorithms. For
+ //! simplicity, the current version of the library only handles finite
+ //! sequences. However, note that this does not affect in any way the
+ //! potential for having infinite `Searchable`s and `Iterable`s.
+ //!
+ //!
+ //! Refined concepts
+ //! ----------------
+ //! 1. `Comparable` (definition provided automatically)\n
+ //! Two `Sequence`s are equal if and only if they contain the same number
+ //! of elements and their elements at any given index are equal.
+ //! @include example/sequence/comparable.cpp
+ //!
+ //! 2. `Orderable` (definition provided automatically)\n
+ //! `Sequence`s are ordered using the traditional lexicographical ordering.
+ //! @include example/sequence/orderable.cpp
+ //!
+ //! 3. `Functor` (definition provided automatically)\n
+ //! `Sequence`s implement `transform` as the mapping of a function over
+ //! each element of the sequence. This is somewhat equivalent to what
+ //! `std::transform` does to ranges of iterators. Also note that mapping
+ //! a function over an empty sequence returns an empty sequence and never
+ //! applies the function, as would be expected.
+ //! @include example/sequence/functor.cpp
+ //!
+ //! 4. `Applicative` (definition provided automatically)\n
+ //! First, `lift`ing a value into a `Sequence` is the same as creating a
+ //! singleton sequence containing that value. Second, applying a sequence
+ //! of functions to a sequence of values will apply each function to
+ //! all the values in the sequence, and then return a list of all the
+ //! results. In other words,
+ //! @code
+ //! ap([f1, ..., fN], [x1, ..., xM]) == [
+ //! f1(x1), ..., f1(xM),
+ //! ...
+ //! fN(x1), ..., fN(xM)
+ //! ]
+ //! @endcode
+ //! Example:
+ //! @include example/sequence/applicative.cpp
+ //!
+ //! 5. `Monad` (definition provided automatically)\n
+ //! First, `flaten`ning a `Sequence` takes a sequence of sequences and
+ //! concatenates them to get a larger sequence. In other words,
+ //! @code
+ //! flatten([[a1, ..., aN], ..., [z1, ..., zM]]) == [
+ //! a1, ..., aN, ..., z1, ..., zM
+ //! ]
+ //! @endcode
+ //! This acts like a `std::tuple_cat` function, except it receives a
+ //! sequence of sequences instead of a variadic pack of sequences to
+ //! flatten.\n
+ //! __Example__:
+ //! @include example/sequence/monad.ints.cpp
+ //! Also note that the model of `Monad` for `Sequence`s can be seen as
+ //! modeling nondeterminism. A nondeterministic computation can be
+ //! modeled as a function which returns a sequence of possible results.
+ //! In this line of thought, `chain`ing a sequence of values into such
+ //! a function will return a sequence of all the possible output values,
+ //! i.e. a sequence of all the values applied to all the functions in
+ //! the sequences.\n
+ //! __Example__:
+ //! @include example/sequence/monad.types.cpp
+ //!
+ //! 6. `MonadPlus` (definition provided automatically)\n
+ //! `Sequence`s are models of the `MonadPlus` concept by considering the
+ //! empty sequence as the unit of `concat`, and sequence concatenation
+ //! as `concat`.
+ //! @include example/sequence/monad_plus.cpp
+ //!
+ //! 7. `Foldable`\n
+ //! The model of `Foldable` for `Sequence`s is uniquely determined by the
+ //! model of `Iterable`.
+ //! @include example/sequence/foldable.cpp
+ //!
+ //! 8. `Iterable`\n
+ //! The model of `Iterable` for `Sequence`s corresponds to iteration over
+ //! each element of the sequence, in order. This model is not provided
+ //! automatically, and it is in fact part of the minimal complete
+ //! definition for the `Sequence` concept.
+ //! @include example/sequence/iterable.cpp
+ //!
+ //! 9. `Searchable` (definition provided automatically)\n
+ //! Searching through a `Sequence` is equivalent to just searching through
+ //! a list of the values it contains. The keys and the values on which
+ //! the search is performed are both the elements of the sequence.
+ //! @include example/sequence/searchable.cpp
+ //!
+ //!
+ //! Concrete models
+ //! ---------------
+ //! `hana::tuple`
+ //!
+ //!
+ //! [1]: http://en.wikipedia.org/wiki/Isomorphism#Isomorphism_vs._bijective_morphism
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename S>
+ struct Sequence;
+#else
+ template <typename S, typename = void>
+ struct Sequence : Sequence<S, when<true>> { };
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_SEQUENCE_HPP
diff --git a/boost/hana/fwd/concept/struct.hpp b/boost/hana/fwd/concept/struct.hpp
new file mode 100644
index 0000000000..f6829466bb
--- /dev/null
+++ b/boost/hana/fwd/concept/struct.hpp
@@ -0,0 +1,156 @@
+/*!
+@file
+Forward declares `boost::hana::Struct`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONCEPT_STRUCT_HPP
+#define BOOST_HANA_FWD_CONCEPT_STRUCT_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-concepts
+ //! @defgroup group-Struct Struct
+ //! The `Struct` concept represents `struct`-like user-defined types.
+ //!
+ //! The `Struct` concept allows restricted compile-time reflection over
+ //! user-defined types. In particular, it allows accessing the names of
+ //! the members of a user-defined type, and also the value of those
+ //! members. `Struct`s can also be folded, searched and converted to
+ //! some types of containers, where more advanced transformations can
+ //! be performed.
+ //!
+ //! While all types can _in theory_ be made `Struct`s, only a subset of
+ //! them are actually interesting to see as such. More precisely, it is
+ //! only interesting to make a type a `Struct` when it is conceptually
+ //! a C++ `struct`, i.e. a mostly dumb aggregate of named data. The way
+ //! this data is accessed is mostly unimportant to the `Struct` concept;
+ //! it could be through getters and setters, through public members,
+ //! through non-member functions or it could even be generated on-the-fly.
+ //! The important part, which is made precise below, is that those accessor
+ //! methods should be move-independent.
+ //!
+ //! Another way to see a `Struct` is as a map where the keys are the names
+ //! of the members and the values are the values of those members. However,
+ //! there are subtle differences like the fact that one can't add a member
+ //! to a `Struct`, and also that the order of the members inside a `Struct`
+ //! plays a role in determining the equality of `Struct`s, which is not
+ //! the case for maps.
+ //!
+ //!
+ //! Minimal complete definition
+ //! ---------------------------
+ //! `accessors`
+ //!
+ //! A model of `Struct` is created by specifying a sequence of key/value
+ //! pairs with the `accessors` function. The first element of a pair in
+ //! this sequence represents the "name" of a member of the `Struct`, while
+ //! the second element is a function which retrieves this member from an
+ //! object. The "names" do not have to be in any special form; they just
+ //! have to be compile-time `Comparable`. For example, it is common to
+ //! provide "names" that are `hana::string`s representing the actual names
+ //! of the members, but one could provide `hana::integral_constant`s just
+ //! as well. The values must be functions which, when given an object,
+ //! retrieve the appropriate member from it.
+ //!
+ //! There are several ways of providing the `accessors` method, some of
+ //! which are more flexible and others which are more convenient. First,
+ //! one can define it through tag-dispatching, as usual.
+ //! @snippet example/struct.mcd.tag_dispatching.cpp main
+ //!
+ //! Secondly, it is possible to provide a nested `hana_accessors_impl`
+ //! type, which should be equivalent to a specialization of
+ //! `accessors_impl` for tag-dispatching. However, for a type `S`, this
+ //! technique only works when the data type of `S` is `S` itself, which
+ //! is the case unless you explicitly asked for something else.
+ //! @snippet example/struct.mcd.nested.cpp main
+ //!
+ //! Finally, the most convenient (but least flexible) option is to use
+ //! the `BOOST_HANA_DEFINE_STRUCT`, the `BOOST_HANA_ADAPT_STRUCT` or the
+ //! `BOOST_HANA_ADAPT_ADT` macro, which provide a minimal syntactic
+ //! overhead. See the documentation of these macros for details on how
+ //! to use them.
+ //!
+ //! Also note that it is not important that the accessor functions retrieve
+ //! an actual member of the struct (e.g. `x.member`). Indeed, an accessor
+ //! function could call a custom getter or even compute the value of the
+ //! member on the fly:
+ //! @snippet example/struct.custom_accessor.cpp main
+ //!
+ //! The only important thing is that the accessor functions are
+ //! move-independent, a notion which is defined below.
+ //!
+ //!
+ //! @anchor move-independence
+ //! Move-independence
+ //! -----------------
+ //! The notion of move-independence presented here defines rigorously
+ //! when it is legitimate to "double-move" from an object.
+ //!
+ //! A collection of functions `f1, ..., fn` sharing the same domain is
+ //! said to be _move-independent_ if for every fresh (not moved-from)
+ //! object `x` in the domain, any permutation of the following statements
+ //! is valid and leaves the `zk` objects in a fresh (not moved-from) state:
+ //! @code
+ //! auto z1 = f1(std::move(x));
+ //! ...
+ //! auto zn = fn(std::move(x));
+ //! @endcode
+ //!
+ //! @note
+ //! In the special case where some functions return objects that can't be
+ //! bound to with `auto zk =` (like `void` or a non-movable, non-copyable
+ //! type), just pretend the return value is ignored.
+ //!
+ //! Intuitively, this ensures that we can treat `f1, ..., fn` as
+ //! "accessors" that decompose `x` into independent subobjects, and
+ //! that do so without moving from `x` more than that subobject. This
+ //! is important because it allows us to optimally decompose `Struct`s
+ //! into their subparts inside the library.
+ //!
+ //!
+ //! Laws
+ //! ----
+ //! For any `Struct` `S`, the accessors in the `accessors<S>()` sequence
+ //! must be move-independent, as defined above.
+ //!
+ //!
+ //! Refined concepts
+ //! ----------------
+ //! 1. `Comparable` (free model)\n
+ //! `Struct`s are required to be `Comparable`. Specifically, two `Struct`s
+ //! of the same data type `S` must be equal if and only if all of their
+ //! members are equal. By default, a model of `Comparable` doing just that
+ //! is provided for models of `Struct`. In particular, note that the
+ //! comparison of the members is made in the same order as they appear in
+ //! the `hana::members` sequence.
+ //! @include example/struct/comparable.cpp
+ //!
+ //! 2. `Foldable` (free model)\n
+ //! A `Struct` can be folded by considering it as a list of pairs each
+ //! containing the name of a member and the value associated to that
+ //! member, in the same order as they appear in the `hana::members`
+ //! sequence. By default, a model of `Foldable` doing just that is
+ //! provided for models of the `Struct` concept.
+ //! @include example/struct/foldable.cpp
+ //! Being a model of `Foldable` makes it possible to turn a `Struct`
+ //! into basically any `Sequence`, but also into a `hana::map` by simply
+ //! using the `to<...>` function!
+ //! @include example/struct/to.cpp
+ //!
+ //! 3. `Searchable` (free model)\n
+ //! A `Struct` can be searched by considering it as a map where the keys
+ //! are the names of the members of the `Struct`, and the values are the
+ //! members associated to those names. By default, a model of `Searchable`
+ //! is provided for any model of the `Struct` concept.
+ //! @include example/struct/searchable.cpp
+ template <typename S>
+ struct Struct;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONCEPT_STRUCT_HPP
diff --git a/boost/hana/fwd/contains.hpp b/boost/hana/fwd/contains.hpp
new file mode 100644
index 0000000000..f717f6738c
--- /dev/null
+++ b/boost/hana/fwd/contains.hpp
@@ -0,0 +1,73 @@
+/*!
+@file
+Forward declares `boost::hana::contains` and `boost::hana::in`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CONTAINS_HPP
+#define BOOST_HANA_FWD_CONTAINS_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/functional/flip.hpp>
+#include <boost/hana/functional/infix.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns whether the key occurs in the structure.
+ //! @ingroup group-Searchable
+ //!
+ //! Given a `Searchable` structure `xs` and a `key`, `contains` returns
+ //! whether any of the keys of the structure is equal to the given `key`.
+ //! If the structure is not finite, an equal key has to appear at a finite
+ //! position in the structure for this method to finish. For convenience,
+ //! `contains` can also be applied in infix notation.
+ //!
+ //!
+ //! @param xs
+ //! The structure to search.
+ //!
+ //! @param key
+ //! A key to be searched for in the structure. The key has to be
+ //! `Comparable` with the other keys of the structure.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/contains.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto contains = [](auto&& xs, auto&& key) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct contains_impl : contains_impl<S, when<true>> { };
+
+ struct contains_t {
+ template <typename Xs, typename Key>
+ constexpr auto operator()(Xs&& xs, Key&& key) const;
+ };
+
+ constexpr auto contains = hana::infix(contains_t{});
+#endif
+
+ //! Return whether the key occurs in the structure.
+ //! @ingroup group-Searchable
+ //!
+ //! Specifically, this is equivalent to `contains`, except `in` takes its
+ //! arguments in reverse order. Like `contains`, `in` can also be applied
+ //! in infix notation for increased expressiveness. This function is not a
+ //! method that can be overriden; it is just a convenience function
+ //! provided with the concept.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/in.cpp
+ constexpr auto in = hana::infix(hana::flip(hana::contains));
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CONTAINS_HPP
diff --git a/boost/hana/fwd/core.hpp b/boost/hana/fwd/core.hpp
new file mode 100644
index 0000000000..10fad8ace9
--- /dev/null
+++ b/boost/hana/fwd/core.hpp
@@ -0,0 +1,21 @@
+/*!
+@file
+Forward declares the @ref group-core module.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CORE_HPP
+#define BOOST_HANA_FWD_CORE_HPP
+
+#include <boost/hana/fwd/core/common.hpp>
+#include <boost/hana/fwd/core/to.hpp>
+#include <boost/hana/fwd/core/default.hpp>
+#include <boost/hana/fwd/core/is_a.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+#include <boost/hana/fwd/core/tag_of.hpp>
+#include <boost/hana/fwd/core/when.hpp>
+
+#endif // !BOOST_HANA_FWD_CORE_HPP
diff --git a/boost/hana/fwd/core/common.hpp b/boost/hana/fwd/core/common.hpp
new file mode 100644
index 0000000000..29702f23d5
--- /dev/null
+++ b/boost/hana/fwd/core/common.hpp
@@ -0,0 +1,103 @@
+/*!
+@file
+Forward declares `boost::hana::common` and `boost::hana::common_t`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CORE_COMMON_HPP
+#define BOOST_HANA_FWD_CORE_COMMON_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-core
+ //! %Metafunction returning the common data type between two data types.
+ //!
+ //! `common` is a natural extension of the `std::common_type` metafunction
+ //! to data types. Given two data types `T` and `U`, we say that they share
+ //! a common type `C` if both objects of data type `T` and objects of data
+ //! type `U` may be converted (using `to`) to an object of data type `C`,
+ //! and if that conversion is equality preserving. In other words, this
+ //! means that for any objects `t1, t2` of data type `T` and `u1, u2` of
+ //! data type `U`, the following law is satisfied:
+ //! @code
+ //! to<C>(t1) == to<C>(t2) if and only if t1 == t2
+ //! to<C>(u1) == to<C>(u2) if and only if u1 == u2
+ //! @endcode
+ //!
+ //! The role of `common` is to provide an alias to such a `C` if it exists.
+ //! In other words, if `T` and `U` have a common data type `C`,
+ //! `common<T, U>::%type` is an alias to `C`. Otherwise, `common<T, U>`
+ //! has no nested `type` and can be used in dependent contexts to exploit
+ //! SFINAE. By default, the exact steps followed by `common` to determine
+ //! the common type `C` of `T` and `U` are
+ //! 1. If `T` and `U` are the same, then `C` is `T`.
+ //! 2. Otherwise, if `true ? std::declval<T>() : std::declval<U>()` is
+ //! well-formed, then `C` is the type of this expression after using
+ //! `std::decay` on it. This is exactly the type that would have been
+ //! returned by `std::common_type`, except that custom specializations
+ //! of `std::common_type` are not taken into account.
+ //! 3. Otherwise, no common data type is detected and `common<T, U>` does
+ //! not have a nested `type` alias, unless it is specialized explicitly.
+ //!
+ //! As point 3 suggests, it is also possible (and sometimes necessary) to
+ //! specialize `common` in the `boost::hana` namespace for pairs of custom
+ //! data types when the default behavior of `common` is not sufficient.
+ //! Note that `when`-based specialization is supported when specializing
+ //! `common` in the `boost::hana` namespace.
+ //!
+ //! > #### Rationale for requiring the conversion to be equality-preserving
+ //! > This decision is aligned with a proposed concept design for the
+ //! > standard library ([N3351][1]). Also, if we did not require this,
+ //! > then all data types would trivially share the common data type
+ //! > `void`, since all objects can be converted to it.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/core/common/common.cpp
+ //!
+ //!
+ //! [1]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3351.pdf
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename T, typename U, optional when-based enabler>
+ struct common { see documentation };
+#else
+ template <typename T, typename U, typename = void>
+ struct common;
+#endif
+
+ //! @ingroup group-core
+ //! %Metafunction returning whether two data types share a common data type.
+ //!
+ //! Given two data types `T` and `U`, this metafunction simply returns
+ //! whether `common<T, U>::%type` is well-formed.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/core/common/has_common.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename T, typename U>
+ struct has_common { whether common<T, U>::type is well-formed };
+#else
+ template <typename T, typename U, typename = void>
+ struct has_common;
+#endif
+
+ //! @ingroup group-core
+ //! Alias to `common<T, U>::%type`, provided for convenience.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/core/common/common_t.cpp
+ template <typename T, typename U>
+ using common_t = typename common<T, U>::type;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CORE_COMMON_HPP
diff --git a/boost/hana/fwd/core/default.hpp b/boost/hana/fwd/core/default.hpp
new file mode 100644
index 0000000000..58e3f060f3
--- /dev/null
+++ b/boost/hana/fwd/core/default.hpp
@@ -0,0 +1,56 @@
+/*!
+@file
+Forward declares `boost::hana::default_` and `boost::hana::is_default`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CORE_DEFAULT_HPP
+#define BOOST_HANA_FWD_CORE_DEFAULT_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-core
+ //! Mark a tag-dispatched method implementation as a default implementation.
+ //!
+ //! When defining a new concept with tag-dispatched methods, it is
+ //! sometimes possible to provide a default implementation for some
+ //! method(s). Making `default_` a base class of such a default
+ //! implementation makes it possible to detect whether the method
+ //! was dispatched to the default implementation afterwards.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/core/default.cpp
+ struct default_ { };
+
+ //! @ingroup group-core
+ //! Returns whether a tag-dispatched method implementation is a default
+ //! implementation.
+ //!
+ //! Given a tag-dispatched method implementation `method_impl<T...>`,
+ //! `is_default<method_impl<T...>>` returns whether `method_impl<T...>`
+ //! is a default implementation. Note that if there is no default
+ //! implementation for the method, then `is_default` should not be
+ //! used unless a static assertion saying that "the method is not
+ //! implemented" is acceptable.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/core/default.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename Method>
+ struct is_default { see documentation };
+#else
+ template <typename T, typename = void>
+ struct is_default;
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CORE_DEFAULT_HPP
diff --git a/boost/hana/fwd/core/is_a.hpp b/boost/hana/fwd/core/is_a.hpp
new file mode 100644
index 0000000000..5a90c6d55b
--- /dev/null
+++ b/boost/hana/fwd/core/is_a.hpp
@@ -0,0 +1,61 @@
+/*!
+@file
+Forward declares `boost::hana::is_a` and `boost::hana::is_an`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CORE_IS_A_HPP
+#define BOOST_HANA_FWD_CORE_IS_A_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-core
+ //! Returns whether the tag of an object matches a given tag.
+ //!
+ //! Given a tag `Tag` and a C++ type `T`, `is_a<Tag, T>` is a compile-time
+ //! Logical representing whether the tag of `T` is exactly `Tag`. In other
+ //! words, it is equivalent to
+ //! @code
+ //! std::is_same<Tag, tag_of<T>::type>
+ //! @endcode
+ //!
+ //! For convenience, an alternate syntax is provided for using `is_a`.
+ //! Specifically, `is_a<Tag>` is a function object returning whether the
+ //! argument it is passed has the given tag. In other words,
+ //! @code
+ //! is_a<Tag>(x) == is_a<Tag, decltype(x)>
+ //! @endcode
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/core/is_a.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename Tag, typename optional_T>
+ constexpr auto is_a = see-documentation;
+#else
+ template <typename Tag, typename ...T>
+ struct is_a_t;
+
+ template <typename Tag, typename ...T>
+ constexpr is_a_t<Tag, T...> is_a{};
+#endif
+
+ //! @ingroup group-core
+ //! Equivalent to `is_a`; provided for consistency with the rules of the
+ //! English language.
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename Tag, typename ...T>
+ constexpr auto is_an = is_a<Tag, T...>;
+#else
+ template <typename Tag, typename ...T>
+ constexpr is_a_t<Tag, T...> is_an{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CORE_IS_A_HPP
diff --git a/boost/hana/fwd/core/make.hpp b/boost/hana/fwd/core/make.hpp
new file mode 100644
index 0000000000..56354b6813
--- /dev/null
+++ b/boost/hana/fwd/core/make.hpp
@@ -0,0 +1,70 @@
+/*!
+@file
+Forward declares `boost::hana::make`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CORE_MAKE_HPP
+#define BOOST_HANA_FWD_CORE_MAKE_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-core
+ //! Create an object of the given tag with the given arguments.
+ //!
+ //! This function serves the same purpose as constructors in usual C++.
+ //! However, instead of creating an object of a specific C++ type, it
+ //! creates an object of a specific tag, regardless of the C++ type
+ //! of that object.
+ //!
+ //! This function is actually a variable template, so `make<T>` can be
+ //! passed around as a function object creating an object of tag `T`.
+ //! Also, it uses tag-dispatching so this is how it should be customized
+ //! for user-defined tags.
+ //!
+ //! Finally, the default implementation of `make` is equivalent to calling
+ //! the constructor of the given tag with the corresponding arguments.
+ //! In other words, by default,
+ //! @code
+ //! make<T>(args...) == T(args...)
+ //! @endcode
+ //!
+ //! Note that the arguments are perfectly forwarded and the form of
+ //! construction which is used is exactly as documented, i.e. `T(args...)`.
+ //! However, if `T(args...)` is not a valid expression, a compilation
+ //! error is triggered. This default behavior is useful because it makes
+ //! foreign C++ types that have no notion of tag constructible with `make`
+ //! out-of-the-box, since their tag is exactly themselves.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/core/make.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename Tag>
+ constexpr auto make = [](auto&& ...x) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename Tag, typename = void>
+ struct make_impl;
+
+ template <typename Tag>
+ struct make_t {
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) const {
+ return make_impl<Tag>::apply(static_cast<X&&>(x)...);
+ }
+ };
+
+ template <typename Tag>
+ constexpr make_t<Tag> make{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CORE_MAKE_HPP
diff --git a/boost/hana/fwd/core/tag_of.hpp b/boost/hana/fwd/core/tag_of.hpp
new file mode 100644
index 0000000000..a2e7cc5605
--- /dev/null
+++ b/boost/hana/fwd/core/tag_of.hpp
@@ -0,0 +1,120 @@
+/*!
+@file
+Forward declares `boost::hana::tag_of` and `boost::hana::tag_of_t`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CORE_TAG_OF_HPP
+#define BOOST_HANA_FWD_CORE_TAG_OF_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-core
+ //! %Metafunction returning the tag associated to `T`.
+ //!
+ //! There are several ways to specify the tag of a C++ type. If it's a
+ //! user-defined type, one can define a nested `hana_tag` alias:
+ //! @code
+ //! struct MyUserDefinedType {
+ //! using hana_tag = MyTag;
+ //! };
+ //! @endcode
+ //!
+ //! Sometimes, however, the C++ type can't be modified (if it's in a
+ //! foreign library) or simply can't have nested types (if it's not a
+ //! struct or class). In those cases, using a nested alias is impossible
+ //! and so ad-hoc customization is also supported by specializing
+ //! `tag_of` in the `boost::hana` namespace:
+ //! @code
+ //! struct i_cant_modify_this;
+ //!
+ //! namespace boost { namespace hana {
+ //! template <>
+ //! struct tag_of<i_cant_modify_this> {
+ //! using type = MyTag;
+ //! };
+ //! }}
+ //! @endcode
+ //!
+ //! `tag_of` can also be specialized for all C++ types satisfying some
+ //! boolean condition using `when`. `when` accepts a single compile-time
+ //! boolean and enables the specialization of `tag_of` if and only if
+ //! that boolean is `true`. This is similar to the well known C++ idiom
+ //! of using a dummy template parameter with `std::enable_if` and relying
+ //! on SFINAE. For example, we could specify the tag of all
+ //! `fusion::vector`s by doing:
+ //! @code
+ //! struct BoostFusionVector;
+ //!
+ //! namespace boost { namespace hana {
+ //! template <typename T>
+ //! struct tag_of<T, when<
+ //! std::is_same<
+ //! typename fusion::traits::tag_of<T>::type,
+ //! fusion::traits::tag_of<fusion::vector<>>::type
+ //! >{}
+ //! >> {
+ //! using type = BoostFusionVector;
+ //! };
+ //! }}
+ //! @endcode
+ //!
+ //! Also, when it is not specialized and when the given C++ type does not
+ //! have a nested `hana_tag` alias, `tag_of<T>` returns `T` itself. This
+ //! makes tags a simple extension of normal C++ types. This is _super_
+ //! useful, mainly for two reasons. First, this allows Hana to adopt a
+ //! reasonable default behavior for some operations involving types that
+ //! have no notion of tags. For example, Hana allows comparing with `equal`
+ //! any two objects for which a valid `operator==` is defined, and that
+ //! without any work on the user side. Second, it also means that you can
+ //! ignore tags completely if you don't need their functionality; just use
+ //! the normal C++ type of your objects and everything will "just work".
+ //!
+ //! Finally, also note that `tag_of<T>` is always equivalent to `tag_of<U>`,
+ //! where `U` is the type `T` after being stripped of all references and
+ //! cv-qualifiers. This makes it unnecessary to specialize `tag_of` for
+ //! all reference and cv combinations, which would be a real pain. Also,
+ //! `tag_of` is required to be idempotent. In other words, it must always
+ //! be the case that `tag_of<tag_of<T>::%type>::%type` is equivalent to
+ //! `tag_of<T>::%type`.
+ //!
+ //! > __Tip 1__\n
+ //! > If compile-time performance is a serious concern, consider
+ //! > specializing the `tag_of` metafunction in Hana's namespace.
+ //! > When unspecialized, the metafunction has to use SFINAE, which
+ //! > tends to incur a larger compile-time overhead. For heavily used
+ //! > templated types, this can potentially make a difference.
+ //!
+ //! > __Tip 2__\n
+ //! > Consider using `tag_of_t` alias instead of `tag_of`, which
+ //! > reduces the amount of typing in dependent contexts.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/core/tag_of.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename T, optional when-based enabler>
+ struct tag_of { unspecified };
+#else
+ template <typename T, typename = void>
+ struct tag_of;
+#endif
+
+ //! @ingroup group-core
+ //! Alias to `tag_of<T>::%type`, provided for convenience.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/core/tag_of_t.cpp
+ template <typename T>
+ using tag_of_t = typename hana::tag_of<T>::type;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CORE_TAG_OF_HPP
diff --git a/boost/hana/fwd/core/to.hpp b/boost/hana/fwd/core/to.hpp
new file mode 100644
index 0000000000..e41d36ee0a
--- /dev/null
+++ b/boost/hana/fwd/core/to.hpp
@@ -0,0 +1,174 @@
+/*!
+@file
+Forward declares `boost::hana::to` and related utilities.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CORE_TO_HPP
+#define BOOST_HANA_FWD_CORE_TO_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-core
+ //! Converts an object from one data type to another.
+ //!
+ //! `to` is a natural extension of the `static_cast` language construct to
+ //! data types. Given a destination data type `To` and an object `x`, `to`
+ //! creates a new object of data type `To` from `x`. Note, however, that
+ //! `to` is not required to actually create a new object, and may return a
+ //! reference to the original object (for example when trying to convert
+ //! an object to its own data type).
+ //!
+ //! As a natural extension to `static_cast`, `to` provides a default
+ //! behavior. For the purpose of what follows, let `To` be the destination
+ //! data type and `From` be the data type of `x`, i.e. the source data type.
+ //! Then, `to` has the following default behavior:
+ //! 1. If the `To` and `From` data types are the same, then the object
+ //! is forwarded as-is.
+ //! 2. Otherwise, if `From` is convertible to `To` using `static_cast`,
+ //! `x` is converted to `From` using `static_cast`.
+ //! 3. Otherwise, calling `to<From>(x)` triggers a static assertion.
+ //!
+ //! However, `to` is a tag-dispatched function, which means that `to_impl`
+ //! may be specialized in the `boost::hana` namespace to customize its
+ //! behavior for arbitrary data types. Also note that `to` is tag-dispatched
+ //! using both the `To` and the `From` data types, which means that `to_impl`
+ //! is called as `to_impl<To, From>::%apply(x)`. Also note that some
+ //! concepts provide conversions to or from their models. For example,
+ //! any `Foldable` may be converted into a `Sequence`. This is achieved
+ //! by specializing `to_impl<To, From>` whenever `To` is a `Sequence` and
+ //! `From` is a `Foldable`. When such conversions are provided, they are
+ //! documented in the source concept, in this case `Foldable`.
+ //!
+ //!
+ //! Hana-convertibility
+ //! -------------------
+ //! When an object `x` of data type `From` can be converted to a data type
+ //! `To` using `to`, we say that `x` is Hana-convertible to the data type
+ //! `To`. We also say that there is a Hana-conversion from `From` to `To`.
+ //! This bit of terminology is useful to avoid mistaking the various kinds
+ //! of conversions C++ offers.
+ //!
+ //!
+ //! Embeddings
+ //! ----------
+ //! As you might have seen by now, Hana uses algebraic and category-
+ //! theoretical structures all around the place to help specify concepts
+ //! in a rigorous way. These structures always have operations associated
+ //! to them, which is why they are useful. The notion of embedding captures
+ //! the idea of injecting a smaller structure into a larger one while
+ //! preserving the operations of the structure. In other words, an
+ //! embedding is an injective mapping that is also structure-preserving.
+ //! Exactly what it means for a structure's operations to be preserved is
+ //! left to explain by the documentation of each structure. For example,
+ //! when we talk of a Monoid-embedding from a Monoid `A` to a Monoid `B`,
+ //! we simply mean an injective transformation that preserves the identity
+ //! and the associative operation, as documented in `Monoid`.
+ //!
+ //! But what does this have to do with the `to` function? Quite simply,
+ //! the `to` function is a mapping between two data types, which will
+ //! sometimes be some kind of structure, and it is sometimes useful to
+ //! know whether such a mapping is well-behaved, i.e. lossless and
+ //! structure preserving. The criterion for this conversion to be well-
+ //! behaved is exactly that of being an embedding. To specify that a
+ //! conversion is an embedding, simply use the `embedding` type as a
+ //! base class of the corresponding `to_impl` specialization. Obviously,
+ //! you should make sure the conversion is really an embedding, unless
+ //! you want to shoot yourself in the foot.
+ //!
+ //!
+ //! @tparam To
+ //! The data type to which `x` should be converted.
+ //!
+ //! @param x
+ //! The object to convert to the given data type.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/core/convert/to.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename To>
+ constexpr auto to = [](auto&& x) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename To, typename From, typename = void>
+ struct to_impl;
+
+ template <typename To>
+ struct to_t {
+ template <typename X>
+ constexpr decltype(auto) operator()(X&& x) const;
+ };
+
+ template <typename To>
+ constexpr to_t<To> to{};
+#endif
+
+ //! @ingroup group-core
+ //! Returns whether there is a Hana-conversion from a data type to another.
+ //!
+ //! Specifically, `is_convertible<From, To>` is whether calling `to<To>`
+ //! with an object of data type `From` would _not_ trigger a static
+ //! assertion.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/core/convert/is_convertible.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename From, typename To>
+ struct is_convertible { see documentation };
+#else
+ template <typename From, typename To, typename = void>
+ struct is_convertible;
+#endif
+
+ //! @ingroup group-core
+ //! Marks a conversion between data types as being an embedding.
+ //!
+ //! To mark a conversion between two data types `To` and `From` as
+ //! an embedding, simply use `embedding<true>` (or simply `embedding<>`)
+ //! as a base class of the corresponding `to_impl` specialization.
+ //! If a `to_impl` specialization does not inherit `embedding<true>`
+ //! or `embedding<>`, then it is not considered an embedding by the
+ //! `is_embedded` metafunction.
+ //!
+ //! > #### Tip
+ //! > The boolean template parameter is useful for marking a conversion
+ //! > as an embedding only when some condition is satisfied.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/core/convert/embedding.cpp
+ template <bool = true>
+ struct embedding { };
+
+ //! @ingroup group-core
+ //! Returns whether a data type can be embedded into another data type.
+ //!
+ //! Given two data types `To` and `From`, `is_embedded<From, To>` returns
+ //! whether `From` is convertible to `To`, and whether that conversion is
+ //! also an embedding, as signaled by the `embedding` type.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/core/convert/is_embedded.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename From, typename To>
+ struct is_embedded { see documentation };
+#else
+ template <typename From, typename To, typename = void>
+ struct is_embedded;
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CORE_TO_HPP
diff --git a/boost/hana/fwd/core/when.hpp b/boost/hana/fwd/core/when.hpp
new file mode 100644
index 0000000000..857dc2581d
--- /dev/null
+++ b/boost/hana/fwd/core/when.hpp
@@ -0,0 +1,74 @@
+/*!
+@file
+Forward declares `boost::hana::when` and `boost::hana::when_valid`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CORE_WHEN_HPP
+#define BOOST_HANA_FWD_CORE_WHEN_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-core
+ //! Enable a partial specialization only if a boolean condition is true.
+ //!
+ //! You might also want to take a look at `when_valid`, which provides
+ //! similar functionality but enables a specialziation only when some
+ //! expression is well-formed.
+ //!
+ //! > #### Rationale for using `when` instead of `std::enable_if`
+ //! > `when` is used to control the priority of partial specializations
+ //! > in a finer grained manner than what can be achieved with the usual
+ //! > `typename Enable = void` and `std::enable_if` pattern. For example,
+ //! > a partially specialized tag-dispatched method will have a higher
+ //! > priority than an equivalent specialization that uses `when`. For
+ //! > more details, see the tutorial section on [tag-dispatching][1].
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/core/when.cpp
+ //!
+ //! [1]: @ref tutorial-core-tag_dispatching
+ template <bool condition>
+ struct when;
+
+ namespace core_detail {
+ template <typename ...>
+ struct always_true { static constexpr bool value = true; };
+ }
+
+ //! @ingroup group-core
+ //! Variant of `when` allowing specializations to be enabled only if an
+ //! expression is well-formed.
+ //!
+ //! `when_valid<...>` is always equivalent to `when<true>`. However, when
+ //! used inside a partial specialization, SFINAE will cause the partial
+ //! specialization to be ignored when the expression is ill-formed.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/core/when_valid.cpp
+ //!
+ //!
+ //! @bug
+ //! Using `when_valid` seems to trigger ambiguous partial specializations
+ //! on GCC.
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename ...>
+ using when_valid = when<true>;
+#else
+ template <typename ...Dummy>
+ using when_valid = when<
+ core_detail::always_true<Dummy...>::value
+ >;
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CORE_WHEN_HPP
diff --git a/boost/hana/fwd/count.hpp b/boost/hana/fwd/count.hpp
new file mode 100644
index 0000000000..ffa4a1a65a
--- /dev/null
+++ b/boost/hana/fwd/count.hpp
@@ -0,0 +1,57 @@
+/*!
+@file
+Forward declares `boost::hana::count`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_COUNT_HPP
+#define BOOST_HANA_FWD_COUNT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Return the number of elements in the structure that compare equal to
+ //! a given value.
+ //! @ingroup group-Foldable
+ //!
+ //! Given a Foldable structure `xs` and a value `value`, `count` returns
+ //! an unsigned integral, or a Constant thereof, representing the number
+ //! of elements of `xs` that compare equal to `value`. For this method to
+ //! be well-defined, all the elements of the structure must be Comparable
+ //! with the given value.
+ //!
+ //!
+ //! @param xs
+ //! The structure whose elements are counted.
+ //!
+ //! @param value
+ //! A value compared with each element in the structure. Elements
+ //! that compare equal to this value are counted, others are not.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/count.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto count = [](auto&& xs, auto&& value) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename = void>
+ struct count_impl : count_impl<T, when<true>> { };
+
+ struct count_t {
+ template <typename Xs, typename Value>
+ constexpr auto operator()(Xs&& xs, Value&& value) const;
+ };
+
+ constexpr count_t count{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_COUNT_HPP
diff --git a/boost/hana/fwd/count_if.hpp b/boost/hana/fwd/count_if.hpp
new file mode 100644
index 0000000000..a618f24e5f
--- /dev/null
+++ b/boost/hana/fwd/count_if.hpp
@@ -0,0 +1,63 @@
+/*!
+@file
+Forward declares `boost::hana::count_if`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_COUNT_IF_HPP
+#define BOOST_HANA_FWD_COUNT_IF_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Return the number of elements in the structure for which the
+ //! `predicate` is satisfied.
+ //! @ingroup group-Foldable
+ //!
+ //! Specifically, returns an object of an unsigned integral type, or
+ //! a `Constant` holding such an object, which represents the number
+ //! of elements in the structure satisfying the given `predicate`.
+ //!
+ //!
+ //! @param xs
+ //! The structure whose elements are counted.
+ //!
+ //! @param predicate
+ //! A function called as `predicate(x)`, where `x` is an element of the
+ //! structure, and returning a `Logical` representing whether `x` should
+ //! be counted.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/count_if.cpp
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.count_if.compile.json">
+ //! </div>
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto count_if = [](auto&& xs, auto&& predicate) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename = void>
+ struct count_if_impl : count_if_impl<T, when<true>> { };
+
+ struct count_if_t {
+ template <typename Xs, typename Pred>
+ constexpr auto operator()(Xs&& xs, Pred&& pred) const;
+ };
+
+ constexpr count_if_t count_if{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_COUNT_IF_HPP
diff --git a/boost/hana/fwd/cycle.hpp b/boost/hana/fwd/cycle.hpp
new file mode 100644
index 0000000000..4d23b8d821
--- /dev/null
+++ b/boost/hana/fwd/cycle.hpp
@@ -0,0 +1,76 @@
+/*!
+@file
+Forward declares `boost::hana::cycle`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_CYCLE_HPP
+#define BOOST_HANA_FWD_CYCLE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Combine a monadic structure with itself `n` times.
+ //! @ingroup group-MonadPlus
+ //!
+ //! Given a monadic structure `xs` and a non-negative number `n`,
+ //! `cycle` returns a new monadic structure which is the result of
+ //! combining `xs` with itself `n` times using the `concat` operation.
+ //! In other words,
+ //! @code
+ //! cycle(xs, n) == concat(xs, concat(xs, ... concat(xs, xs)))
+ //! // ^^^^^ n times total
+ //! @endcode
+ //!
+ //! Also note that since `concat` is required to be associative, we
+ //! could also have written
+ //! @code
+ //! cycle(xs, n) == concat(concat(... concat(xs, xs), xs), xs)
+ //! // ^^^^^ n times total
+ //! @endcode
+ //!
+ //! If `n` is zero, then the identity of `concat`, `empty`, is returned.
+ //! In the case of sequences, this boils down to returning a sequence
+ //! containing `n` copies of itself; for other models it might differ.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given an `IntegralConstant` `C` and a `MonadPlus` `M`, the signature is
+ //! @f$ \mathrm{cycle} : M(T) \times C \to M(T) @f$.
+ //!
+ //! @param xs
+ //! A monadic structure to combine with itself a certain number of times.
+ //!
+ //! @param n
+ //! A non-negative `IntegralConstant` representing the number of times to
+ //! combine the monadic structure with itself. If `n` is zero, `cycle`
+ //! returns `empty`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/cycle.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto cycle = [](auto&& xs, auto const& n) {
+ return tag-dispatched;
+ };
+#else
+ template <typename M, typename = void>
+ struct cycle_impl : cycle_impl<M, when<true>> { };
+
+ struct cycle_t {
+ template <typename Xs, typename N>
+ constexpr auto operator()(Xs&& xs, N const& n) const;
+ };
+
+ constexpr cycle_t cycle{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_CYCLE_HPP
diff --git a/boost/hana/fwd/define_struct.hpp b/boost/hana/fwd/define_struct.hpp
new file mode 100644
index 0000000000..b4adb89f5c
--- /dev/null
+++ b/boost/hana/fwd/define_struct.hpp
@@ -0,0 +1,48 @@
+/*!
+@file
+Documents the `BOOST_HANA_DEFINE_STRUCT` macro.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_DEFINE_STRUCT_HPP
+#define BOOST_HANA_FWD_DEFINE_STRUCT_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ // Note:
+ // The weird definition as a variable seems to exploit a glitch in Doxygen
+ // which makes the macro appear in the related objects of Struct (as we
+ // want it to).
+
+ //! Defines members of a structure, while at the same time
+ //! modeling `Struct`.
+ //! @ingroup group-Struct
+ //!
+ //! Using this macro in the body of a user-defined type will define the
+ //! given members inside that type, and will also provide a model of the
+ //! `Struct` concept for that user-defined type. This macro is often the
+ //! easiest way to define a model of the `Struct` concept.
+ //!
+ //! @note
+ //! This macro only works if the tag of the user-defined type `T` is `T`
+ //! itself. This is the case unless you specifically asked for something
+ //! different; see `tag_of`'s documentation.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/define_struct.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ auto BOOST_HANA_DEFINE_STRUCT(...) = ;
+ #define BOOST_HANA_DEFINE_STRUCT(Name, ...) see documentation
+#else
+ // defined in <boost/hana/define_struct.hpp>
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_DEFINE_STRUCT_HPP
diff --git a/boost/hana/fwd/difference.hpp b/boost/hana/fwd/difference.hpp
new file mode 100644
index 0000000000..74c8e9ccee
--- /dev/null
+++ b/boost/hana/fwd/difference.hpp
@@ -0,0 +1,72 @@
+/*!
+@file
+Forward declares `boost::hana::difference`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_DIFFERENCE_HPP
+#define BOOST_HANA_FWD_DIFFERENCE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns the set-theoretic difference of two sets.
+ //! @relates hana::set
+ //!
+ //! Given two sets `xs` and `ys`, `difference(xs, ys)` is a new set
+ //! containing all the elements of `xs` that are _not_ contained in `ys`.
+ //! For any object `x`, the following holds:
+ //! @code
+ //! x ^in^ difference(xs, ys) if and only if x ^in^ xs && !(x ^in^ ys)
+ //! @endcode
+ //!
+ //!
+ //! @note
+ //! This operation is not commutative, i.e. `difference(xs, ys)` is not
+ //! necessarily the same as `difference(ys, xs)`. Indeed, consider the
+ //! case where `xs` is empty and `ys` isn't. Then, `difference(xs, ys)`
+ //! is empty but `difference(ys, xs)` is equal to `ys`. For the symmetric
+ //! version of this operation, see `symmetric_difference`.
+ //!
+ //!
+ //! @param xs
+ //! A set to remove values from.
+ //!
+ //! @param ys
+ //! The set whose values are removed from `xs`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/difference.cpp
+ //!
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.difference.compile.json">
+ //! </div>
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto difference = [](auto&& xs, auto&& ys) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct difference_impl : difference_impl<S, when<true>> { };
+
+ struct difference_t {
+ template <typename Xs, typename Ys>
+ constexpr auto operator()(Xs&& xs, Ys&& ys) const;
+ };
+
+ constexpr difference_t difference{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_DIFFERENCE_HPP
diff --git a/boost/hana/fwd/div.hpp b/boost/hana/fwd/div.hpp
new file mode 100644
index 0000000000..82684d7162
--- /dev/null
+++ b/boost/hana/fwd/div.hpp
@@ -0,0 +1,59 @@
+/*!
+@file
+Forward declares `boost::hana::div`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_DIV_HPP
+#define BOOST_HANA_FWD_DIV_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Generalized integer division.
+ //! @ingroup group-EuclideanRing
+ //!
+ //!
+ //! Cross-type version of the method
+ //! --------------------------------
+ //! The `div` method is "overloaded" to handle distinct data types
+ //! with certain properties. Specifically, `div` is defined for
+ //! _distinct_ data types `A` and `B` such that
+ //! 1. `A` and `B` share a common data type `C`, as determined by the
+ //! `common` metafunction
+ //! 2. `A`, `B` and `C` are all `EuclideanRing`s when taken individually
+ //! 3. `to<C> : A -> B` and `to<C> : B -> C` are `Ring`-embeddings, as
+ //! determined by the `is_embedding` metafunction.
+ //!
+ //! In that case, the `div` method is defined as
+ //! @code
+ //! div(x, y) = div(to<C>(x), to<C>(y))
+ //! @endcode
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/div.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto div = [](auto&& x, auto&& y) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename U, typename = void>
+ struct div_impl : div_impl<T, U, when<true>> { };
+
+ struct div_t {
+ template <typename X, typename Y>
+ constexpr decltype(auto) operator()(X&& x, Y&& y) const;
+ };
+
+ constexpr div_t div{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_DIV_HPP
diff --git a/boost/hana/fwd/drop_back.hpp b/boost/hana/fwd/drop_back.hpp
new file mode 100644
index 0000000000..814382e855
--- /dev/null
+++ b/boost/hana/fwd/drop_back.hpp
@@ -0,0 +1,63 @@
+/*!
+@file
+Forward declares `boost::hana::drop_back`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_DROP_BACK_HPP
+#define BOOST_HANA_FWD_DROP_BACK_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Drop the last `n` elements of a finite sequence, and return the rest.
+ //! @ingroup group-Sequence
+ //!
+ //! Given a finite `Sequence` `xs` with a linearization of `[x1, ..., xm]`
+ //! and a non-negative `IntegralConstant` `n`, `drop_back(xs, n)` is a
+ //! sequence with the same tag as `xs` whose linearization is
+ //! `[x1, ..., xm-n]`. If `n` is not given, it defaults to an
+ //! `IntegralConstant` with a value equal to `1`.
+ //!
+ //! In case `length(xs) <= n`, `drop_back` will simply drop the whole
+ //! sequence without failing, thus returning an empty sequence.
+ //!
+ //!
+ //! @param xs
+ //! The sequence from which elements are dropped.
+ //!
+ //! @param n
+ //! A non-negative `IntegralConstant` representing the number of elements
+ //! to be dropped from the end of the sequence. If `n` is not given, it
+ //! defaults to an `IntegralConstant` with a value equal to `1`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/drop_back.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto drop_back = [](auto&& xs[, auto const& n]) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct drop_back_impl : drop_back_impl<S, when<true>> { };
+
+ struct drop_back_t {
+ template <typename Xs, typename N>
+ constexpr auto operator()(Xs&& xs, N const& n) const;
+
+ template <typename Xs>
+ constexpr auto operator()(Xs&& xs) const;
+ };
+
+ constexpr drop_back_t drop_back{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_DROP_BACK_HPP
diff --git a/boost/hana/fwd/drop_front.hpp b/boost/hana/fwd/drop_front.hpp
new file mode 100644
index 0000000000..b76c710ef7
--- /dev/null
+++ b/boost/hana/fwd/drop_front.hpp
@@ -0,0 +1,66 @@
+/*!
+@file
+Forward declares `boost::hana::drop_front`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_DROP_FRONT_HPP
+#define BOOST_HANA_FWD_DROP_FRONT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Drop the first `n` elements of an iterable, and return the rest.
+ //! @ingroup group-Iterable
+ //!
+ //! Given an `Iterable` `xs` with a linearization of `[x1, x2, ...]` and
+ //! a non-negative `IntegralConstant` `n`, `drop_front(xs, n)` is an
+ //! iterable with the same tag as `xs` whose linearization is
+ //! `[xn+1, xn+2, ...]`. In particular, note that this function does not
+ //! mutate the original iterable in any way. If `n` is not given, it
+ //! defaults to an `IntegralConstant` with a value equal to `1`.
+ //!
+ //! In case `length(xs) <= n`, `drop_front` will simply drop the whole
+ //! iterable without failing, thus returning an empty iterable. This is
+ //! different from `drop_front_exactly`, which expects `n <= length(xs)`
+ //! but can be better optimized because of this additional guarantee.
+ //!
+ //!
+ //! @param xs
+ //! The iterable from which elements are dropped.
+ //!
+ //! @param n
+ //! A non-negative `IntegralConstant` representing the number of elements
+ //! to be dropped from the iterable. If `n` is not given, it defaults to
+ //! an `IntegralConstant` with a value equal to `1`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/drop_front.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto drop_front = [](auto&& xs[, auto const& n]) {
+ return tag-dispatched;
+ };
+#else
+ template <typename It, typename = void>
+ struct drop_front_impl : drop_front_impl<It, when<true>> { };
+
+ struct drop_front_t {
+ template <typename Xs, typename N>
+ constexpr auto operator()(Xs&& xs, N const& n) const;
+
+ template <typename Xs>
+ constexpr auto operator()(Xs&& xs) const;
+ };
+
+ constexpr drop_front_t drop_front{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_DROP_FRONT_HPP
diff --git a/boost/hana/fwd/drop_front_exactly.hpp b/boost/hana/fwd/drop_front_exactly.hpp
new file mode 100644
index 0000000000..3cb11d76a7
--- /dev/null
+++ b/boost/hana/fwd/drop_front_exactly.hpp
@@ -0,0 +1,67 @@
+/*!
+@file
+Forward declares `boost::hana::drop_front_exactly`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_DROP_FRONT_EXACTLY_HPP
+#define BOOST_HANA_FWD_DROP_FRONT_EXACTLY_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Drop the first `n` elements of an iterable, and return the rest.
+ //! @ingroup group-Iterable
+ //!
+ //! Given an `Iterable` `xs` with a linearization of `[x1, x2, ...]` and
+ //! a non-negative `IntegralConstant` `n`, `drop_front_exactly(xs, n)` is
+ //! an iterable with the same tag as `xs` whose linearization is
+ //! `[xn+1, xn+2, ...]`. In particular, note that this function does not
+ //! mutate the original iterable in any way. If `n` is not given, it
+ //! defaults to an `IntegralConstant` with a value equal to `1`.
+ //!
+ //! It is an error to use `drop_front_exactly` with `n > length(xs)`. This
+ //! additional guarantee allows `drop_front_exactly` to be better optimized
+ //! than the `drop_front` function, which allows `n > length(xs)`.
+ //!
+ //!
+ //! @param xs
+ //! The iterable from which elements are dropped.
+ //!
+ //! @param n
+ //! A non-negative `IntegralConstant` representing the number of elements
+ //! to be dropped from the iterable. In addition to being non-negative,
+ //! `n` must be less than or equal to the number of elements in `xs`.
+ //! If `n` is not given, it defaults to an `IntegralConstant` with a value
+ //! equal to `1`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/drop_front_exactly.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto drop_front_exactly = [](auto&& xs[, auto const& n]) {
+ return tag-dispatched;
+ };
+#else
+ template <typename It, typename = void>
+ struct drop_front_exactly_impl : drop_front_exactly_impl<It, when<true>> { };
+
+ struct drop_front_exactly_t {
+ template <typename Xs, typename N>
+ constexpr auto operator()(Xs&& xs, N const& n) const;
+
+ template <typename Xs>
+ constexpr auto operator()(Xs&& xs) const;
+ };
+
+ constexpr drop_front_exactly_t drop_front_exactly{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_DROP_FRONT_EXACTLY_HPP
diff --git a/boost/hana/fwd/drop_while.hpp b/boost/hana/fwd/drop_while.hpp
new file mode 100644
index 0000000000..ef555f8609
--- /dev/null
+++ b/boost/hana/fwd/drop_while.hpp
@@ -0,0 +1,60 @@
+/*!
+@file
+Forward declares `boost::hana::drop_while`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_DROP_WHILE_HPP
+#define BOOST_HANA_FWD_DROP_WHILE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Drop elements from an iterable up to, but excluding, the first
+ //! element for which the `predicate` is not satisfied.
+ //! @ingroup group-Iterable
+ //!
+ //! Specifically, `drop_while` returns an iterable containing all the
+ //! elements of the original iterable except for those in the range
+ //! delimited by [`head`, `e`), where `head` is the first element and
+ //! `e` is the first element for which the `predicate` is not satisfied.
+ //! If the iterable is not finite, the `predicate` has to return a false-
+ //! valued `Logical` at a finite index for this method to return.
+ //!
+ //!
+ //! @param iterable
+ //! The iterable from which elements are dropped.
+ //!
+ //! @param predicate
+ //! A function called as `predicate(x)`, where `x` is an element of the
+ //! structure, and returning a `Logical` representing whether `x` should
+ //! be dropped from the structure. In the current version of the library,
+ //! `predicate` should return a compile-time `Logical`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/drop_while.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto drop_while = [](auto&& iterable, auto&& predicate) {
+ return tag-dispatched;
+ };
+#else
+ template <typename It, typename = void>
+ struct drop_while_impl : drop_while_impl<It, when<true>> { };
+
+ struct drop_while_t {
+ template <typename Xs, typename Pred>
+ constexpr auto operator()(Xs&& xs, Pred&& pred) const;
+ };
+
+ constexpr drop_while_t drop_while{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWDDROP_WHILE_HPP
diff --git a/boost/hana/fwd/duplicate.hpp b/boost/hana/fwd/duplicate.hpp
new file mode 100644
index 0000000000..b1a0af242b
--- /dev/null
+++ b/boost/hana/fwd/duplicate.hpp
@@ -0,0 +1,57 @@
+/*!
+@file
+Forward declares `boost::hana::duplicate`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_DUPLICATE_HPP
+#define BOOST_HANA_FWD_DUPLICATE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Add an extra layer of comonadic context to a comonadic value.
+ //! @ingroup group-Comonad
+ //!
+ //! Given a value already in a comonadic context, `duplicate` wraps this
+ //! value with an additional layer of comonadic context. This can be seen
+ //! as the dual operation to `flatten` from the Monad concept.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a Comonad `W`, the signature is
+ //! \f$
+ //! \mathtt{duplicate} : W(T) \to W(W(T))
+ //! \f$
+ //!
+ //! @param w
+ //! The value to wrap in an additional level of comonadic context.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/duplicate.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto duplicate = [](auto&& w) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename W, typename = void>
+ struct duplicate_impl : duplicate_impl<W, when<true>> { };
+
+ struct duplicate_t {
+ template <typename W_>
+ constexpr decltype(auto) operator()(W_&& w) const;
+ };
+
+ constexpr duplicate_t duplicate{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_DUPLICATE_HPP
diff --git a/boost/hana/fwd/empty.hpp b/boost/hana/fwd/empty.hpp
new file mode 100644
index 0000000000..90a3696357
--- /dev/null
+++ b/boost/hana/fwd/empty.hpp
@@ -0,0 +1,51 @@
+/*!
+@file
+Forward declares `boost::hana::empty`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_EMPTY_HPP
+#define BOOST_HANA_FWD_EMPTY_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Identity of the monadic combination `concat`.
+ //! @ingroup group-MonadPlus
+ //!
+ //! Signature
+ //! ---------
+ //! Given a MonadPlus `M`, the signature is
+ //! @f$ \mathtt{empty}_M : \emptyset \to M(T) @f$.
+ //!
+ //! @tparam M
+ //! The tag of the monadic structure to return. This must be
+ //! a model of the MonadPlus concept.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/empty.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename M>
+ constexpr auto empty = []() {
+ return tag-dispatched;
+ };
+#else
+ template <typename M, typename = void>
+ struct empty_impl : empty_impl<M, when<true>> { };
+
+ template <typename M>
+ struct empty_t;
+
+ template <typename M>
+ constexpr empty_t<M> empty{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_EMPTY_HPP
diff --git a/boost/hana/fwd/equal.hpp b/boost/hana/fwd/equal.hpp
new file mode 100644
index 0000000000..e72614407d
--- /dev/null
+++ b/boost/hana/fwd/equal.hpp
@@ -0,0 +1,80 @@
+/*!
+@file
+Forward declares `boost::hana::equal`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_EQUAL_HPP
+#define BOOST_HANA_FWD_EQUAL_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/detail/nested_to_fwd.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns a `Logical` representing whether `x` is equal to `y`.
+ //! @ingroup group-Comparable
+ //!
+ //! The `equal` function can be called in two different ways. First, it
+ //! can be called like a normal function:
+ //! @code
+ //! equal(x, y)
+ //! @endcode
+ //!
+ //! However, it may also be partially applied to an argument by using
+ //! `equal.to`:
+ //! @code
+ //! equal.to(x)(y) == equal(x, y)
+ //! @endcode
+ //!
+ //! In other words, `equal.to(x)` is a function object that is equivalent
+ //! to `partial(equal, x)`. This is provided to enhance the readability of
+ //! some constructs, especially when using higher order algorithms.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a Logical `Bool` and two Comparables `A` and `B` that
+ //! share a common embedding, the signature is
+ //! @f$ \mathtt{equal} : A \times B \to Bool @f$.
+ //!
+ //! @param x, y
+ //! Two objects to compare for equality.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/equal.cpp
+ //!
+ //!
+ //! > #### Rationale for the arity of `equal`
+ //! > It is a valid question whether `equal` should accept more than 2
+ //! > arguments and have semantics matching those of Python's `==`. This
+ //! > is not supported right now for the following reasons:
+ //! > - It was implemented in the MPL11, but it was not shown to be useful
+ //! > so far.
+ //! > - It does not make sense for `not_equal` to have an arity of more
+ //! > than 2, only `equal` could maybe have those semantics, which would
+ //! > break symmetry.
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto equal = [](auto&& x, auto&& y) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename U, typename = void>
+ struct equal_impl : equal_impl<T, U, when<true>> { };
+
+ struct equal_t : detail::nested_to<equal_t> {
+ template <typename X, typename Y>
+ constexpr auto operator()(X&& x, Y&& y) const;
+ };
+
+ constexpr equal_t equal{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_EQUAL_HPP
diff --git a/boost/hana/fwd/erase_key.hpp b/boost/hana/fwd/erase_key.hpp
new file mode 100644
index 0000000000..4612424802
--- /dev/null
+++ b/boost/hana/fwd/erase_key.hpp
@@ -0,0 +1,32 @@
+/*!
+@file
+Forward declares `boost::hana::erase_key`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_ERASE_KEY_HPP
+#define BOOST_HANA_FWD_ERASE_KEY_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ // Note: This function is documented per datatype/concept only.
+ //! @cond
+ template <typename T, typename = void>
+ struct erase_key_impl : erase_key_impl<T, when<true>> { };
+ //! @endcond
+
+ struct erase_key_t {
+ template <typename Set, typename ...Args>
+ constexpr decltype(auto) operator()(Set&& set, Args&& ...args) const;
+ };
+
+ constexpr erase_key_t erase_key{};
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_ERASE_KEY_HPP
diff --git a/boost/hana/fwd/eval.hpp b/boost/hana/fwd/eval.hpp
new file mode 100644
index 0000000000..d1d0b7f488
--- /dev/null
+++ b/boost/hana/fwd/eval.hpp
@@ -0,0 +1,58 @@
+/*!
+@file
+Forward declares `boost::hana::eval`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_EVAL_HPP
+#define BOOST_HANA_FWD_EVAL_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Evaluate a lazy value and return it.
+ //! @relates hana::lazy
+ //!
+ //! Given a lazy expression `expr`, `eval` evaluates `expr` and returns
+ //! the result as a normal value. However, for convenience, `eval` can
+ //! also be used with nullary and unary function objects. Specifically,
+ //! if `expr` is not a `hana::lazy`, it is called with no arguments at
+ //! all and the result of that call (`expr()`) is returned. Otherwise,
+ //! if `expr()` is ill-formed, then `expr(hana::id)` is returned instead.
+ //! If that expression is ill-formed, then a compile-time error is
+ //! triggered.
+ //!
+ //! The reason for allowing nullary callables in `eval` is because this
+ //! allows using nullary lambdas as lazy branches to `eval_if`, which
+ //! is convenient. The reason for allowing unary callables and calling
+ //! them with `hana::id` is because this allows deferring the
+ //! compile-time evaluation of selected expressions inside the callable.
+ //! How this can be achieved is documented by `hana::eval_if`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/eval.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto eval = [](auto&& see_documentation) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename = void>
+ struct eval_impl : eval_impl<T, when<true>> { };
+
+ struct eval_t {
+ template <typename Expr>
+ constexpr decltype(auto) operator()(Expr&& expr) const;
+ };
+
+ constexpr eval_t eval{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_EVAL_HPP
diff --git a/boost/hana/fwd/eval_if.hpp b/boost/hana/fwd/eval_if.hpp
new file mode 100644
index 0000000000..865e561c99
--- /dev/null
+++ b/boost/hana/fwd/eval_if.hpp
@@ -0,0 +1,155 @@
+/*!
+@file
+Forward declares `boost::hana::eval_if`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_EVAL_IF_HPP
+#define BOOST_HANA_FWD_EVAL_IF_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Conditionally execute one of two branches based on a condition.
+ //! @ingroup group-Logical
+ //!
+ //! Given a condition and two branches in the form of lambdas or
+ //! `hana::lazy`s, `eval_if` will evaluate the branch selected by the
+ //! condition with `eval` and return the result. The exact requirements
+ //! for what the branches may be are the same requirements as those for
+ //! the `eval` function.
+ //!
+ //!
+ //! Deferring compile-time evaluation inside `eval_if`
+ //! --------------------------------------------------
+ //! By passing a unary callable to `eval_if`, it is possible to defer
+ //! the compile-time evaluation of selected expressions inside the
+ //! lambda. This is useful when instantiating a branch would trigger
+ //! a compile-time error; we only want the branch to be instantiated
+ //! when that branch is selected. Here's how it can be achieved.
+ //!
+ //! For simplicity, we'll use a unary lambda as our unary callable.
+ //! Our lambda must accept a parameter (usually called `_`), which
+ //! can be used to defer the compile-time evaluation of expressions
+ //! as required. For example,
+ //! @code
+ //! template <typename N>
+ //! auto fact(N n) {
+ //! return hana::eval_if(n == hana::int_c<0>,
+ //! [] { return hana::int_c<1>; },
+ //! [=](auto _) { return n * fact(_(n) - hana::int_c<1>); }
+ //! );
+ //! }
+ //! @endcode
+ //!
+ //! What happens here is that `eval_if` will call `eval` on the selected
+ //! branch. In turn, `eval` will call the selected branch either with
+ //! nothing -- for the _then_ branch -- or with `hana::id` -- for the
+ //! _else_ branch. Hence, `_(x)` is always the same as `x`, but the
+ //! compiler can't tell until the lambda has been called! Hence, the
+ //! compiler has to wait before it instantiates the body of the lambda
+ //! and no infinite recursion happens. However, this trick to delay the
+ //! instantiation of the lambda's body can only be used when the condition
+ //! is known at compile-time, because otherwise both branches have to be
+ //! instantiated inside the `eval_if` anyway.
+ //!
+ //! There are several caveats to note with this approach to lazy branching.
+ //! First, because we're using lambdas, it means that the function's
+ //! result can't be used in a constant expression. This is a limitation
+ //! of the current language.
+ //!
+ //! The second caveat is that compilers currently have several bugs
+ //! regarding deeply nested lambdas with captures. So you always risk
+ //! crashing the compiler, but this is a question of time before it is
+ //! not a problem anymore.
+ //!
+ //! Finally, it means that conditionals can't be written directly inside
+ //! unevaluated contexts. The reason is that a lambda can't appear in an
+ //! unevaluated context, for example in `decltype`. One way to workaround
+ //! this is to completely lift your type computations into variable
+ //! templates instead. For example, instead of writing
+ //! @code
+ //! template <typename T>
+ //! struct pointerize : decltype(
+ //! hana::eval_if(hana::traits::is_pointer(hana::type_c<T>),
+ //! [] { return hana::type_c<T>; },
+ //! [](auto _) { return _(hana::traits::add_pointer)(hana::type_c<T>); }
+ //! ))
+ //! { };
+ //! @endcode
+ //!
+ //! you could instead write
+ //!
+ //! @code
+ //! template <typename T>
+ //! auto pointerize_impl(T t) {
+ //! return hana::eval_if(hana::traits::is_pointer(t),
+ //! [] { return hana::type_c<T>; },
+ //! [](auto _) { return _(hana::traits::add_pointer)(hana::type_c<T>); }
+ //! );
+ //! }
+ //!
+ //! template <typename T>
+ //! using pointerize = decltype(pointerize_impl(hana::type_c<T>));
+ //! @endcode
+ //!
+ //! > __Note__: This example would actually be implemented more easily
+ //! > with partial specializations, but my bag of good examples is empty
+ //! > at the time of writing this.
+ //!
+ //! Now, this hoop-jumping only has to be done in one place, because
+ //! you should use normal function notation everywhere else in your
+ //! metaprogram to perform type computations. So the syntactic
+ //! cost is amortized over the whole program.
+ //!
+ //! Another way to work around this limitation of the language would be
+ //! to use `hana::lazy` for the branches. However, this is only suitable
+ //! when the branches are not too complicated. With `hana::lazy`, you
+ //! could write the previous example as
+ //! @code
+ //! template <typename T>
+ //! struct pointerize : decltype(
+ //! hana::eval_if(hana::traits::is_pointer(hana::type_c<T>),
+ //! hana::make_lazy(hana::type_c<T>),
+ //! hana::make_lazy(hana::traits::add_pointer)(hana::type_c<T>)
+ //! ))
+ //! { };
+ //! @endcode
+ //!
+ //!
+ //! @param cond
+ //! The condition determining which of the two branches is selected.
+ //!
+ //! @param then
+ //! An expression called as `eval(then)` if `cond` is true-valued.
+ //!
+ //! @param else_
+ //! A function called as `eval(else_)` if `cond` is false-valued.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/eval_if.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto eval_if = [](auto&& cond, auto&& then, auto&& else_) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename L, typename = void>
+ struct eval_if_impl : eval_if_impl<L, when<true>> { };
+
+ struct eval_if_t {
+ template <typename Cond, typename Then, typename Else>
+ constexpr decltype(auto) operator()(Cond&& cond, Then&& then, Else&& else_) const;
+ };
+
+ constexpr eval_if_t eval_if{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_EVAL_IF_HPP
diff --git a/boost/hana/fwd/extend.hpp b/boost/hana/fwd/extend.hpp
new file mode 100644
index 0000000000..6cbf1ffc2b
--- /dev/null
+++ b/boost/hana/fwd/extend.hpp
@@ -0,0 +1,62 @@
+/*!
+@file
+Forward declares `boost::hana::extend`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_EXTEND_HPP
+#define BOOST_HANA_FWD_EXTEND_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Comonadic application of a function to a comonadic value.
+ //! @ingroup group-Comonad
+ //!
+ //! Given a comonadic value and a function accepting a comonadic input,
+ //! `extend` returns the result of applying the function to that input
+ //! inside the comonadic context.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a Comonad `W` and a function of type \f$ W(T) \to U \f$, the
+ //! signature is
+ //! \f$
+ //! \mathtt{extend} : W(T) \times (W(T) \to U) \to W(U)
+ //! \f$
+ //!
+ //! @param w
+ //! A comonadic value to call the function with.
+ //!
+ //! @param f
+ //! A function of signature \f$ W(T) \to U \f$ to be applied to its
+ //! comonadic argument inside the comonadic context.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/extend.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto extend = [](auto&& w, auto&& f) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename W, typename = void>
+ struct extend_impl : extend_impl<W, when<true>> { };
+
+ struct extend_t {
+ template <typename W_, typename F>
+ constexpr decltype(auto) operator()(W_&& w, F&& f) const;
+ };
+
+ constexpr extend_t extend{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_EXTEND_HPP
diff --git a/boost/hana/fwd/extract.hpp b/boost/hana/fwd/extract.hpp
new file mode 100644
index 0000000000..8a9917bc66
--- /dev/null
+++ b/boost/hana/fwd/extract.hpp
@@ -0,0 +1,58 @@
+/*!
+@file
+Forward declares `boost::hana::extract`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_EXTRACT_HPP
+#define BOOST_HANA_FWD_EXTRACT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Extract a value in a given comonadic context.
+ //! @ingroup group-Comonad
+ //!
+ //! Given a value inside a comonadic context, extract it from that
+ //! context, performing whatever effects are mandated by that context.
+ //! This can be seen as the dual operation to the `lift` method of the
+ //! Applicative concept.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a Comonad `W`, the signature is
+ //! \f$
+ //! \mathtt{extract} : W(T) \to T
+ //! \f$
+ //!
+ //! @param w
+ //! The value to be extracted inside a comonadic context.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/extract.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto extract = [](auto&& w) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename W, typename = void>
+ struct extract_impl : extract_impl<W, when<true>> { };
+
+ struct extract_t {
+ template <typename W_>
+ constexpr decltype(auto) operator()(W_&& w) const;
+ };
+
+ constexpr extract_t extract{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_EXTRACT_HPP
diff --git a/boost/hana/fwd/fill.hpp b/boost/hana/fwd/fill.hpp
new file mode 100644
index 0000000000..38a4a35c96
--- /dev/null
+++ b/boost/hana/fwd/fill.hpp
@@ -0,0 +1,57 @@
+/*!
+@file
+Forward declares `boost::hana::fill`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_FILL_HPP
+#define BOOST_HANA_FWD_FILL_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Replace all the elements of a structure with a fixed value.
+ //! @ingroup group-Functor
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given `F` a Functor, the signature is
+ //! \f$
+ //! \mathtt{fill} : F(T) \times U \to F(U)
+ //! \f$
+ //!
+ //! @param xs
+ //! The structure to fill with a `value`.
+ //!
+ //! @param value
+ //! A value by which every element `x` of the structure is replaced,
+ //! unconditionally.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/fill.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto fill = [](auto&& xs, auto&& value) {
+ return tag-dispatched;
+ };
+#else
+ template <typename Xs, typename = void>
+ struct fill_impl : fill_impl<Xs, when<true>> { };
+
+ struct fill_t {
+ template <typename Xs, typename Value>
+ constexpr auto operator()(Xs&& xs, Value&& value) const;
+ };
+
+ constexpr fill_t fill{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_FILL_HPP
diff --git a/boost/hana/fwd/filter.hpp b/boost/hana/fwd/filter.hpp
new file mode 100644
index 0000000000..7152361ef7
--- /dev/null
+++ b/boost/hana/fwd/filter.hpp
@@ -0,0 +1,88 @@
+/*!
+@file
+Forward declares `boost::hana::filter`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_FILTER_HPP
+#define BOOST_HANA_FWD_FILTER_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Filter a monadic structure using a custom predicate.
+ //! @ingroup group-MonadPlus
+ //!
+ //! Given a monadic structure and a predicate, `filter` returns a new
+ //! monadic structure containing only those elements that satisfy the
+ //! predicate. This is a generalization of the usual `filter` function
+ //! for sequences; it works for any MonadPlus. Intuitively, `filter` is
+ //! somewhat equivalent to:
+ //! @code
+ //! filter(xs, pred) == flatten(transform(xs, [](auto x) {
+ //! return pred(x) ? lift<Xs>(x) : empty<Xs>();
+ //! })
+ //! @endcode
+ //! In other words, we basically turn a monadic structure containing
+ //! `[x1, ..., xn]` into a monadic structure containing
+ //! @code
+ //! [
+ //! pred(x1) ? [x1] : [],
+ //! pred(x2) ? [x2] : [],
+ //! ...
+ //! pred(xn) ? [xn] : []
+ //! ]
+ //! @endcode
+ //! and we then `flatten` that.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a `MonadPlus` `M` and an `IntegralConstant` `Bool` holding a
+ //! value of type `bool`, the signature is
+ //! @f$ \mathtt{filter} : M(T) \times (T \to \mathtt{Bool}) \to M(T) @f$.
+ //!
+ //! @param xs
+ //! The monadic structure to filter.
+ //!
+ //! @param pred
+ //! A function called as `pred(x)` for each element `x` in the monadic
+ //! structure and returning whether that element should be __kept__ in
+ //! the resulting structure. In the current version of the library, the
+ //! predicate has to return an `IntegralConstant` holding a value
+ //! convertible to a `bool`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/filter.cpp
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.filter.compile.json">
+ //! </div>
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto filter = [](auto&& xs, auto&& pred) {
+ return tag-dispatched;
+ };
+#else
+ template <typename M, typename = void>
+ struct filter_impl : filter_impl<M, when<true>> { };
+
+ struct filter_t {
+ template <typename Xs, typename Pred>
+ constexpr auto operator()(Xs&& xs, Pred&& pred) const;
+ };
+
+ constexpr filter_t filter{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_FILTER_HPP
diff --git a/boost/hana/fwd/find.hpp b/boost/hana/fwd/find.hpp
new file mode 100644
index 0000000000..00c74d1a43
--- /dev/null
+++ b/boost/hana/fwd/find.hpp
@@ -0,0 +1,60 @@
+/*!
+@file
+Forward declares `boost::hana::find`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_FIND_HPP
+#define BOOST_HANA_FWD_FIND_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Finds the value associated to the given key in a structure.
+ //! @ingroup group-Searchable
+ //!
+ //! Given a `key` and a `Searchable` structure, `find` returns the `just`
+ //! the first value whose key is equal to the given `key`, or `nothing` if
+ //! there is no such key. Comparison is done with `equal`. `find` satisfies
+ //! the following:
+ //! @code
+ //! find(xs, key) == find_if(xs, equal.to(key))
+ //! @endcode
+ //!
+ //!
+ //! @param xs
+ //! The structure to be searched.
+ //!
+ //! @param key
+ //! A key to be searched for in the structure. The key has to be
+ //! `Comparable` with the other keys of the structure. In the current
+ //! version of the library, the comparison of `key` with any other key
+ //! of the structure must return a compile-time `Logical`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/find.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto find = [](auto&& xs, auto const& key) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct find_impl : find_impl<S, when<true>> { };
+
+ struct find_t {
+ template <typename Xs, typename Key>
+ constexpr auto operator()(Xs&& xs, Key const& key) const;
+ };
+
+ constexpr find_t find{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_FIND_HPP
diff --git a/boost/hana/fwd/find_if.hpp b/boost/hana/fwd/find_if.hpp
new file mode 100644
index 0000000000..6308086944
--- /dev/null
+++ b/boost/hana/fwd/find_if.hpp
@@ -0,0 +1,64 @@
+/*!
+@file
+Forward declares `boost::hana::find_if`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_FIND_IF_HPP
+#define BOOST_HANA_FWD_FIND_IF_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Finds the value associated to the first key satisfying a predicate.
+ //! @ingroup group-Searchable
+ //!
+ //! Given a `Searchable` structure `xs` and a predicate `pred`,
+ //! `find_if(xs, pred)` returns `just` the first element whose key
+ //! satisfies the predicate, or `nothing` if there is no such element.
+ //!
+ //!
+ //! @param xs
+ //! The structure to be searched.
+ //!
+ //! @param predicate
+ //! A function called as `predicate(k)`, where `k` is a key of the
+ //! structure, and returning whether `k` is the key of the element
+ //! being searched for. In the current version of the library, the
+ //! predicate has to return an `IntegralConstant` holding a value
+ //! that can be converted to `bool`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/find_if.cpp
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.find_if.compile.json">
+ //! </div>
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto find_if = [](auto&& xs, auto&& predicate) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct find_if_impl : find_if_impl<S, when<true>> { };
+
+ struct find_if_t {
+ template <typename Xs, typename Pred>
+ constexpr auto operator()(Xs&& xs, Pred&& pred) const;
+ };
+
+ constexpr find_if_t find_if{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_FIND_IF_HPP
diff --git a/boost/hana/fwd/first.hpp b/boost/hana/fwd/first.hpp
new file mode 100644
index 0000000000..8cfef1472e
--- /dev/null
+++ b/boost/hana/fwd/first.hpp
@@ -0,0 +1,49 @@
+/*!
+@file
+Forward declares `boost::hana::first`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_FIRST_HPP
+#define BOOST_HANA_FWD_FIRST_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns the first element of a pair.
+ //! @ingroup group-Product
+ //!
+ //! Note that if the `Product` actually stores the elements it contains,
+ //! `hana::first` is required to return a lvalue reference, a lvalue
+ //! reference to const or a rvalue reference to the first element, where
+ //! the type of reference must match that of the pair passed to `first`.
+ //! If the `Product` does not store the elements it contains (i.e. it
+ //! generates them on demand), this requirement is dropped.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/first.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto first = [](auto&& product) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename P, typename = void>
+ struct first_impl : first_impl<P, when<true>> { };
+
+ struct first_t {
+ template <typename Pair>
+ constexpr decltype(auto) operator()(Pair&& pair) const;
+ };
+
+ constexpr first_t first{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_FIRST_HPP
diff --git a/boost/hana/fwd/flatten.hpp b/boost/hana/fwd/flatten.hpp
new file mode 100644
index 0000000000..42c83f8f22
--- /dev/null
+++ b/boost/hana/fwd/flatten.hpp
@@ -0,0 +1,63 @@
+/*!
+@file
+Forward declares `boost::hana::flatten`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_FLATTEN_HPP
+#define BOOST_HANA_FWD_FLATTEN_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Collapse two levels of monadic structure into a single level.
+ //! @ingroup group-Monad
+ //!
+ //! Given a monadic value wrapped into two levels of monad, `flatten`
+ //! removes one such level. An implementation of `flatten` must satisfy
+ //! @code
+ //! flatten(xs) == chain(xs, id)
+ //! @endcode
+ //!
+ //! For `Sequence`s, this simply takes a `Sequence` of `Sequence`s, and
+ //! returns a (non-recursively) flattened `Sequence`.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! For a `Monad` `M`, the signature of `flatten` is
+ //! @f$
+ //! \mathtt{flatten} : M(M(T)) \to M(T)
+ //! @f$
+ //!
+ //! @param xs
+ //! A value with two levels of monadic structure, which should be
+ //! collapsed into a single level of structure.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/flatten.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto flatten = [](auto&& xs) {
+ return tag-dispatched;
+ };
+#else
+ template <typename M, typename = void>
+ struct flatten_impl : flatten_impl<M, when<true>> { };
+
+ struct flatten_t {
+ template <typename Xs>
+ constexpr auto operator()(Xs&& xs) const;
+ };
+
+ constexpr flatten_t flatten{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_FLATTEN_HPP
diff --git a/boost/hana/fwd/fold.hpp b/boost/hana/fwd/fold.hpp
new file mode 100644
index 0000000000..f34961d507
--- /dev/null
+++ b/boost/hana/fwd/fold.hpp
@@ -0,0 +1,38 @@
+/*!
+@file
+Forward declares `boost::hana::fold`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_FOLD_HPP
+#define BOOST_HANA_FWD_FOLD_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/fwd/fold_left.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Equivalent to `fold_left`; provided for convenience.
+ //! @ingroup group-Foldable
+ //!
+ //! `fold` is equivalent to `fold_left`. However, it is not tag-dispatched
+ //! on its own because it is just an alias to `fold_left`. Also note that
+ //! `fold` can be called with or without an initial state, just like
+ //! `fold_left`:
+ //!
+ //! @code
+ //! fold(xs, state, f) == fold_left(xs, state, f)
+ //! fold(xs, f) == fold_left(xs, f)
+ //! @endcode
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/fold.cpp
+ constexpr auto fold = fold_left;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_FOLD_HPP
diff --git a/boost/hana/fwd/fold_left.hpp b/boost/hana/fwd/fold_left.hpp
new file mode 100644
index 0000000000..061956ce9c
--- /dev/null
+++ b/boost/hana/fwd/fold_left.hpp
@@ -0,0 +1,96 @@
+/*!
+@file
+Forward declares `boost::hana::fold_left`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_FOLD_LEFT_HPP
+#define BOOST_HANA_FWD_FOLD_LEFT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Left-fold of a structure using a binary operation and an optional
+ //! initial reduction state.
+ //! @ingroup group-Foldable
+ //!
+ //! `fold_left` is a left-associative fold using a binary operation.
+ //! Given a structure containing `x1, ..., xn`, a function `f` and
+ //! an optional initial state, `fold_left` applies `f` as follows
+ //! @code
+ //! f(... f(f(f(x1, x2), x3), x4) ..., xn) // without state
+ //! f(... f(f(f(f(state, x1), x2), x3), x4) ..., xn) // with state
+ //! @endcode
+ //!
+ //! When the structure is empty, two things may arise. If an initial
+ //! state was provided, it is returned as-is. Otherwise, if the no-state
+ //! version of the function was used, an error is triggered. When the
+ //! stucture contains a single element and the no-state version of the
+ //! function was used, that single element is returned as is.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a `Foldable` `F` and an optional initial state of tag `S`,
+ //! the signatures for `fold_left` are
+ //! \f[
+ //! \mathtt{fold\_left} : F(T) \times S \times (S \times T \to S) \to S
+ //! \f]
+ //!
+ //! for the variant with an initial state, and
+ //! \f[
+ //! \mathtt{fold\_left} : F(T) \times (T \times T \to T) \to T
+ //! \f]
+ //!
+ //! for the variant without an initial state.
+ //!
+ //! @param xs
+ //! The structure to fold.
+ //!
+ //! @param state
+ //! The initial value used for folding.
+ //!
+ //! @param f
+ //! A binary function called as `f(state, x)`, where `state` is the
+ //! result accumulated so far and `x` is an element in the structure.
+ //! For left folds without an initial state, the function is called as
+ //! `f(x1, x2)`, where `x1` and `x2` are elements of the structure.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/fold_left.cpp
+ //!
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.fold_left.compile.json">
+ //! </div>
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto fold_left = [](auto&& xs[, auto&& state], auto&& f) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename = void>
+ struct fold_left_impl : fold_left_impl<T, when<true>> { };
+
+ struct fold_left_t {
+ template <typename Xs, typename State, typename F>
+ constexpr decltype(auto) operator()(Xs&& xs, State&& state, F&& f) const;
+
+ template <typename Xs, typename F>
+ constexpr decltype(auto) operator()(Xs&& xs, F&& f) const;
+ };
+
+ constexpr fold_left_t fold_left{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_FOLD_LEFT_HPP
diff --git a/boost/hana/fwd/fold_right.hpp b/boost/hana/fwd/fold_right.hpp
new file mode 100644
index 0000000000..319bbade1a
--- /dev/null
+++ b/boost/hana/fwd/fold_right.hpp
@@ -0,0 +1,100 @@
+/*!
+@file
+Forward declares `boost::hana::fold_right`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_FOLD_RIGHT_HPP
+#define BOOST_HANA_FWD_FOLD_RIGHT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Right-fold of a structure using a binary operation and an optional
+ //! initial reduction state.
+ //! @ingroup group-Foldable
+ //!
+ //! `fold_right` is a right-associative fold using a binary operation.
+ //! Given a structure containing `x1, ..., xn`, a function `f` and
+ //! an optional initial state, `fold_right` applies `f` as follows
+ //! @code
+ //! f(x1, f(x2, f(x3, f(x4, ... f(xn-1, xn) ... )))) // without state
+ //! f(x1, f(x2, f(x3, f(x4, ... f(xn, state) ... )))) // with state
+ //! @endcode
+ //!
+ //! @note
+ //! It is worth noting that the order in which the binary function should
+ //! expect its arguments is reversed from `fold_left`.
+ //!
+ //! When the structure is empty, two things may arise. If an initial
+ //! state was provided, it is returned as-is. Otherwise, if the no-state
+ //! version of the function was used, an error is triggered. When the
+ //! stucture contains a single element and the no-state version of the
+ //! function was used, that single element is returned as is.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a `Foldable` `F` and an optional initial state of tag `S`,
+ //! the signatures for `fold_right` are
+ //! \f[
+ //! \mathtt{fold\_right} : F(T) \times S \times (T \times S \to S) \to S
+ //! \f]
+ //!
+ //! for the variant with an initial state, and
+ //! \f[
+ //! \mathtt{fold\_right} : F(T) \times (T \times T \to T) \to T
+ //! \f]
+ //!
+ //! for the variant without an initial state.
+ //!
+ //! @param xs
+ //! The structure to fold.
+ //!
+ //! @param state
+ //! The initial value used for folding.
+ //!
+ //! @param f
+ //! A binary function called as `f(x, state)`, where `state` is the
+ //! result accumulated so far and `x` is an element in the structure.
+ //! For right folds without an initial state, the function is called as
+ //! `f(x1, x2)`, where `x1` and `x2` are elements of the structure.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/fold_right.cpp
+ //!
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.fold_right.compile.json">
+ //! </div>
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto fold_right = [](auto&& xs[, auto&& state], auto&& f) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename = void>
+ struct fold_right_impl : fold_right_impl<T, when<true>> { };
+
+ struct fold_right_t {
+ template <typename Xs, typename State, typename F>
+ constexpr decltype(auto) operator()(Xs&& xs, State&& state, F&& f) const;
+
+ template <typename Xs, typename F>
+ constexpr decltype(auto) operator()(Xs&& xs, F&& f) const;
+ };
+
+ constexpr fold_right_t fold_right{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_FOLD_RIGHT_HPP
diff --git a/boost/hana/fwd/for_each.hpp b/boost/hana/fwd/for_each.hpp
new file mode 100644
index 0000000000..35c0bd45ce
--- /dev/null
+++ b/boost/hana/fwd/for_each.hpp
@@ -0,0 +1,55 @@
+/*!
+@file
+Forward declares `boost::hana::for_each`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_FOR_EACH_HPP
+#define BOOST_HANA_FWD_FOR_EACH_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Perform an action on each element of a foldable, discarding
+ //! the result each time.
+ //! @ingroup group-Foldable
+ //!
+ //! Iteration is done from left to right, i.e. in the same order as when
+ //! using `fold_left`. If the structure is not finite, this method will
+ //! not terminate.
+ //!
+ //!
+ //! @param xs
+ //! The structure to iterate over.
+ //!
+ //! @param f
+ //! A function called as `f(x)` for each element `x` of the structure.
+ //! The result of `f(x)`, whatever it is, is ignored.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/for_each.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto for_each = [](auto&& xs, auto&& f) -> void {
+ tag-dispatched;
+ };
+#else
+ template <typename T, typename = void>
+ struct for_each_impl : for_each_impl<T, when<true>> { };
+
+ struct for_each_t {
+ template <typename Xs, typename F>
+ constexpr void operator()(Xs&& xs, F&& f) const;
+ };
+
+ constexpr for_each_t for_each{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_FOR_EACH_HPP
diff --git a/boost/hana/fwd/front.hpp b/boost/hana/fwd/front.hpp
new file mode 100644
index 0000000000..805cbdd15d
--- /dev/null
+++ b/boost/hana/fwd/front.hpp
@@ -0,0 +1,48 @@
+/*!
+@file
+Forward declares `boost::hana::front`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_FRONT_HPP
+#define BOOST_HANA_FWD_FRONT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns the first element of a non-empty iterable.
+ //! @ingroup group-Iterable
+ //!
+ //! Given a non-empty Iterable `xs` with a linearization of `[x1, ..., xN]`,
+ //! `front(xs)` is equal to `x1`. If `xs` is empty, it is an error to
+ //! use this function. Equivalently, `front(xs)` must be equivalent to
+ //! `at_c<0>(xs)`, and that regardless of the value category of `xs`
+ //! (`front` must respect the reference semantics of `at`).
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/front.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto front = [](auto&& xs) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename It, typename = void>
+ struct front_impl : front_impl<It, when<true>> { };
+
+ struct front_t {
+ template <typename Xs>
+ constexpr decltype(auto) operator()(Xs&& xs) const;
+ };
+
+ constexpr front_t front{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_FRONT_HPP
diff --git a/boost/hana/fwd/fuse.hpp b/boost/hana/fwd/fuse.hpp
new file mode 100644
index 0000000000..6e38227c61
--- /dev/null
+++ b/boost/hana/fwd/fuse.hpp
@@ -0,0 +1,55 @@
+/*!
+@file
+Forward declares `boost::hana::fuse`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_FUSE_HPP
+#define BOOST_HANA_FWD_FUSE_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Transform a function taking multiple arguments into a function that
+ //! can be called with a compile-time `Foldable`.
+ //! @ingroup group-Foldable
+ //!
+ //!
+ //! This function is provided for convenience as a different way of
+ //! calling `unpack`. Specifically, `fuse(f)` is a function such that
+ //! @code
+ //! fuse(f)(foldable) == unpack(foldable, f)
+ //! == f(x...)
+ //! @endcode
+ //! where `x...` are the elements in the foldable. This function is
+ //! useful when one wants to create a function that accepts a foldable
+ //! which is not known yet.
+ //!
+ //! @note
+ //! This function is not tag-dispatched; customize `unpack` instead.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/fuse.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto fuse = [](auto&& f) {
+ return [perfect-capture](auto&& xs) -> decltype(auto) {
+ return unpack(forwarded(xs), forwarded(f));
+ };
+ };
+#else
+ struct fuse_t {
+ template <typename F>
+ constexpr auto operator()(F&& f) const;
+ };
+
+ constexpr fuse_t fuse{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_FUSE_HPP
diff --git a/boost/hana/fwd/greater.hpp b/boost/hana/fwd/greater.hpp
new file mode 100644
index 0000000000..091c1d36de
--- /dev/null
+++ b/boost/hana/fwd/greater.hpp
@@ -0,0 +1,53 @@
+/*!
+@file
+Forward declares `boost::hana::greater`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_GREATER_HPP
+#define BOOST_HANA_FWD_GREATER_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/detail/nested_than_fwd.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns a `Logical` representing whether `x` is greater than `y`.
+ //! @ingroup group-Orderable
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a Logical `Bool` and two Orderables `A` and `B` with a common
+ //! embedding, the signature is
+ //! @f$ \mathrm{greater} : A \times B \to Bool @f$.
+ //!
+ //! @param x, y
+ //! Two objects to compare.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/greater.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto greater = [](auto&& x, auto&& y) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename U, typename = void>
+ struct greater_impl : greater_impl<T, U, when<true>> { };
+
+ struct greater_t : detail::nested_than<greater_t> {
+ template <typename X, typename Y>
+ constexpr decltype(auto) operator()(X&& x, Y&& y) const;
+ };
+
+ constexpr greater_t greater{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_GREATER_HPP
diff --git a/boost/hana/fwd/greater_equal.hpp b/boost/hana/fwd/greater_equal.hpp
new file mode 100644
index 0000000000..d19c6734be
--- /dev/null
+++ b/boost/hana/fwd/greater_equal.hpp
@@ -0,0 +1,54 @@
+/*!
+@file
+Forward declares `boost::hana::greater_equal`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_GREATER_EQUAL_HPP
+#define BOOST_HANA_FWD_GREATER_EQUAL_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/detail/nested_than_fwd.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns a `Logical` representing whether `x` is greater than or
+ //! equal to `y`.
+ //! @ingroup group-Orderable
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a Logical `Bool` and two Orderables `A` and `B` with a common
+ //! embedding, the signature is
+ //! @f$ \mathrm{greater\_equal} : A \times B \to Bool @f$.
+ //!
+ //! @param x, y
+ //! Two objects to compare.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/greater_equal.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto greater_equal = [](auto&& x, auto&& y) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename U, typename = void>
+ struct greater_equal_impl : greater_equal_impl<T, U, when<true>> { };
+
+ struct greater_equal_t : detail::nested_than<greater_equal_t> {
+ template <typename X, typename Y>
+ constexpr decltype(auto) operator()(X&& x, Y&& y) const;
+ };
+
+ constexpr greater_equal_t greater_equal{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_GREATER_EQUAL_HPP
diff --git a/boost/hana/fwd/group.hpp b/boost/hana/fwd/group.hpp
new file mode 100644
index 0000000000..75fb68c832
--- /dev/null
+++ b/boost/hana/fwd/group.hpp
@@ -0,0 +1,103 @@
+/*!
+@file
+Forward declares `boost::hana::group`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_GROUP_HPP
+#define BOOST_HANA_FWD_GROUP_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/detail/nested_by_fwd.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Group adjacent elements of a sequence that all respect a binary
+ //! predicate, by default equality.
+ //! @ingroup group-Sequence
+ //!
+ //! Given a _finite_ Sequence and an optional predicate (by default
+ //! `equal`), `group` returns a sequence of subsequences representing
+ //! groups of adjacent elements that are "equal" with respect to the
+ //! predicate. In other words, the groups are such that the predicate is
+ //! satisfied when it is applied to any two adjacent elements in that
+ //! group. The sequence returned by `group` is such that the concatenation
+ //! of its elements is equal to the original sequence, which is equivalent
+ //! to saying that the order of the elements is not changed.
+ //!
+ //! If no predicate is provided, adjacent elements in the sequence must
+ //! all be compile-time `Comparable`.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a Sequence `s` with tag `S(T)`, an `IntegralConstant` `Bool`
+ //! holding a value of type `bool`, and a predicate
+ //! \f$ pred : T \times T \to Bool \f$, `group` has the following
+ //! signatures. For the variant with a provided predicate,
+ //! \f[
+ //! \mathtt{group} : S(T) \times (T \times T \to Bool) \to S(S(T))
+ //! \f]
+ //!
+ //! for the variant without a custom predicate, `T` is required to be
+ //! Comparable. The signature is then
+ //! \f[
+ //! \mathtt{group} : S(T) \to S(S(T))
+ //! \f]
+ //!
+ //! @param xs
+ //! The sequence to split into groups.
+ //!
+ //! @param predicate
+ //! A binary function called as `predicate(x, y)`, where `x` and `y` are
+ //! _adjacent_ elements in the sequence, whether both elements should be
+ //! in the same group (subsequence) of the result. In the current version
+ //! of the library, the result returned by `predicate` must be an
+ //! `IntegralConstant` holding a value of a type convertible to `bool`.
+ //! Also, `predicate` has to define an equivalence relation as defined by
+ //! the `Comparable` concept. When this predicate is not provided, it
+ //! defaults to `equal`, which requires the comparison of any two adjacent
+ //! elements in the sequence to return a boolean `IntegralConstant`.
+ //!
+ //!
+ //! Syntactic sugar (`group.by`)
+ //! ----------------------------
+ //! `group` can be called in a third way, which provides a nice syntax
+ //! especially when working with the `comparing` combinator:
+ //! @code
+ //! group.by(predicate, xs) == group(xs, predicate)
+ //! group.by(predicate) == group(-, predicate)
+ //! @endcode
+ //!
+ //! where `group(-, predicate)` denotes the partial application of
+ //! `group` to `predicate`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/group.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto group = [](auto&& xs[, auto&& predicate]) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct group_impl : group_impl<S, when<true>> { };
+
+ struct group_t : detail::nested_by<group_t> {
+ template <typename Xs>
+ constexpr auto operator()(Xs&& xs) const;
+
+ template <typename Xs, typename Predicate>
+ constexpr auto operator()(Xs&& xs, Predicate&& pred) const;
+ };
+
+ constexpr group_t group{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_GROUP_HPP
diff --git a/boost/hana/fwd/hash.hpp b/boost/hana/fwd/hash.hpp
new file mode 100644
index 0000000000..38602db518
--- /dev/null
+++ b/boost/hana/fwd/hash.hpp
@@ -0,0 +1,68 @@
+/*!
+@file
+Forward declares `boost::hana::hash`.
+
+@copyright Louis Dionne 2016
+@copyright Jason Rice 2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_HASH_HPP
+#define BOOST_HANA_FWD_HASH_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns a `hana::type` representing the compile-time hash of an object.
+ //! @ingroup group-Hashable
+ //!
+ //! Given an arbitrary object `x`, `hana::hash` returns a `hana::type`
+ //! representing the hash of `x`. In normal programming, hashes are
+ //! usually numerical values that can be used e.g. as indices in an
+ //! array as part of the implementation of a hash table. In the context
+ //! of metaprogramming, we are interested in type-level hashes instead.
+ //! Thus, `hana::hash` must return a `hana::type` object instead of an
+ //! integer. This `hana::type` must somehow summarize the object being
+ //! hashed, but that summary may of course lose some information.
+ //!
+ //! In order for the `hash` function to be defined properly, it must be
+ //! the case that whenever `x` is equal to `y`, then `hash(x)` is equal
+ //! to `hash(y)`. This ensures that `hana::hash` is a function in the
+ //! mathematical sense of the term.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a `Hashable` `H`, the signature is
+ //! \f$
+ //! \mathtt{hash} : H \to \mathtt{type\_tag}
+ //! \f$
+ //!
+ //! @param x
+ //! An object whose hash is to be computed.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/hash.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto hash = [](auto const& x) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename = void>
+ struct hash_impl : hash_impl<T, when<true>> { };
+
+ struct hash_t {
+ template <typename X>
+ constexpr auto operator()(X const& x) const;
+ };
+
+ constexpr hash_t hash{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_HASH_HPP
diff --git a/boost/hana/fwd/if.hpp b/boost/hana/fwd/if.hpp
new file mode 100644
index 0000000000..c221b355cf
--- /dev/null
+++ b/boost/hana/fwd/if.hpp
@@ -0,0 +1,57 @@
+/*!
+@file
+Forward declares `boost::hana::if_`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_IF_HPP
+#define BOOST_HANA_FWD_IF_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Conditionally return one of two values based on a condition.
+ //! @ingroup group-Logical
+ //!
+ //! Specifically, `then` is returned iff `cond` is true-valued, and
+ //! `else_` is returned otherwise. Note that some `Logical` models may
+ //! allow `then` and `else_` to have different types, while others may
+ //! require both values to have the same type.
+ //!
+ //!
+ //! @param cond
+ //! The condition determining which of the two values is returned.
+ //!
+ //! @param then
+ //! The value returned when `cond` is true-valued.
+ //!
+ //! @param else_
+ //! The value returned when `cond` is false-valued.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/if.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto if_ = [](auto&& cond, auto&& then, auto&& else_) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename L, typename = void>
+ struct if_impl : if_impl<L, when<true>> { };
+
+ struct if_t {
+ template <typename Cond, typename Then, typename Else>
+ constexpr decltype(auto) operator()(Cond&& cond, Then&& then, Else&& else_) const;
+ };
+
+ constexpr if_t if_{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_IF_HPP
diff --git a/boost/hana/fwd/insert.hpp b/boost/hana/fwd/insert.hpp
new file mode 100644
index 0000000000..0ad88849c9
--- /dev/null
+++ b/boost/hana/fwd/insert.hpp
@@ -0,0 +1,60 @@
+/*!
+@file
+Forward declares `boost::hana::insert`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_INSERT_HPP
+#define BOOST_HANA_FWD_INSERT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ // Note: This function is documented per datatype/concept only.
+ //! @cond
+ template <typename T, typename = void>
+ struct insert_impl : insert_impl<T, when<true>> { };
+ //! @endcond
+
+ struct insert_t {
+ template <typename Set, typename ...Args>
+ constexpr decltype(auto) operator()(Set&& set, Args&& ...args) const;
+ };
+
+ constexpr insert_t insert{};
+
+
+ //! Insert a value at a given index in a sequence.
+ //! @ingroup group-Sequence
+ //!
+ //! Given a sequence, an index and an element to insert, `insert` inserts
+ //! the element at the given index.
+ //!
+ //! @param xs
+ //! The sequence in which a value should be inserted.
+ //!
+ //! @param n
+ //! The index at which an element should be inserted. This must be a
+ //! non-negative `Constant` of an integral type, and it must also be
+ //! true that `n < length(xs)` if `xs` is a finite sequence.
+ //!
+ //! @param element
+ //! The element to insert in the sequence.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/insert.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto insert = [](auto&& xs, auto&& n, auto&& element) {
+ return tag-dispatched;
+ };
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_INSERT_HPP
diff --git a/boost/hana/fwd/insert_range.hpp b/boost/hana/fwd/insert_range.hpp
new file mode 100644
index 0000000000..e424059c8c
--- /dev/null
+++ b/boost/hana/fwd/insert_range.hpp
@@ -0,0 +1,57 @@
+/*!
+@file
+Forward declares `boost::hana::insert_range`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_INSERT_RANGE_HPP
+#define BOOST_HANA_FWD_INSERT_RANGE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Insert several values at a given index in a sequence.
+ //! @ingroup group-Sequence
+ //!
+ //! Given a sequence, an index and any `Foldable` containing elements to
+ //! insert, `insert_range` inserts the elements in the `Foldable` at the
+ //! given index of the sequence.
+ //!
+ //! @param xs
+ //! The sequence in which values should be inserted.
+ //!
+ //! @param n
+ //! The index at which elements should be inserted. This must be a
+ //! non-negative `Constant` of an integral type, and it must also be
+ //! true that `n < length(xs)` if `xs` is a finite sequence.
+ //!
+ //! @param elements
+ //! A `Foldable` containing elements to insert in the sequence.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/insert_range.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto insert_range = [](auto&& xs, auto&& n, auto&& elements) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct insert_range_impl : insert_range_impl<S, when<true>> { };
+
+ struct insert_range_t {
+ template <typename Xs, typename N, typename Elements>
+ constexpr auto operator()(Xs&& xs, N&& n, Elements&& elements) const;
+ };
+
+ constexpr insert_range_t insert_range{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_INSERT_RANGE_HPP
diff --git a/boost/hana/fwd/integral_constant.hpp b/boost/hana/fwd/integral_constant.hpp
new file mode 100644
index 0000000000..e04eb8865d
--- /dev/null
+++ b/boost/hana/fwd/integral_constant.hpp
@@ -0,0 +1,399 @@
+/*!
+@file
+Forward declares `boost::hana::integral_constant`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_INTEGRAL_CONSTANT_HPP
+#define BOOST_HANA_FWD_INTEGRAL_CONSTANT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/operators/adl.hpp>
+
+#include <cstddef>
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Tag representing `hana::integral_constant`.
+ //! @relates hana::integral_constant
+ template <typename T>
+ struct integral_constant_tag {
+ using value_type = T;
+ };
+
+ namespace ic_detail {
+ template <typename T, T v>
+ struct with_index_t {
+ template <typename F>
+ constexpr void operator()(F&& f) const;
+ };
+
+ template <typename T, T v>
+ struct times_t {
+ static constexpr with_index_t<T, v> with_index{};
+
+ template <typename F>
+ constexpr void operator()(F&& f) const;
+ };
+ }
+
+ //! @ingroup group-datatypes
+ //! Compile-time value of an integral type.
+ //!
+ //! An `integral_constant` is an object that represents a compile-time
+ //! integral value. As the name suggests, `hana::integral_constant` is
+ //! basically equivalent to `std::integral_constant`, except that
+ //! `hana::integral_constant` also provide other goodies to make them
+ //! easier to use, like arithmetic operators and similar features. In
+ //! particular, `hana::integral_constant` is guaranteed to inherit from
+ //! the corresponding `std::integral_constant`, and hence have the same
+ //! members and capabilities. The sections below explain the extensions
+ //! to `std::integral_constant` provided by `hana::integral_constant`.
+ //!
+ //!
+ //! Arithmetic operators
+ //! --------------------
+ //! `hana::integral_constant` provides arithmetic operators that return
+ //! `hana::integral_constant`s to ease writing compile-time arithmetic:
+ //! @snippet example/integral_constant.cpp operators
+ //!
+ //! It is pretty important to realize that these operators return other
+ //! `integral_constant`s, not normal values of an integral type.
+ //! Actually, all those operators work pretty much in the same way.
+ //! Simply put, for an operator `@`,
+ //! @code
+ //! integral_constant<T, x>{} @ integral_constant<T, y>{} == integral_constant<T, x @ y>{}
+ //! @endcode
+ //!
+ //! The fact that the operators return `Constant`s is very important
+ //! because it allows all the information that's known at compile-time
+ //! to be conserved as long as it's only used with other values known at
+ //! compile-time. It is also interesting to observe that whenever an
+ //! `integral_constant` is combined with a normal runtime value, the
+ //! result will be a runtime value (because of the implicit conversion).
+ //! In general, this gives us the following table
+ //!
+ //! left operand | right operand | result
+ //! :-----------------: | :-----------------: | :-----------------:
+ //! `integral_constant` | `integral_constant` | `integral_constant`
+ //! `integral_constant` | runtime | runtime
+ //! runtime | `integral_constant` | runtime
+ //! runtime | runtime | runtime
+ //!
+ //! The full range of provided operators is
+ //! - Arithmetic: binary `+`, binary `-`, `/`, `*`, `%`, unary `+`, unary `-`
+ //! - Bitwise: `~`, `&`, `|`, `^`, `<<`, `>>`
+ //! - Comparison: `==`, `!=`, `<`, `<=`, `>`, `>=`
+ //! - %Logical: `||`, `&&`, `!`
+ //!
+ //!
+ //! Construction with user-defined literals
+ //! ---------------------------------------
+ //! `integral_constant`s of type `long long` can be created with the
+ //! `_c` user-defined literal, which is contained in the `literals`
+ //! namespace:
+ //! @snippet example/integral_constant.cpp literals
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! 1. `Constant` and `IntegralConstant`\n
+ //! An `integral_constant` is a model of the `IntegralConstant` concept in
+ //! the most obvious way possible. Specifically,
+ //! @code
+ //! integral_constant<T, v>::value == v // of type T
+ //! @endcode
+ //! The model of `Constant` follows naturally from the model of `IntegralConstant`, i.e.
+ //! @code
+ //! value<integral_constant<T, v>>() == v // of type T
+ //! @endcode
+ //!
+ //! 2. `Comparable`, `Orderable`, `Logical`, `Monoid`, `Group`, `Ring`, and `EuclideanRing`, `Hashable`\n
+ //! Those models are exactly those provided for `Constant`s, which are
+ //! documented in their respective concepts.
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename T, T v>
+ struct integral_constant {
+ //! Call a function n times.
+ //!
+ //! `times` allows a nullary function to be invoked `n` times:
+ //! @code
+ //! int_<3>::times(f)
+ //! @endcode
+ //! should be expanded by any decent compiler to
+ //! @code
+ //! f(); f(); f();
+ //! @endcode
+ //!
+ //! This can be useful in several contexts, e.g. for loop unrolling:
+ //! @snippet example/integral_constant.cpp times_loop_unrolling
+ //!
+ //! Note that `times` is really a static function object, not just a
+ //! static function. This allows `int_<n>::%times` to be passed to
+ //! higher-order algorithms:
+ //! @snippet example/integral_constant.cpp times_higher_order
+ //!
+ //! Also, since static members can be accessed using both the `.` and
+ //! the `::` syntax, one can take advantage of this (loophole?) to
+ //! call `times` on objects just as well as on types:
+ //! @snippet example/integral_constant.cpp from_object
+ //!
+ //! @note
+ //! `times` is equivalent to the `hana::repeat` function, which works
+ //! on an arbitrary `IntegralConstant`.
+ //!
+ //! Sometimes, it is also useful to know the index we're at inside the
+ //! function. This can be achieved by using `times.with_index`:
+ //! @snippet example/integral_constant.cpp times_with_index_runtime
+ //!
+ //! Remember that `times` is a _function object_, and hence it can
+ //! have subobjects. `with_index` is just a function object nested
+ //! inside `times`, which allows for this nice little interface. Also
+ //! note that the indices passed to the function are `integral_constant`s;
+ //! they are known at compile-time. Hence, we can do compile-time stuff
+ //! with them, like indexing inside a tuple:
+ //! @snippet example/integral_constant.cpp times_with_index_compile_time
+ //!
+ //! @note
+ //! `times.with_index(f)` guarantees that the calls to `f` will be
+ //! done in order of ascending index. In other words, `f` will be
+ //! called as `f(0)`, `f(1)`, `f(2)`, etc., but with `integral_constant`s
+ //! instead of normal integers. Side effects can also be done in the
+ //! function passed to `times` and `times.with_index`.
+ template <typename F>
+ static constexpr void times(F&& f) {
+ f(); f(); ... f(); // n times total
+ }
+
+ //! Equivalent to `hana::plus`
+ template <typename X, typename Y>
+ friend constexpr auto operator+(X&& x, Y&& y);
+
+ //! Equivalent to `hana::minus`
+ template <typename X, typename Y>
+ friend constexpr auto operator-(X&& x, Y&& y);
+
+ //! Equivalent to `hana::negate`
+ template <typename X>
+ friend constexpr auto operator-(X&& x);
+
+ //! Equivalent to `hana::mult`
+ template <typename X, typename Y>
+ friend constexpr auto operator*(X&& x, Y&& y);
+
+ //! Equivalent to `hana::div`
+ template <typename X, typename Y>
+ friend constexpr auto operator/(X&& x, Y&& y);
+
+ //! Equivalent to `hana::mod`
+ template <typename X, typename Y>
+ friend constexpr auto operator%(X&& x, Y&& y);
+
+ //! Equivalent to `hana::equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator==(X&& x, Y&& y);
+
+ //! Equivalent to `hana::not_equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator!=(X&& x, Y&& y);
+
+ //! Equivalent to `hana::or_`
+ template <typename X, typename Y>
+ friend constexpr auto operator||(X&& x, Y&& y);
+
+ //! Equivalent to `hana::and_`
+ template <typename X, typename Y>
+ friend constexpr auto operator&&(X&& x, Y&& y);
+
+ //! Equivalent to `hana::not_`
+ template <typename X>
+ friend constexpr auto operator!(X&& x);
+
+ //! Equivalent to `hana::less`
+ template <typename X, typename Y>
+ friend constexpr auto operator<(X&& x, Y&& y);
+
+ //! Equivalent to `hana::greater`
+ template <typename X, typename Y>
+ friend constexpr auto operator>(X&& x, Y&& y);
+
+ //! Equivalent to `hana::less_equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator<=(X&& x, Y&& y);
+
+ //! Equivalent to `hana::greater_equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator>=(X&& x, Y&& y);
+ };
+#else
+ template <typename T, T v>
+ struct integral_constant
+ : std::integral_constant<T, v>
+ , detail::operators::adl<integral_constant<T, v>>
+ {
+ using type = integral_constant; // override std::integral_constant::type
+ static constexpr ic_detail::times_t<T, v> times{};
+ using hana_tag = integral_constant_tag<T>;
+ };
+#endif
+
+ //! Creates an `integral_constant` holding the given compile-time value.
+ //! @relates hana::integral_constant
+ //!
+ //! Specifically, `integral_c<T, v>` is a `hana::integral_constant`
+ //! holding the compile-time value `v` of an integral type `T`.
+ //!
+ //!
+ //! @tparam T
+ //! The type of the value to hold in the `integral_constant`.
+ //! It must be an integral type.
+ //!
+ //! @tparam v
+ //! The integral value to hold in the `integral_constant`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @snippet example/integral_constant.cpp integral_c
+ template <typename T, T v>
+ constexpr integral_constant<T, v> integral_c{};
+
+
+ //! @relates hana::integral_constant
+ template <bool b>
+ using bool_ = integral_constant<bool, b>;
+
+ //! @relates hana::integral_constant
+ template <bool b>
+ constexpr bool_<b> bool_c{};
+
+ //! @relates hana::integral_constant
+ using true_ = bool_<true>;
+
+ //! @relates hana::integral_constant
+ constexpr auto true_c = bool_c<true>;
+
+ //! @relates hana::integral_constant
+ using false_ = bool_<false>;
+
+ //! @relates hana::integral_constant
+ constexpr auto false_c = bool_c<false>;
+
+
+ //! @relates hana::integral_constant
+ template <char c>
+ using char_ = integral_constant<char, c>;
+
+ //! @relates hana::integral_constant
+ template <char c>
+ constexpr char_<c> char_c{};
+
+
+ //! @relates hana::integral_constant
+ template <short i>
+ using short_ = integral_constant<short, i>;
+
+ //! @relates hana::integral_constant
+ template <short i>
+ constexpr short_<i> short_c{};
+
+
+ //! @relates hana::integral_constant
+ template <unsigned short i>
+ using ushort_ = integral_constant<unsigned short, i>;
+
+ //! @relates hana::integral_constant
+ template <unsigned short i>
+ constexpr ushort_<i> ushort_c{};
+
+
+ //! @relates hana::integral_constant
+ template <int i>
+ using int_ = integral_constant<int, i>;
+
+ //! @relates hana::integral_constant
+ template <int i>
+ constexpr int_<i> int_c{};
+
+
+ //! @relates hana::integral_constant
+ template <unsigned int i>
+ using uint = integral_constant<unsigned int, i>;
+
+ //! @relates hana::integral_constant
+ template <unsigned int i>
+ constexpr uint<i> uint_c{};
+
+
+ //! @relates hana::integral_constant
+ template <long i>
+ using long_ = integral_constant<long, i>;
+
+ //! @relates hana::integral_constant
+ template <long i>
+ constexpr long_<i> long_c{};
+
+
+ //! @relates hana::integral_constant
+ template <unsigned long i>
+ using ulong = integral_constant<unsigned long, i>;
+
+ //! @relates hana::integral_constant
+ template <unsigned long i>
+ constexpr ulong<i> ulong_c{};
+
+
+ //! @relates hana::integral_constant
+ template <long long i>
+ using llong = integral_constant<long long, i>;
+
+ //! @relates hana::integral_constant
+ template <long long i>
+ constexpr llong<i> llong_c{};
+
+
+ //! @relates hana::integral_constant
+ template <unsigned long long i>
+ using ullong = integral_constant<unsigned long long, i>;
+
+ //! @relates hana::integral_constant
+ template <unsigned long long i>
+ constexpr ullong<i> ullong_c{};
+
+
+ //! @relates hana::integral_constant
+ template <std::size_t i>
+ using size_t = integral_constant<std::size_t, i>;
+
+ //! @relates hana::integral_constant
+ template <std::size_t i>
+ constexpr size_t<i> size_c{};
+
+
+ namespace literals {
+ //! Creates a `hana::integral_constant` from a literal.
+ //! @relatesalso boost::hana::integral_constant
+ //!
+ //! The literal is parsed at compile-time and the result is returned
+ //! as a `llong<...>`.
+ //!
+ //! @note
+ //! We use `llong<...>` instead of `ullong<...>` because using an
+ //! unsigned type leads to unexpected behavior when doing stuff like
+ //! `-1_c`. If we used an unsigned type, `-1_c` would be something
+ //! like `ullong<-1>` which is actually `ullong<something huge>`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @snippet example/integral_constant.cpp literals
+ template <char ...c>
+ constexpr auto operator"" _c();
+ }
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_INTEGRAL_CONSTANT_HPP
diff --git a/boost/hana/fwd/intersection.hpp b/boost/hana/fwd/intersection.hpp
new file mode 100644
index 0000000000..59a1c298c7
--- /dev/null
+++ b/boost/hana/fwd/intersection.hpp
@@ -0,0 +1,61 @@
+/*!
+@file
+Forward declares `boost::hana::intersection`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_INTERSECTION_HPP
+#define BOOST_HANA_FWD_INTERSECTION_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns the intersection of two sets.
+ //! @relates hana::set
+ //!
+ //! Given two sets `xs` and `ys`, `intersection(xs, ys)` is a new set
+ //! containing exactly those elements that are present both in `xs` and
+ //! in `ys`. In other words, the following holds for any object `x`:
+ //! @code
+ //! x ^in^ intersection(xs, ys) if and only if x ^in^ xs && x ^in^ ys
+ //! @endcode
+ //!
+ //!
+ //! @param xs, ys
+ //! Two sets to intersect.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/intersection.cpp
+ //!
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.intersection.compile.json">
+ //! </div>
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto intersection = [](auto&& xs, auto&& ys) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct intersection_impl : intersection_impl<S, when<true>> { };
+
+ struct intersection_t {
+ template <typename Xs, typename Ys>
+ constexpr auto operator()(Xs&& xs, Ys&& ys) const;
+ };
+
+ constexpr intersection_t intersection{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_INTERSECTION_HPP
diff --git a/boost/hana/fwd/intersperse.hpp b/boost/hana/fwd/intersperse.hpp
new file mode 100644
index 0000000000..fd29d3a321
--- /dev/null
+++ b/boost/hana/fwd/intersperse.hpp
@@ -0,0 +1,57 @@
+/*!
+@file
+Forward declares `boost::hana::intersperse`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_INTERSPERSE_HPP
+#define BOOST_HANA_FWD_INTERSPERSE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Insert a value between each pair of elements in a finite sequence.
+ //! @ingroup group-Sequence
+ //!
+ //! Given a finite `Sequence` `xs` with a linearization of
+ //! `[x1, x2, ..., xn]`, `intersperse(xs, z)` is a new sequence with a
+ //! linearization of `[x1, z, x2, z, x3, ..., xn-1, z, xn]`. In other
+ //! words, it inserts the `z` element between every pair of elements of
+ //! the original sequence. If the sequence is empty or has a single
+ //! element, `intersperse` returns the sequence as-is. In all cases,
+ //! the sequence must be finite.
+ //!
+ //!
+ //! @param xs
+ //! The sequence in which a value is interspersed.
+ //!
+ //! @param z
+ //! The value to be inserted between every pair of elements of the sequence.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/intersperse.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto intersperse = [](auto&& xs, auto&& z) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct intersperse_impl : intersperse_impl<S, when<true>> { };
+
+ struct intersperse_t {
+ template <typename Xs, typename Z>
+ constexpr auto operator()(Xs&& xs, Z&& z) const;
+ };
+
+ constexpr intersperse_t intersperse{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_INTERSPERSE_HPP
diff --git a/boost/hana/fwd/is_disjoint.hpp b/boost/hana/fwd/is_disjoint.hpp
new file mode 100644
index 0000000000..9f960ba07e
--- /dev/null
+++ b/boost/hana/fwd/is_disjoint.hpp
@@ -0,0 +1,58 @@
+/*!
+@file
+Forward declares `boost::hana::is_disjoint`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_IS_DISJOINT_HPP
+#define BOOST_HANA_FWD_IS_DISJOINT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns whether two `Searchable`s are disjoint.
+ //! @ingroup group-Searchable
+ //!
+ //! Given two `Searchable`s `xs` and `ys`, `is_disjoint` returns a
+ //! `Logical` representing whether the keys in `xs` are disjoint from
+ //! the keys in `ys`, i.e. whether both structures have no keys in common.
+ //!
+ //!
+ //! @param xs, ys
+ //! Two `Searchable`s to test for disjointness.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/is_disjoint.cpp
+ //!
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.is_disjoint.compile.json">
+ //! </div>
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto is_disjoint = [](auto const& xs, auto const& ys) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S1, typename S2, typename = void>
+ struct is_disjoint_impl : is_disjoint_impl<S1, S2, when<true>> { };
+
+ struct is_disjoint_t {
+ template <typename Xs, typename Ys>
+ constexpr auto operator()(Xs&& xs, Ys&& ys) const;
+ };
+
+ constexpr is_disjoint_t is_disjoint{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_IS_DISJOINT_HPP
diff --git a/boost/hana/fwd/is_empty.hpp b/boost/hana/fwd/is_empty.hpp
new file mode 100644
index 0000000000..ddc524672d
--- /dev/null
+++ b/boost/hana/fwd/is_empty.hpp
@@ -0,0 +1,49 @@
+/*!
+@file
+Forward declares `boost::hana::is_empty`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_IS_EMPTY_HPP
+#define BOOST_HANA_FWD_IS_EMPTY_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns whether the iterable is empty.
+ //! @ingroup group-Iterable
+ //!
+ //! Given an `Iterable` `xs`, `is_empty` returns whether `xs` contains
+ //! no more elements. In other words, it returns whether trying to
+ //! extract the tail of `xs` would be an error. In the current version
+ //! of the library, `is_empty` must return an `IntegralConstant` holding
+ //! a value convertible to `bool`. This is because only compile-time
+ //! `Iterable`s are supported right now.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/is_empty.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto is_empty = [](auto const& xs) {
+ return tag-dispatched;
+ };
+#else
+ template <typename It, typename = void>
+ struct is_empty_impl : is_empty_impl<It, when<true>> { };
+
+ struct is_empty_t {
+ template <typename Xs>
+ constexpr auto operator()(Xs const& xs) const;
+ };
+
+ constexpr is_empty_t is_empty{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_IS_EMPTY_HPP
diff --git a/boost/hana/fwd/is_subset.hpp b/boost/hana/fwd/is_subset.hpp
new file mode 100644
index 0000000000..9d5ed28cd4
--- /dev/null
+++ b/boost/hana/fwd/is_subset.hpp
@@ -0,0 +1,87 @@
+/*!
+@file
+Forward declares `boost::hana::is_subset`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_IS_SUBSET_HPP
+#define BOOST_HANA_FWD_IS_SUBSET_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+#include <boost/hana/functional/infix.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns whether a structure contains a subset of the keys of
+ //! another structure.
+ //! @ingroup group-Searchable
+ //!
+ //! Given two `Searchable`s `xs` and `ys`, `is_subset` returns a `Logical`
+ //! representing whether `xs` is a subset of `ys`. In other words, it
+ //! returns whether all the keys of `xs` are also present in `ys`. This
+ //! method does not return whether `xs` is a _strict_ subset of `ys`; if
+ //! `xs` and `ys` are equal, all the keys of `xs` are also present in
+ //! `ys`, and `is_subset` returns true.
+ //!
+ //! @note
+ //! For convenience, `is_subset` can also be applied in infix notation.
+ //!
+ //!
+ //! Cross-type version of the method
+ //! --------------------------------
+ //! This method is tag-dispatched using the tags of both arguments.
+ //! It can be called with any two `Searchable`s sharing a common
+ //! `Searchable` embedding, as defined in the main documentation
+ //! of the `Searchable` concept. When `Searchable`s with two different
+ //! tags but sharing a common embedding are sent to `is_subset`, they
+ //! are first converted to this common `Searchable` and the `is_subset`
+ //! method of the common embedding is then used. Of course, the method
+ //! can be overriden for custom `Searchable`s for efficieny.
+ //!
+ //! @note
+ //! While cross-type dispatching for `is_subset` is supported, it is
+ //! not currently used by the library because there are no models
+ //! of `Searchable` with a common embedding.
+ //!
+ //!
+ //! @param xs
+ //! The structure to check whether it is a subset of `ys`.
+ //!
+ //! @param ys
+ //! The structure to check whether it is a superset of `xs`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/is_subset.cpp
+ //!
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.is_subset.compile.json">
+ //! </div>
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto is_subset = [](auto&& xs, auto&& ys) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S1, typename S2, typename = void>
+ struct is_subset_impl : is_subset_impl<S1, S2, when<true>> { };
+
+ struct is_subset_t {
+ template <typename Xs, typename Ys>
+ constexpr auto operator()(Xs&& xs, Ys&& ys) const;
+ };
+
+ constexpr auto is_subset = hana::infix(is_subset_t{});
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_IS_SUBSET_HPP
diff --git a/boost/hana/fwd/keys.hpp b/boost/hana/fwd/keys.hpp
new file mode 100644
index 0000000000..285c34d9a1
--- /dev/null
+++ b/boost/hana/fwd/keys.hpp
@@ -0,0 +1,50 @@
+/*!
+@file
+Forward declares `boost::hana::keys`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_KEYS_HPP
+#define BOOST_HANA_FWD_KEYS_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ // Note: This function is documented per datatype/concept only.
+ //! @cond
+ template <typename T, typename = void>
+ struct keys_impl : keys_impl<T, when<true>> { };
+ //! @endcond
+
+ struct keys_t {
+ template <typename Map>
+ constexpr auto operator()(Map&& map) const;
+ };
+
+ constexpr keys_t keys{};
+
+ //! Returns a `Sequence` containing the name of the members of
+ //! the data structure.
+ //! @ingroup group-Struct
+ //!
+ //! Given a `Struct` object, `keys` returns a `Sequence` containing the
+ //! name of all the members of the `Struct`, in the same order as they
+ //! appear in the `accessors` sequence.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/struct/keys.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto keys = [](auto&& object) {
+ return implementation_defined;
+ };
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_KEYS_HPP
diff --git a/boost/hana/fwd/lazy.hpp b/boost/hana/fwd/lazy.hpp
new file mode 100644
index 0000000000..6ae6a830ef
--- /dev/null
+++ b/boost/hana/fwd/lazy.hpp
@@ -0,0 +1,124 @@
+/*!
+@file
+Forward declares `boost::hana::lazy`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_LAZY_HPP
+#define BOOST_HANA_FWD_LAZY_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-datatypes
+ //! `hana::lazy` implements superficial laziness via a monadic interface.
+ //!
+ //! It is important to understand that the laziness implemented by `lazy`
+ //! is only superficial; only function applications made inside the `lazy`
+ //! monad can be made lazy, not all their subexpressions.
+ //!
+ //!
+ //! @note
+ //! The actual representation of `hana::lazy` is completely
+ //! implementation-defined. Lazy values may only be created through
+ //! `hana::make_lazy`, and they can be stored in variables using
+ //! `auto`, but any other assumption about the representation of
+ //! `hana::lazy<...>` should be avoided. In particular, one should
+ //! not rely on the fact that `hana::lazy<...>` can be pattern-matched
+ //! on, because it may be a dependent type.
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! 1. `Functor`\n
+ //! Applying a function over a lazy value with `transform` returns the
+ //! result of applying the function, as a lazy value.
+ //! @include example/lazy/functor.cpp
+ //!
+ //! 2. `Applicative`\n
+ //! A normal value can be lifted into a lazy value by using `lift<lazy_tag>`.
+ //! A lazy function can be lazily applied to a lazy value by using `ap`.
+ //!
+ //! 3. `Monad`\n
+ //! The `lazy` monad allows combining lazy computations into larger
+ //! lazy computations. Note that the `|` operator can be used in place
+ //! of the `chain` function.
+ //! @include example/lazy/monad.cpp
+ //!
+ //! 4. `Comonad`\n
+ //! The `lazy` comonad allows evaluating a lazy computation to get its
+ //! result and lazily applying functions taking lazy inputs to lazy
+ //! values. This [blog post][1] goes into more details about lazy
+ //! evaluation and comonads.
+ //! @include example/lazy/comonad.cpp
+ //!
+ //!
+ //! @note
+ //! `hana::lazy` only models a few concepts because providing more
+ //! functionality would require evaluating the lazy values in most cases.
+ //! Since this raises some issues such as side effects and memoization,
+ //! the interface is kept minimal.
+ //!
+ //!
+ //! [1]: http://ldionne.com/2015/03/16/laziness-as-a-comonad
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename implementation_defined>
+ struct lazy {
+ //! Equivalent to `hana::chain`.
+ template <typename ...T, typename F>
+ friend constexpr auto operator|(lazy<T...>, F);
+ };
+#else
+ // We do not _actually_ define the lazy<...> type. Per the documentation,
+ // users can't rely on it being anything, and so they should never use
+ // it explicitly. The implementation in <boost/hana/lazy.hpp> is much
+ // simpler if we use different types for lazy calls and lazy values.
+#endif
+
+ //! Tag representing `hana::lazy`.
+ //! @relates hana::lazy
+ struct lazy_tag { };
+
+ //! Lifts a normal value to a lazy one.
+ //! @relates hana::lazy
+ //!
+ //! `make<lazy_tag>` can be used to lift a normal value or a function call
+ //! into a lazy expression. Precisely, `make<lazy_tag>(x)` is a lazy value
+ //! equal to `x`, and `make<lazy_tag>(f)(x1, ..., xN)` is a lazy function
+ //! call that is equal to `f(x1, ..., xN)` when it is `eval`uated.
+ //!
+ //! @note
+ //! It is interesting to note that `make<lazy_tag>(f)(x1, ..., xN)` is
+ //! equivalent to
+ //! @code
+ //! ap(make<lazy_tag>(f), lift<lazy_tag>(x1), ..., lift<lazy_tag>(xN))
+ //! @endcode
+ //! which in turn is equivalent to `make<lazy_tag>(f(x1, ..., xN))`, except
+ //! for the fact that the inner call to `f` is evaluated lazily.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/lazy/make.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <>
+ constexpr auto make<lazy_tag> = [](auto&& x) {
+ return lazy<implementation_defined>{forwarded(x)};
+ };
+#endif
+
+ //! Alias to `make<lazy_tag>`; provided for convenience.
+ //! @relates hana::lazy
+ //!
+ //! Example
+ //! -------
+ //! @include example/lazy/make.cpp
+ constexpr auto make_lazy = make<lazy_tag>;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_LAZY_HPP
diff --git a/boost/hana/fwd/length.hpp b/boost/hana/fwd/length.hpp
new file mode 100644
index 0000000000..c995a80dd8
--- /dev/null
+++ b/boost/hana/fwd/length.hpp
@@ -0,0 +1,50 @@
+/*!
+@file
+Forward declares `boost::hana::length`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_LENGTH_HPP
+#define BOOST_HANA_FWD_LENGTH_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Return the number of elements in a foldable structure.
+ //! @ingroup group-Foldable
+ //!
+ //! Given a `Foldable` `xs`, `length(xs)` must return an object of an
+ //! unsigned integral type, or an `IntegralConstant` holding such an
+ //! object, which represents the number of elements in the structure.
+ //!
+ //! @note
+ //! Since only compile-time `Foldable`s are supported in the library
+ //! right now, `length` must always return an `IntegralConstant`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/length.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto length = [](auto const& xs) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename = void>
+ struct length_impl : length_impl<T, when<true>> { };
+
+ struct length_t {
+ template <typename Xs>
+ constexpr auto operator()(Xs const& xs) const;
+ };
+
+ constexpr length_t length{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_LENGTH_HPP
diff --git a/boost/hana/fwd/less.hpp b/boost/hana/fwd/less.hpp
new file mode 100644
index 0000000000..1dd585db33
--- /dev/null
+++ b/boost/hana/fwd/less.hpp
@@ -0,0 +1,53 @@
+/*!
+@file
+Forward declares `boost::hana::less`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_LESS_HPP
+#define BOOST_HANA_FWD_LESS_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/detail/nested_than_fwd.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns a `Logical` representing whether `x` is less than `y`.
+ //! @ingroup group-Orderable
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a Logical `Bool` and two Orderables `A` and `B` with a common
+ //! embedding, the signature is
+ //! @f$ \mathrm{less} : A \times B \to Bool @f$.
+ //!
+ //! @param x, y
+ //! Two objects to compare.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/less.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto less = [](auto&& x, auto&& y) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename U, typename = void>
+ struct less_impl : less_impl<T, U, when<true>> { };
+
+ struct less_t : detail::nested_than<less_t> {
+ template <typename X, typename Y>
+ constexpr auto operator()(X&& x, Y&& y) const;
+ };
+
+ constexpr less_t less{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_LESS_HPP
diff --git a/boost/hana/fwd/less_equal.hpp b/boost/hana/fwd/less_equal.hpp
new file mode 100644
index 0000000000..9de3d6b779
--- /dev/null
+++ b/boost/hana/fwd/less_equal.hpp
@@ -0,0 +1,54 @@
+/*!
+@file
+Forward declares `boost::hana::less_equal`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_LESS_EQUAL_HPP
+#define BOOST_HANA_FWD_LESS_EQUAL_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/detail/nested_than_fwd.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns a `Logical` representing whether `x` is less than or
+ //! equal to `y`.
+ //! @ingroup group-Orderable
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a Logical `Bool` and two Orderables `A` and `B` with a common
+ //! embedding, the signature is
+ //! @f$ \mathrm{less\_equal} : A \times B \to Bool @f$.
+ //!
+ //! @param x, y
+ //! Two objects to compare.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/less_equal.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto less_equal = [](auto&& x, auto&& y) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename U, typename = void>
+ struct less_equal_impl : less_equal_impl<T, U, when<true>> { };
+
+ struct less_equal_t : detail::nested_than<less_equal_t> {
+ template <typename X, typename Y>
+ constexpr auto operator()(X&& x, Y&& y) const;
+ };
+
+ constexpr less_equal_t less_equal{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_LESS_EQUAL_HPP
diff --git a/boost/hana/fwd/lexicographical_compare.hpp b/boost/hana/fwd/lexicographical_compare.hpp
new file mode 100644
index 0000000000..3c9f3f0e76
--- /dev/null
+++ b/boost/hana/fwd/lexicographical_compare.hpp
@@ -0,0 +1,101 @@
+/*!
+@file
+Forward declares `boost::hana::lexicographical_compare`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_LEXICOGRAPHICAL_COMPARE_HPP
+#define BOOST_HANA_FWD_LEXICOGRAPHICAL_COMPARE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Short-circuiting lexicographical comparison of two `Iterable`s with
+ //! an optional custom predicate, by default `hana::less`.
+ //! @ingroup group-Iterable
+ //!
+ //! Given two `Iterable`s `xs` and `ys` and a binary predicate `pred`,
+ //! `lexicographical_compare` returns whether `xs` is to be considered
+ //! less than `ys` in a lexicographical ordering. Specifically, let's
+ //! denote the linearizations of `xs` and `ys` by `[x1, x2, ...]` and
+ //! `[y1, y2, ...]`, respectively. If the first couple satisfying the
+ //! predicate is of the form `xi, yi`, `lexicographical_compare` returns
+ //! true. Otherwise, if the first couple to satisfy the predicate is of
+ //! the form `yi, xi`, `lexicographical_compare` returns false. If no
+ //! such couple can be found, `lexicographical_compare` returns whether
+ //! `xs` has fewer elements than `ys`.
+ //!
+ //! @note
+ //! This algorithm will short-circuit as soon as it can determine that one
+ //! sequence is lexicographically less than the other. Hence, it can be
+ //! used to compare infinite sequences. However, for the procedure to
+ //! terminate on infinite sequences, the predicate has to be satisfied
+ //! at a finite index.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given two `Iterable`s `It1(T)` and `It2(T)` and a predicate
+ //! \f$ pred : T \times T \to Bool \f$ (where `Bool` is some `Logical`),
+ //! `lexicographical_compare` has the following signatures. For the
+ //! variant with a provided predicate,
+ //! \f[
+ //! \mathtt{lexicographical\_compare}
+ //! : It1(T) \times It2(T) \times (T \times T \to Bool) \to Bool
+ //! \f]
+ //!
+ //! for the variant without a custom predicate, `T` is required to be
+ //! `Orderable`. The signature is then
+ //! \f[
+ //! \mathtt{lexicographical\_compare} : It1(T) \times It2(T) \to Bool
+ //! \f]
+ //!
+ //! @param xs, ys
+ //! Two `Iterable`s to compare lexicographically.
+ //!
+ //! @param pred
+ //! A binary function called as `pred(x, y)` and `pred(y, x)`, where `x`
+ //! and `y` are elements of `xs` and `ys`, respectively. `pred` must
+ //! return a `Logical` representing whether its first argument is to be
+ //! considered as less than its second argument. Also note that `pred`
+ //! must define a total ordering as defined by the `Orderable` concept.
+ //! When `pred` is not provided, it defaults to `less`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/lexicographical_compare.cpp
+ //!
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.lexicographical_compare.compile.json">
+ //! </div>
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto lexicographical_compare = [](auto const& xs, auto const& ys, auto const& pred = hana::less) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename = void>
+ struct lexicographical_compare_impl : lexicographical_compare_impl<T, when<true>> { };
+
+ struct lexicographical_compare_t {
+ template <typename Xs, typename Ys>
+ constexpr auto operator()(Xs const& xs, Ys const& ys) const;
+
+ template <typename Xs, typename Ys, typename Pred>
+ constexpr auto operator()(Xs const& xs, Ys const& ys, Pred const& pred) const;
+ };
+
+ constexpr lexicographical_compare_t lexicographical_compare{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_LEXICOGRAPHICAL_COMPARE_HPP
diff --git a/boost/hana/fwd/lift.hpp b/boost/hana/fwd/lift.hpp
new file mode 100644
index 0000000000..2f30fd68d5
--- /dev/null
+++ b/boost/hana/fwd/lift.hpp
@@ -0,0 +1,59 @@
+/*!
+@file
+Forward declares `boost::hana::lift`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_LIFT_HPP
+#define BOOST_HANA_FWD_LIFT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Lift a value into an `Applicative` structure.
+ //! @ingroup group-Applicative
+ //!
+ //! `lift<A>` takes a normal value and embeds it into a structure whose
+ //! shape is represented by the `A` `Applicative`. Note that the value
+ //! may be a function, in which case the created structure may be
+ //! `ap`plied to another `Applicative` structure containing values.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given an Applicative `A`, the signature is
+ //! @f$ \mathtt{lift}_A : T \to A(T) @f$.
+ //!
+ //! @tparam A
+ //! A tag representing the `Applicative` into which the value is lifted.
+ //!
+ //! @param x
+ //! The value to lift into the applicative.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/lift.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename A>
+ constexpr auto lift = [](auto&& x) {
+ return tag-dispatched;
+ };
+#else
+ template <typename A, typename = void>
+ struct lift_impl : lift_impl<A, when<true>> { };
+
+ template <typename A>
+ struct lift_t;
+
+ template <typename A>
+ constexpr lift_t<A> lift{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_LIFT_HPP
diff --git a/boost/hana/fwd/map.hpp b/boost/hana/fwd/map.hpp
new file mode 100644
index 0000000000..4d7f005740
--- /dev/null
+++ b/boost/hana/fwd/map.hpp
@@ -0,0 +1,233 @@
+/*!
+@file
+Forward declares `boost::hana::map`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_MAP_HPP
+#define BOOST_HANA_FWD_MAP_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/fwd/core/to.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+#include <boost/hana/fwd/erase_key.hpp>
+#include <boost/hana/fwd/insert.hpp>
+#include <boost/hana/fwd/keys.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-datatypes
+ //! Basic associative container requiring unique, `Comparable` and
+ //! `Hashable` keys.
+ //!
+ //! The order of the elements of the map is unspecified. Also, all the
+ //! keys must be `Hashable`, and any two keys with equal hashes must be
+ //! `Comparable` with each other at compile-time.
+ //!
+ //! @note
+ //! The actual representation of a `hana::map` is implementation-defined.
+ //! In particular, one should not take for granted the order of the
+ //! template parameters and the presence of any additional constructors
+ //! or assignment operators than what is documented. The canonical way of
+ //! creating a `hana::map` is through `hana::make_map`.
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! 1. `Comparable`\n
+ //! Two maps are equal iff all their keys are equal and are associated
+ //! to equal values.
+ //! @include example/map/comparable.cpp
+ //!
+ //! 2. `Searchable`\n
+ //! A map can be searched by its keys with a predicate yielding a
+ //! compile-time `Logical`. Also note that `operator[]` can be used
+ //! instead of `at_key`.
+ //! @include example/map/searchable.cpp
+ //!
+ //! 3. `Foldable`\n
+ //! Folding a map is equivalent to folding a list of the key/value pairs
+ //! it contains. In particular, since that list is not guaranteed to be
+ //! in any specific order, folding a map with an operation that is not
+ //! both commutative and associative will yield non-deterministic behavior.
+ //! @include example/map/foldable.cpp
+ //!
+ //!
+ //! Conversion from any `Foldable`
+ //! ------------------------------
+ //! Any `Foldable` of `Product`s can be converted to a `hana::map` with
+ //! `hana::to<hana::map_tag>` or, equivalently, `hana::to_map`. If the
+ //! `Foldable` contains duplicate keys, only the value associated to the
+ //! first occurence of each key is kept.
+ //! @include example/map/to.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename implementation_defined>
+ struct map {
+ //! Default-construct a map. This constructor only exists when all the
+ //! elements of the map are default-constructible.
+ constexpr map() = default;
+
+ //! Copy-construct a map from another map. This constructor only
+ //! exists when all the elements of the map are copy-constructible.
+ constexpr map(map const& other) = default;
+
+ //! Move-construct a map from another map. This constructor only
+ //! exists when all the elements of the map are move-constructible.
+ constexpr map(map&& other) = default;
+
+ //! Equivalent to `hana::equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator==(X&& x, Y&& y);
+
+ //! Equivalent to `hana::not_equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator!=(X&& x, Y&& y);
+
+ //! Equivalent to `hana::at_key`
+ template <typename Key>
+ constexpr decltype(auto) operator[](Key&& key);
+ };
+#else
+ template <typename HashTable, typename Storage>
+ struct map;
+#endif
+
+ //! Tag representing `hana::map`s.
+ //! @relates hana::map
+ struct map_tag { };
+
+ //! Function object for creating a `hana::map`.
+ //! @relates hana::map
+ //!
+ //! Given zero or more `Product`s representing key/value associations,
+ //! `make<map_tag>` returns a `hana::map` associating these keys to these
+ //! values.
+ //!
+ //! `make<map_tag>` requires all the keys to be unique and to have
+ //! different hashes. If you need to create a map with duplicate keys
+ //! or with keys whose hashes might collide, use `hana::to_map` or
+ //! insert `(key, value)` pairs to an empty map successively. However,
+ //! be aware that doing so will be much more compile-time intensive than
+ //! using `make<map_tag>`, because the uniqueness of keys will have to be
+ //! enforced.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/map/make.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <>
+ constexpr auto make<map_tag> = [](auto&& ...pairs) {
+ return map<implementation_defined>{forwarded(pairs)...};
+ };
+#endif
+
+ //! Alias to `make<map_tag>`; provided for convenience.
+ //! @relates hana::map
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/map/make.cpp
+ constexpr auto make_map = make<map_tag>;
+
+ //! Equivalent to `to<map_tag>`; provided for convenience.
+ //! @relates hana::map
+ constexpr auto to_map = to<map_tag>;
+
+ //! Returns a `Sequence` of the keys of the map, in unspecified order.
+ //! @relates hana::map
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/map/keys.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto keys = [](auto&& map) {
+ return implementation_defined;
+ };
+#endif
+
+ //! Returns a `Sequence` of the values of the map, in unspecified order.
+ //! @relates hana::map
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/map/values.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto values = [](auto&& map) -> decltype(auto) {
+ return implementation_defined;
+ };
+#else
+ struct values_t {
+ template <typename Map>
+ constexpr decltype(auto) operator()(Map&& map) const;
+ };
+
+ constexpr values_t values{};
+#endif
+
+ //! Inserts a new key/value pair in a map.
+ //! @relates hana::map
+ //!
+ //! Given a `(key, value)` pair, `insert` inserts this new pair into a
+ //! map. If the map already contains this key, nothing is done and the
+ //! map is returned as-is.
+ //!
+ //!
+ //! @param map
+ //! The map in which to insert a `(key,value)` pair.
+ //!
+ //! @param pair
+ //! An arbitrary `Product` representing a `(key, value)` pair to insert
+ //! in the map. The `key` must be compile-time `Comparable`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/map/insert.cpp
+ //!
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.insert.compile.json">
+ //! </div>
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto insert = [](auto&& map, auto&& pair) {
+ return tag-dispatched;
+ };
+#endif
+
+ //! Removes a key/value pair from a map.
+ //! @relates hana::map
+ //!
+ //! Returns a new `hana::map` containing all the elements of the original,
+ //! except for the `(key, value)` pair whose `key` compares `equal`
+ //! to the given key. If the map does not contain such an element,
+ //! a new map equal to the original is returned.
+ //!
+ //!
+ //! @param map
+ //! The map in which to erase a `key`.
+ //!
+ //! @param key
+ //! A key to remove from the map. It must be compile-time `Comparable`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/map/erase_key.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto erase_key = [](auto&& map, auto&& key) {
+ return tag-dispatched;
+ };
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_MAP_HPP
diff --git a/boost/hana/fwd/max.hpp b/boost/hana/fwd/max.hpp
new file mode 100644
index 0000000000..7a63fbc270
--- /dev/null
+++ b/boost/hana/fwd/max.hpp
@@ -0,0 +1,44 @@
+/*!
+@file
+Forward declares `boost::hana::max`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_MAX_HPP
+#define BOOST_HANA_FWD_MAX_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns the greatest of its arguments according to the `less` ordering.
+ //! @ingroup group-Orderable
+ //!
+ //!
+ //! @todo Can't specify the signature here either. See `min` for details.
+ //!
+ //! Example
+ //! -------
+ //! @include example/max.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto max = [](auto&& x, auto&& y) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename U, typename = void>
+ struct max_impl : max_impl<T, U, when<true>> { };
+
+ struct max_t {
+ template <typename X, typename Y>
+ constexpr decltype(auto) operator()(X&& x, Y&& y) const;
+ };
+
+ constexpr max_t max{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_MAX_HPP
diff --git a/boost/hana/fwd/maximum.hpp b/boost/hana/fwd/maximum.hpp
new file mode 100644
index 0000000000..b725a68fa3
--- /dev/null
+++ b/boost/hana/fwd/maximum.hpp
@@ -0,0 +1,116 @@
+/*!
+@file
+Forward declares `boost::hana::maximum`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_MAXIMUM_HPP
+#define BOOST_HANA_FWD_MAXIMUM_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/detail/nested_by_fwd.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Return the greatest element of a non-empty structure with respect to
+ //! a `predicate`, by default `less`.
+ //! @ingroup group-Foldable
+ //!
+ //! Given a non-empty structure and an optional binary predicate
+ //! (`less` by default), `maximum` returns the greatest element of
+ //! the structure, i.e. an element which is greater than or equal to
+ //! every other element in the structure, according to the predicate.
+ //!
+ //! If the structure contains heterogeneous objects, then the predicate
+ //! must return a compile-time `Logical`. If no predicate is provided,
+ //! the elements in the structure must be Orderable, or compile-time
+ //! Orderable if the structure is heterogeneous.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a Foldable `F`, a Logical `Bool` and a predicate
+ //! \f$ \mathtt{pred} : T \times T \to Bool \f$, `maximum` has the
+ //! following signatures. For the variant with a provided predicate,
+ //! \f[
+ //! \mathtt{maximum} : F(T) \times (T \times T \to Bool) \to T
+ //! \f]
+ //!
+ //! for the variant without a custom predicate, `T` is required to be
+ //! Orderable. The signature is then
+ //! \f[
+ //! \mathtt{maximum} : F(T) \to T
+ //! \f]
+ //!
+ //! @param xs
+ //! The structure to find the greatest element of.
+ //!
+ //! @param predicate
+ //! A function called as `predicate(x, y)`, where `x` and `y` are elements
+ //! of the structure. `predicate` should be a strict weak ordering on the
+ //! elements of the structure and its return value should be a Logical,
+ //! or a compile-time Logical if the structure is heterogeneous.
+ //!
+ //! ### Example
+ //! @include example/maximum.cpp
+ //!
+ //!
+ //! Syntactic sugar (`maximum.by`)
+ //! ------------------------------
+ //! `maximum` can be called in a third way, which provides a nice syntax
+ //! especially when working with the `ordering` combinator:
+ //! @code
+ //! maximum.by(predicate, xs) == maximum(xs, predicate)
+ //! maximum.by(predicate) == maximum(-, predicate)
+ //! @endcode
+ //!
+ //! where `maximum(-, predicate)` denotes the partial application of
+ //! `maximum` to `predicate`.
+ //!
+ //! ### Example
+ //! @include example/maximum_by.cpp
+ //!
+ //!
+ //! Tag dispatching
+ //! ---------------
+ //! Both the non-predicated version and the predicated versions of
+ //! `maximum` are tag-dispatched methods, and hence they can be
+ //! customized independently. One reason for this is that some
+ //! structures are able to provide a much more efficient implementation
+ //! of `maximum` when the `less` predicate is used. Here is how the
+ //! different versions of `maximum` are dispatched:
+ //! @code
+ //! maximum(xs) -> maximum_impl<tag of xs>::apply(xs)
+ //! maximum(xs, pred) -> maximum_pred_impl<tag of xs>::apply(xs, pred)
+ //! @endcode
+ //!
+ //! Also note that `maximum.by` is not tag-dispatched on its own, since it
+ //! is just syntactic sugar for calling the corresponding `maximum`.
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto maximum = [](auto&& xs[, auto&& predicate]) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename = void>
+ struct maximum_impl : maximum_impl<T, when<true>> { };
+
+ template <typename T, typename = void>
+ struct maximum_pred_impl : maximum_pred_impl<T, when<true>> { };
+
+ struct maximum_t : detail::nested_by<maximum_t> {
+ template <typename Xs>
+ constexpr decltype(auto) operator()(Xs&& xs) const;
+
+ template <typename Xs, typename Predicate>
+ constexpr decltype(auto) operator()(Xs&& xs, Predicate&& pred) const;
+ };
+
+ constexpr maximum_t maximum{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_MAXIMUM_HPP
diff --git a/boost/hana/fwd/members.hpp b/boost/hana/fwd/members.hpp
new file mode 100644
index 0000000000..aaf9472faa
--- /dev/null
+++ b/boost/hana/fwd/members.hpp
@@ -0,0 +1,46 @@
+/*!
+@file
+Forward declares `boost::hana::members`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_MEMBERS_HPP
+#define BOOST_HANA_FWD_MEMBERS_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns a `Sequence` containing the members of a `Struct`.
+ //! @ingroup group-Struct
+ //!
+ //! Given a `Struct` object, `members` returns a `Sequence` containing
+ //! all the members of the `Struct`, in the same order as their respective
+ //! accessor appears in the `accessors` sequence.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/members.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto members = [](auto&& object) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct members_impl : members_impl<S, when<true>> { };
+
+ struct members_t {
+ template <typename Object>
+ constexpr auto operator()(Object&& object) const;
+ };
+
+ constexpr members_t members{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_MEMBERS_HPP
diff --git a/boost/hana/fwd/min.hpp b/boost/hana/fwd/min.hpp
new file mode 100644
index 0000000000..2aeb7bda22
--- /dev/null
+++ b/boost/hana/fwd/min.hpp
@@ -0,0 +1,51 @@
+/*!
+@file
+Forward declares `boost::hana::min`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_MIN_HPP
+#define BOOST_HANA_FWD_MIN_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns the smallest of its arguments according to the `less` ordering.
+ //! @ingroup group-Orderable
+ //!
+ //!
+ //! @todo
+ //! We can't specify the signature right now, because the tag of the
+ //! returned object depends on whether `x < y` or not. If we wanted to be
+ //! mathematically correct, we should probably ask that `if_(cond, x, y)`
+ //! returns a common data type of `x` and `y`, and then the behavior
+ //! of `min` would follow naturally. However, I'm unsure whether this
+ //! is desirable because that's a big requirement.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/min.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto min = [](auto&& x, auto&& y) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename U, typename = void>
+ struct min_impl : min_impl<T, U, when<true>> { };
+
+ struct min_t {
+ template <typename X, typename Y>
+ constexpr decltype(auto) operator()(X&& x, Y&& y) const;
+ };
+
+ constexpr min_t min{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_MIN_HPP
diff --git a/boost/hana/fwd/minimum.hpp b/boost/hana/fwd/minimum.hpp
new file mode 100644
index 0000000000..93926d92a6
--- /dev/null
+++ b/boost/hana/fwd/minimum.hpp
@@ -0,0 +1,116 @@
+/*!
+@file
+Forward declares `boost::hana::minimum`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_MINIMUM_HPP
+#define BOOST_HANA_FWD_MINIMUM_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/detail/nested_by_fwd.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Return the least element of a non-empty structure with respect to
+ //! a `predicate`, by default `less`.
+ //! @ingroup group-Foldable
+ //!
+ //! Given a non-empty structure and an optional binary predicate
+ //! (`less` by default), `minimum` returns the least element of
+ //! the structure, i.e. an element which is less than or equal to
+ //! every other element in the structure, according to the predicate.
+ //!
+ //! If the structure contains heterogeneous objects, then the predicate
+ //! must return a compile-time `Logical`. If no predicate is provided,
+ //! the elements in the structure must be Orderable, or compile-time
+ //! Orderable if the structure is heterogeneous.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a `Foldable` `F`, a Logical `Bool` and a predicate
+ //! \f$ \mathtt{pred} : T \times T \to Bool \f$, `minimum` has the
+ //! following signatures. For the variant with a provided predicate,
+ //! \f[
+ //! \mathtt{minimum} : F(T) \times (T \times T \to Bool) \to T
+ //! \f]
+ //!
+ //! for the variant without a custom predicate, `T` is required to be
+ //! Orderable. The signature is then
+ //! \f[
+ //! \mathtt{minimum} : F(T) \to T
+ //! \f]
+ //!
+ //! @param xs
+ //! The structure to find the least element of.
+ //!
+ //! @param predicate
+ //! A function called as `predicate(x, y)`, where `x` and `y` are elements
+ //! of the structure. `predicate` should be a strict weak ordering on the
+ //! elements of the structure and its return value should be a Logical,
+ //! or a compile-time Logical if the structure is heterogeneous.
+ //!
+ //! ### Example
+ //! @include example/minimum.cpp
+ //!
+ //!
+ //! Syntactic sugar (`minimum.by`)
+ //! ------------------------------
+ //! `minimum` can be called in a third way, which provides a nice syntax
+ //! especially when working with the `ordering` combinator:
+ //! @code
+ //! minimum.by(predicate, xs) == minimum(xs, predicate)
+ //! minimum.by(predicate) == minimum(-, predicate)
+ //! @endcode
+ //!
+ //! where `minimum(-, predicate)` denotes the partial application of
+ //! `minimum` to `predicate`.
+ //!
+ //! ### Example
+ //! @include example/minimum_by.cpp
+ //!
+ //!
+ //! Tag dispatching
+ //! ---------------
+ //! Both the non-predicated version and the predicated versions of
+ //! `minimum` are tag-dispatched methods, and hence they can be
+ //! customized independently. One reason for this is that some
+ //! structures are able to provide a much more efficient implementation
+ //! of `minimum` when the `less` predicate is used. Here is how the
+ //! different versions of `minimum` are dispatched:
+ //! @code
+ //! minimum(xs) -> minimum_impl<tag of xs>::apply(xs)
+ //! minimum(xs, pred) -> minimum_pred_impl<tag of xs>::apply(xs, pred)
+ //! @endcode
+ //!
+ //! Also note that `minimum.by` is not tag-dispatched on its own, since it
+ //! is just syntactic sugar for calling the corresponding `minimum`.
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto minimum = [](auto&& xs[, auto&& predicate]) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename = void>
+ struct minimum_impl : minimum_impl<T, when<true>> { };
+
+ template <typename T, typename = void>
+ struct minimum_pred_impl : minimum_pred_impl<T, when<true>> { };
+
+ struct minimum_t : detail::nested_by<minimum_t> {
+ template <typename Xs>
+ constexpr decltype(auto) operator()(Xs&& xs) const;
+
+ template <typename Xs, typename Predicate>
+ constexpr decltype(auto) operator()(Xs&& xs, Predicate&& pred) const;
+ };
+
+ constexpr minimum_t minimum{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_MINIMUM_HPP
diff --git a/boost/hana/fwd/minus.hpp b/boost/hana/fwd/minus.hpp
new file mode 100644
index 0000000000..a113e47dbb
--- /dev/null
+++ b/boost/hana/fwd/minus.hpp
@@ -0,0 +1,67 @@
+/*!
+@file
+Forward declares `boost::hana::minus`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_MINUS_HPP
+#define BOOST_HANA_FWD_MINUS_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Subtract two elements of a group.
+ //! @ingroup group-Group
+ //!
+ //! Specifically, this performs the `Monoid` operation on the first
+ //! argument and on the inverse of the second argument, thus being
+ //! equivalent to:
+ //! @code
+ //! minus(x, y) == plus(x, negate(y))
+ //! @endcode
+ //!
+ //!
+ //! Cross-type version of the method
+ //! --------------------------------
+ //! The `minus` method is "overloaded" to handle distinct data types
+ //! with certain properties. Specifically, `minus` is defined for
+ //! _distinct_ data types `A` and `B` such that
+ //! 1. `A` and `B` share a common data type `C`, as determined by the
+ //! `common` metafunction
+ //! 2. `A`, `B` and `C` are all `Group`s when taken individually
+ //! 3. `to<C> : A -> B` and `to<C> : B -> C` are `Group`-embeddings, as
+ //! determined by the `is_embedding` metafunction.
+ //!
+ //! The definition of `minus` for data types satisfying the above
+ //! properties is obtained by setting
+ //! @code
+ //! minus(x, y) = minus(to<C>(x), to<C>(y))
+ //! @endcode
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/minus.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto minus = [](auto&& x, auto&& y) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename U, typename = void>
+ struct minus_impl : minus_impl<T, U, when<true>> { };
+
+ struct minus_t {
+ template <typename X, typename Y>
+ constexpr decltype(auto) operator()(X&& x, Y&& y) const;
+ };
+
+ constexpr minus_t minus{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_MINUS_HPP
diff --git a/boost/hana/fwd/mod.hpp b/boost/hana/fwd/mod.hpp
new file mode 100644
index 0000000000..1ed87eb5a5
--- /dev/null
+++ b/boost/hana/fwd/mod.hpp
@@ -0,0 +1,62 @@
+/*!
+@file
+Forward declares `boost::hana::mod`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_MOD_HPP
+#define BOOST_HANA_FWD_MOD_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Generalized integer modulus.
+ //! @ingroup group-EuclideanRing
+ //!
+ //! Given two elements of an EuclideanRing `x` and `y`, with `y`
+ //! nonzero, `mod` returns the modulus of the division of `x` by `y`.
+ //! In other words, `mod` can be seen as an equivalent to `%`.
+ //!
+ //! Cross-type version of the method
+ //! --------------------------------
+ //! The `mod` method is "overloaded" to handle distinct data types
+ //! with certain properties. Specifically, `mod` is defined for
+ //! _distinct_ data types `A` and `B` such that
+ //! 1. `A` and `B` share a common data type `C`, as determined by the
+ //! `common` metafunction
+ //! 2. `A`, `B` and `C` are all `EuclideanRing`s when taken individually
+ //! 3. `to<C> : A -> B` and `to<C> : B -> C` are `Ring`-embeddings, as
+ //! determined by the `is_embedding` metafunction.
+ //!
+ //! In that case, `mod` is defined as
+ //! @code
+ //! mod(x, y) = mod(to<C>(x), to<C>(y))
+ //! @endcode
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/mod.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto mod = [](auto&& x, auto&& y) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename U, typename = void>
+ struct mod_impl : mod_impl<T, U, when<true>> { };
+
+ struct mod_t {
+ template <typename X, typename Y>
+ constexpr decltype(auto) operator()(X&& x, Y&& y) const;
+ };
+
+ constexpr mod_t mod{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_MOD_HPP
diff --git a/boost/hana/fwd/monadic_compose.hpp b/boost/hana/fwd/monadic_compose.hpp
new file mode 100644
index 0000000000..e5edfcc133
--- /dev/null
+++ b/boost/hana/fwd/monadic_compose.hpp
@@ -0,0 +1,75 @@
+/*!
+@file
+Forward declares `boost::hana::monadic_compose`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_MONADIC_COMPOSE_HPP
+#define BOOST_HANA_FWD_MONADIC_COMPOSE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Composition of monadic functions.
+ //! @ingroup group-Monad
+ //!
+ //! Given two monadic functions `f` and `g`, `monadic_compose` returns
+ //! a new function equivalent to the composition of `f` with `g`, except
+ //! the result of `g` is `chain`ed into `f` instead of simply passed to
+ //! it, as with normal composition. `monadic_compose` satisfies
+ //! @code
+ //! monadic_compose(f, g)(x) == chain(g(x), f)
+ //! @endcode
+ //!
+ //!
+ //! @note
+ //! Unlike `compose`, `monadic_compose` does not generalize nicely to
+ //! arities higher than one. Hence, only unary functions may be used
+ //! with `monadic_compose`.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a `Monad` `M` and two functions @f$ f : B \to M(C) @f$ and
+ //! @f$ g : A \to M(B) @f$, the signature is
+ //! @f$
+ //! \mathtt{monadic\_compose}
+ //! : (B \to M(C)) \times (A \to M(B)) \to (A \to M(C))
+ //! @f$.
+ //!
+ //! @param f
+ //! A monadic function with signature @f$ B \to M(C) @f$.
+ //!
+ //! @param g
+ //! A monadic function with signature @f$ A \to M(B) @f$.
+ //!
+ //!
+ //! @note
+ //! This method is not tag-dispatched, so it can't be customized directly.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/monadic_compose.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto monadic_compose = [](auto&& f, auto&& g) {
+ return [perfect-capture](auto&& x) -> decltype(auto) {
+ return hana::chain(forwarded(g)(forwarded(x)), forwarded(f));
+ };
+ };
+#else
+ struct monadic_compose_t {
+ template <typename F, typename G>
+ constexpr auto operator()(F&& f, G&& g) const;
+ };
+
+ constexpr monadic_compose_t monadic_compose{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_MONADIC_COMPOSE_HPP
diff --git a/boost/hana/fwd/monadic_fold_left.hpp b/boost/hana/fwd/monadic_fold_left.hpp
new file mode 100644
index 0000000000..786019b0b4
--- /dev/null
+++ b/boost/hana/fwd/monadic_fold_left.hpp
@@ -0,0 +1,104 @@
+/*!
+@file
+Forward declares `boost::hana::monadic_fold_left`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_MONADIC_FOLD_LEFT_HPP
+#define BOOST_HANA_FWD_MONADIC_FOLD_LEFT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Monadic left-fold of a structure with a binary operation and an
+ //! optional initial reduction state.
+ //! @ingroup group-Foldable
+ //!
+ //! @note
+ //! This assumes the reader to be accustomed to non-monadic left-folds as
+ //! explained by `hana::fold_left`, and to have read the [primer]
+ //! (@ref monadic-folds) on monadic folds.
+ //!
+ //! `monadic_fold_left<M>` is a left-associative monadic fold. Given a
+ //! `Foldable` with linearization `[x1, ..., xn]`, a function `f` and an
+ //! optional initial state, `monadic_fold_left<M>` applies `f` as follows:
+ //! @code
+ //! // with state
+ //! ((((f(state, x1) | f(-, x2)) | f(-, x3)) | ...) | f(-, xn))
+ //!
+ //! // without state
+ //! ((((f(x1, x2) | f(-, x3)) | f(-, x4)) | ...) | f(-, xn))
+ //! @endcode
+ //!
+ //! where `f(-, xk)` denotes the partial application of `f` to `xk`, and
+ //! `|` is just the operator version of the monadic `chain`.
+ //!
+ //! When the structure is empty, one of two things may happen. If an
+ //! initial state was provided, it is lifted to the given Monad and
+ //! returned as-is. Otherwise, if the no-state version of the function
+ //! was used, an error is triggered. When the stucture contains a single
+ //! element and the no-state version of the function was used, that
+ //! single element is lifted into the given Monad and returned as is.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a `Monad` `M`, a `Foldable` `F`, an initial state of tag `S`,
+ //! and a function @f$ f : S \times T \to M(S) @f$, the signatures of
+ //! `monadic_fold_left<M>` are
+ //! \f[
+ //! \mathtt{monadic\_fold\_left}_M :
+ //! F(T) \times S \times (S \times T \to M(S)) \to M(S)
+ //! \f]
+ //!
+ //! for the version with an initial state, and
+ //! \f[
+ //! \mathtt{monadic\_fold\_left}_M :
+ //! F(T) \times (T \times T \to M(T)) \to M(T)
+ //! \f]
+ //!
+ //! for the version without an initial state.
+ //!
+ //! @tparam M
+ //! The Monad representing the monadic context in which the fold happens.
+ //! The return type of `f` must be in that Monad.
+ //!
+ //! @param xs
+ //! The structure to fold.
+ //!
+ //! @param state
+ //! The initial value used for folding. If the structure is empty, this
+ //! value is lifted in to the `M` Monad and then returned as-is.
+ //!
+ //! @param f
+ //! A binary function called as `f(state, x)`, where `state` is the result
+ //! accumulated so far and `x` is an element in the structure. The
+ //! function must return its result inside the `M` Monad.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/monadic_fold_left.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename M>
+ constexpr auto monadic_fold_left = [](auto&& xs[, auto&& state], auto&& f) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename = void>
+ struct monadic_fold_left_impl : monadic_fold_left_impl<T, when<true>> { };
+
+ template <typename M>
+ struct monadic_fold_left_t;
+
+ template <typename M>
+ constexpr monadic_fold_left_t<M> monadic_fold_left{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_MONADIC_FOLD_LEFT_HPP
diff --git a/boost/hana/fwd/monadic_fold_right.hpp b/boost/hana/fwd/monadic_fold_right.hpp
new file mode 100644
index 0000000000..692eacbdf4
--- /dev/null
+++ b/boost/hana/fwd/monadic_fold_right.hpp
@@ -0,0 +1,106 @@
+/*!
+@file
+Forward declares `boost::hana::monadic_fold_right`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_MONADIC_FOLD_RIGHT_HPP
+#define BOOST_HANA_FWD_MONADIC_FOLD_RIGHT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Monadic right-fold of a structure with a binary operation and an
+ //! optional initial reduction state.
+ //! @ingroup group-Foldable
+ //!
+ //! @note
+ //! This assumes the reader to be accustomed to non-monadic right-folds as
+ //! explained by `hana::fold_right`, and to have read the [primer]
+ //! (@ref monadic-folds) on monadic folds.
+ //!
+ //! `monadic_fold_right<M>` is a right-associative monadic fold. Given a
+ //! structure containing `x1, ..., xn`, a function `f` and an optional
+ //! initial state, `monadic_fold_right<M>` applies `f` as follows
+ //! @code
+ //! // with state
+ //! (f(x1, -) | (f(x2, -) | (f(x3, -) | (... | f(xn, state)))))
+ //!
+ //! // without state
+ //! (f(x1, -) | (f(x2, -) | (f(x3, -) | (... | f(xn-1, xn)))))
+ //! @endcode
+ //!
+ //! where `f(xk, -)` denotes the partial application of `f` to `xk`,
+ //! and `|` is just the operator version of the monadic `chain`.
+ //! It is worth noting that the order in which the binary function should
+ //! expect its arguments is reversed from `monadic_fold_left<M>`.
+ //!
+ //! When the structure is empty, one of two things may happen. If an
+ //! initial state was provided, it is lifted to the given Monad and
+ //! returned as-is. Otherwise, if the no-state version of the function
+ //! was used, an error is triggered. When the stucture contains a single
+ //! element and the no-state version of the function was used, that
+ //! single element is lifted into the given Monad and returned as is.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a `Monad` `M`, a `Foldable` `F`, an initial state of tag `S`,
+ //! and a function @f$ f : T \times S \to M(S) @f$, the signatures of
+ //! `monadic_fold_right<M>` are
+ //! \f[
+ //! \mathtt{monadic\_fold\_right}_M :
+ //! F(T) \times S \times (T \times S \to M(S)) \to M(S)
+ //! \f]
+ //!
+ //! for the version with an initial state, and
+ //! \f[
+ //! \mathtt{monadic\_fold\_right}_M :
+ //! F(T) \times (T \times T \to M(T)) \to M(T)
+ //! \f]
+ //!
+ //! for the version without an initial state.
+ //!
+ //! @tparam M
+ //! The Monad representing the monadic context in which the fold happens.
+ //! The return type of `f` must be in that Monad.
+ //!
+ //! @param xs
+ //! The structure to fold.
+ //!
+ //! @param state
+ //! The initial value used for folding. If the structure is empty, this
+ //! value is lifted in to the `M` Monad and then returned as-is.
+ //!
+ //! @param f
+ //! A binary function called as `f(x, state)`, where `state` is the result
+ //! accumulated so far and `x` is an element in the structure. The
+ //! function must return its result inside the `M` Monad.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/monadic_fold_right.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename M>
+ constexpr auto monadic_fold_right = [](auto&& xs[, auto&& state], auto&& f) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename = void>
+ struct monadic_fold_right_impl : monadic_fold_right_impl<T, when<true>> { };
+
+ template <typename M>
+ struct monadic_fold_right_t;
+
+ template <typename M>
+ constexpr monadic_fold_right_t<M> monadic_fold_right{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_MONADIC_FOLD_RIGHT_HPP
diff --git a/boost/hana/fwd/mult.hpp b/boost/hana/fwd/mult.hpp
new file mode 100644
index 0000000000..cc624e76f2
--- /dev/null
+++ b/boost/hana/fwd/mult.hpp
@@ -0,0 +1,63 @@
+/*!
+@file
+Forward declares `boost::hana::mult`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_MULT_HPP
+#define BOOST_HANA_FWD_MULT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Associative operation of a `Ring`.
+ //! @ingroup group-Ring
+ //!
+ //! @param x, y
+ //! Two `Ring` elements to combine with the `Ring` binary operation.
+ //!
+ //!
+ //! Cross-type version of the method
+ //! --------------------------------
+ //! The `mult` method is "overloaded" to handle distinct data types
+ //! with certain properties. Specifically, `mult` is defined for
+ //! _distinct_ data types `A` and `B` such that
+ //! 1. `A` and `B` share a common data type `C`, as determined by the
+ //! `common` metafunction
+ //! 2. `A`, `B` and `C` are all `Ring`s when taken individually
+ //! 3. `to<C> : A -> B` and `to<C> : B -> C` are `Ring`-embeddings, as
+ //! determined by the `is_embedding` metafunction.
+ //!
+ //! The definition of `mult` for data types satisfying the above
+ //! properties is obtained by setting
+ //! @code
+ //! mult(x, y) = mult(to<C>(x), to<C>(y))
+ //! @endcode
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/mult.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto mult = [](auto&& x, auto&& y) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename U, typename = void>
+ struct mult_impl : mult_impl<T, U, when<true>> { };
+
+ struct mult_t {
+ template <typename X, typename Y>
+ constexpr decltype(auto) operator()(X&& x, Y&& y) const;
+ };
+
+ constexpr mult_t mult{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_MULT_HPP
diff --git a/boost/hana/fwd/negate.hpp b/boost/hana/fwd/negate.hpp
new file mode 100644
index 0000000000..2be58f2252
--- /dev/null
+++ b/boost/hana/fwd/negate.hpp
@@ -0,0 +1,42 @@
+/*!
+@file
+Forward declares `boost::hana::negate`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_NEGATE_HPP
+#define BOOST_HANA_FWD_NEGATE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Return the inverse of an element of a group.
+ //! @ingroup group-Group
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/negate.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto negate = [](auto&& x) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename G, typename = void>
+ struct negate_impl : negate_impl<G, when<true>> { };
+
+ struct negate_t {
+ template <typename X>
+ constexpr decltype(auto) operator()(X&& x) const;
+ };
+
+ constexpr negate_t negate{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_NEGATE_HPP
diff --git a/boost/hana/fwd/none.hpp b/boost/hana/fwd/none.hpp
new file mode 100644
index 0000000000..158f4c93d7
--- /dev/null
+++ b/boost/hana/fwd/none.hpp
@@ -0,0 +1,46 @@
+/*!
+@file
+Forward declares `boost::hana::none`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_NONE_HPP
+#define BOOST_HANA_FWD_NONE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns whether all of the keys of the structure are false-valued.
+ //! @ingroup group-Searchable
+ //!
+ //! The keys of the structure must be `Logical`s. If the structure is not
+ //! finite, a true-valued key must appear at a finite "index" in order
+ //! for this method to finish.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/none.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto none = [](auto&& xs) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct none_impl : none_impl<S, when<true>> { };
+
+ struct none_t {
+ template <typename Xs>
+ constexpr auto operator()(Xs&& xs) const;
+ };
+
+ constexpr none_t none{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_NONE_HPP
diff --git a/boost/hana/fwd/none_of.hpp b/boost/hana/fwd/none_of.hpp
new file mode 100644
index 0000000000..2455f1a9da
--- /dev/null
+++ b/boost/hana/fwd/none_of.hpp
@@ -0,0 +1,55 @@
+/*!
+@file
+Forward declares `boost::hana::none_of`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_NONE_OF_HPP
+#define BOOST_HANA_FWD_NONE_OF_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns whether none of the keys of the structure satisfy the
+ //! `predicate`.
+ //! @ingroup group-Searchable
+ //!
+ //! If the structure is not finite, `predicate` has to return a true-
+ //! valued `Logical` after looking at a finite number of keys for this
+ //! method to finish.
+ //!
+ //!
+ //! @param xs
+ //! The structure to search.
+ //!
+ //! @param predicate
+ //! A function called as `predicate(k)`, where `k` is a key of the
+ //! structure, and returning a `Logical`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/none_of.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto none_of = [](auto&& xs, auto&& predicate) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct none_of_impl : none_of_impl<S, when<true>> { };
+
+ struct none_of_t {
+ template <typename Xs, typename Pred>
+ constexpr auto operator()(Xs&& xs, Pred&& pred) const;
+ };
+
+ constexpr none_of_t none_of{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_NONE_OF_HPP
diff --git a/boost/hana/fwd/not.hpp b/boost/hana/fwd/not.hpp
new file mode 100644
index 0000000000..f343a417ab
--- /dev/null
+++ b/boost/hana/fwd/not.hpp
@@ -0,0 +1,47 @@
+/*!
+@file
+Forward declares `boost::hana::not_`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_NOT_HPP
+#define BOOST_HANA_FWD_NOT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Negates a `Logical`.
+ //! @ingroup group-Logical
+ //!
+ //! This method returns a `Logical` with the same tag, but whose
+ //! truth-value is negated. Specifically, `not_(x)` returns a false-valued
+ //! `Logical` if `x` is a true-valued `Logical`, and a true-valued one
+ //! otherwise.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/not.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto not_ = [](auto&& x) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename L, typename = void>
+ struct not_impl : not_impl<L, when<true>> { };
+
+ struct not_t {
+ template <typename X>
+ constexpr decltype(auto) operator()(X&& x) const;
+ };
+
+ constexpr not_t not_{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_NOT_HPP
diff --git a/boost/hana/fwd/not_equal.hpp b/boost/hana/fwd/not_equal.hpp
new file mode 100644
index 0000000000..4c7bdbfbcf
--- /dev/null
+++ b/boost/hana/fwd/not_equal.hpp
@@ -0,0 +1,70 @@
+/*!
+@file
+Forward declares `boost::hana::not_equal`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_NOT_EQUAL_HPP
+#define BOOST_HANA_FWD_NOT_EQUAL_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/detail/nested_to_fwd.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns a `Logical` representing whether `x` is not equal to `y`.
+ //! @ingroup group-Comparable
+ //!
+ //! The `not_equal` function can be called in two different ways. First,
+ //! it can be called like a normal function:
+ //! @code
+ //! not_equal(x, y)
+ //! @endcode
+ //!
+ //! However, it may also be partially applied to an argument by using
+ //! `not_equal.to`:
+ //! @code
+ //! not_equal.to(x)(y) == not_equal(x, y)
+ //! @endcode
+ //!
+ //! In other words, `not_equal.to(x)` is a function object that is
+ //! equivalent to `partial(not_equal, x)`. This is provided to enhance
+ //! the readability of some constructs, especially when using higher
+ //! order algorithms.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a Logical `Bool` and two Comparables `A` and `B` that
+ //! share a common embedding, the signature is
+ //! @f$ \mathtt{not\_equal} : A \times B \to Bool @f$.
+ //!
+ //! @param x, y
+ //! Two objects to compare for inequality.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/not_equal.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto not_equal = [](auto&& x, auto&& y) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename U, typename = void>
+ struct not_equal_impl : not_equal_impl<T, U, when<true>> { };
+
+ struct not_equal_t : detail::nested_to<not_equal_t> {
+ template <typename X, typename Y>
+ constexpr auto operator()(X&& x, Y&& y) const;
+ };
+
+ constexpr not_equal_t not_equal{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_NOT_EQUAL_HPP
diff --git a/boost/hana/fwd/one.hpp b/boost/hana/fwd/one.hpp
new file mode 100644
index 0000000000..65df2bf3c4
--- /dev/null
+++ b/boost/hana/fwd/one.hpp
@@ -0,0 +1,45 @@
+/*!
+@file
+Forward declares `boost::hana::one`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_ONE_HPP
+#define BOOST_HANA_FWD_ONE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Identity of the `Ring` multiplication.
+ //! @ingroup group-Ring
+ //!
+ //! @tparam R
+ //! The tag (must be a model of `Ring`) of the returned identity.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/one.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename R>
+ constexpr auto one = []() -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename R, typename = void>
+ struct one_impl : one_impl<R, when<true>> { };
+
+ template <typename R>
+ struct one_t;
+
+ template <typename R>
+ constexpr one_t<R> one{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_ONE_HPP
diff --git a/boost/hana/fwd/optional.hpp b/boost/hana/fwd/optional.hpp
new file mode 100644
index 0000000000..934eca809a
--- /dev/null
+++ b/boost/hana/fwd/optional.hpp
@@ -0,0 +1,510 @@
+/*!
+@file
+Forward declares `boost::hana::optional`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_OPTIONAL_HPP
+#define BOOST_HANA_FWD_OPTIONAL_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/operators/adl.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-datatypes
+ //! Optional value whose optional-ness is known at compile-time.
+ //!
+ //! An `optional` either contains a value (represented as `just(x)`), or
+ //! it is empty (represented as `nothing`). In essence, `hana::optional`
+ //! is pretty much like a `boost::optional` or the upcoming `std::optional`,
+ //! except for the fact that whether a `hana::optional` is empty or not is
+ //! known at compile-time. This can be particularly useful for returning
+ //! from a function that might fail, but whose reason for failing is not
+ //! important. Of course, whether the function will fail has to be known
+ //! at compile-time.
+ //!
+ //! This is really an important difference between `hana::optional` and
+ //! `std::optional`. Unlike `std::optional<T>{}` and `std::optional<T>{x}`
+ //! who share the same type (`std::optional<T>`), `hana::just(x)` and
+ //! `hana::nothing` do not share the same type, since the state of the
+ //! optional has to be known at compile-time. Hence, whether a `hana::just`
+ //! or a `hana::nothing` will be returned from a function has to be known
+ //! at compile-time for the return type of that function to be computable
+ //! by the compiler. This makes `hana::optional` well suited for static
+ //! metaprogramming tasks, but very poor for anything dynamic.
+ //!
+ //!
+ //! Interoperation with `type`s
+ //! ---------------------------
+ //! When a `just` contains an object of type `T` which is a `type`,
+ //! it has a nested `::%type` alias equivalent to `T::%type`. `nothing`,
+ //! however, never has a nested `::%type` alias. If `t` is a `type`,
+ //! this allows `decltype(just(t))` to be seen as a nullary metafunction
+ //! equivalent to `decltype(t)`. Along with the `sfinae` function,
+ //! this allows `hana::optional` to interact seamlessly with
+ //! SFINAE-friendly metafunctions.
+ //! Example:
+ //! @include example/optional/sfinae_friendly_metafunctions.cpp
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! 1. `Comparable`\n
+ //! Two `optional`s are equal if and only if they are both empty or they
+ //! both contain a value and those values are equal.
+ //! @include example/optional/comparable.cpp
+ //!
+ //! 2. `Orderable`\n
+ //! Optional values can be ordered by considering the value they are
+ //! holding, if any. To handle the case of an empty optional value, we
+ //! arbitrarily set `nothing` as being less than any other `just`. Hence,
+ //! @code
+ //! just(x) < just(y) if and only if x < y
+ //! nothing < just(anything)
+ //! @endcode
+ //! Example:
+ //! @include example/optional/orderable.cpp
+ //!
+ //! 3. `Functor`\n
+ //! An optional value can be seen as a list containing either one element
+ //! (`just(x)`) or no elements at all (`nothing`). As such, mapping
+ //! a function over an optional value is equivalent to applying it to
+ //! its value if there is one, and to `nothing` otherwise:
+ //! @code
+ //! transform(just(x), f) == just(f(x))
+ //! transform(nothing, f) == nothing
+ //! @endcode
+ //! Example:
+ //! @include example/optional/functor.cpp
+ //!
+ //! 4. `Applicative`\n
+ //! First, a value can be made optional with `lift<optional_tag>`, which
+ //! is equivalent to `just`. Second, one can feed an optional value to an
+ //! optional function with `ap`, which will return `just(f(x))` if there
+ //! is both a function _and_ a value, and `nothing` otherwise:
+ //! @code
+ //! ap(just(f), just(x)) == just(f(x))
+ //! ap(nothing, just(x)) == nothing
+ //! ap(just(f), nothing) == nothing
+ //! ap(nothing, nothing) == nothing
+ //! @endcode
+ //! A simple example:
+ //! @include example/optional/applicative.cpp
+ //! A more complex example:
+ //! @include example/optional/applicative.complex.cpp
+ //!
+ //! 5. `Monad`\n
+ //! The `Monad` model makes it easy to compose actions that might fail.
+ //! One can feed an optional value if there is one into a function with
+ //! `chain`, which will return `nothing` if there is no value. Finally,
+ //! optional-optional values can have their redundant level of optionality
+ //! removed with `flatten`. Also note that the `|` operator can be used in
+ //! place of the `chain` function.
+ //! Example:
+ //! @include example/optional/monad.cpp
+ //!
+ //! 6. `MonadPlus`\n
+ //! The `MonadPlus` model allows choosing the first valid value out of
+ //! two optional values with `concat`. If both optional values are
+ //! `nothing`s, `concat` will return `nothing`.
+ //! Example:
+ //! @include example/optional/monad_plus.cpp
+ //!
+ //! 7. `Foldable`\n
+ //! Folding an optional value is equivalent to folding a list containing
+ //! either no elements (for `nothing`) or `x` (for `just(x)`).
+ //! Example:
+ //! @include example/optional/foldable.cpp
+ //!
+ //! 8. `Searchable`\n
+ //! Searching an optional value is equivalent to searching a list
+ //! containing `x` for `just(x)` and an empty list for `nothing`.
+ //! Example:
+ //! @include example/optional/searchable.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename ...T>
+ struct optional {
+ // 5.3.1, Constructors
+
+ //! Default-construct an `optional`. Only exists if the optional
+ //! contains a value, and if that value is DefaultConstructible.
+ constexpr optional() = default;
+
+ //! Copy-construct an `optional`.
+ //! An empty optional may only be copy-constructed from another
+ //! empty `optional`, and an `optional` with a value may only be
+ //! copy-constructed from another `optional` with a value.
+ //! Furthermore, this constructor only exists if the value
+ //! held in the `optional` is CopyConstructible.
+ optional(optional const&) = default;
+
+ //! Move-construct an `optional`.
+ //! An empty optional may only be move-constructed from another
+ //! empty `optional`, and an `optional` with a value may only be
+ //! move-constructed from another `optional` with a value.
+ //! Furthermore, this constructor only exists if the value
+ //! held in the `optional` is MoveConstructible.
+ optional(optional&&) = default;
+
+ //! Construct an `optional` holding a value of type `T` from another
+ //! object of type `T`. The value is copy-constructed.
+ constexpr optional(T const& t)
+ : value_(t)
+ { }
+
+ //! Construct an `optional` holding a value of type `T` from another
+ //! object of type `T`. The value is move-constructed.
+ constexpr optional(T&& t)
+ : value_(static_cast<T&&>(t))
+ { }
+
+ // 5.3.3, Assignment
+
+ //! Copy-assign an `optional`.
+ //! An empty optional may only be copy-assigned from another empty
+ //! `optional`, and an `optional` with a value may only be copy-assigned
+ //! from another `optional` with a value. Furthermore, this assignment
+ //! operator only exists if the value held in the `optional` is
+ //! CopyAssignable.
+ constexpr optional& operator=(optional const&) = default;
+
+ //! Move-assign an `optional`.
+ //! An empty optional may only be move-assigned from another empty
+ //! `optional`, and an `optional` with a value may only be move-assigned
+ //! from another `optional` with a value. Furthermore, this assignment
+ //! operator only exists if the value held in the `optional` is
+ //! MoveAssignable.
+ constexpr optional& operator=(optional&&) = default;
+
+ // 5.3.5, Observers
+
+ //! Returns a pointer to the contained value, or a `nullptr` if the
+ //! `optional` is empty.
+ //!
+ //!
+ //! @note Overloads of this method are provided for both the `const`
+ //! and the non-`const` cases.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/optional/value.cpp
+ constexpr T* operator->();
+
+ //! Extract the content of an `optional`, or fail at compile-time.
+ //!
+ //! If `*this` contains a value, that value is returned. Otherwise,
+ //! a static assertion is triggered.
+ //!
+ //! @note
+ //! Overloads of this method are provided for the cases where `*this`
+ //! is a reference, a rvalue-reference and their `const` counterparts.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/optional/value.cpp
+ constexpr T& value();
+
+ //! Equivalent to `value()`, provided for convenience.
+ //!
+ //! @note
+ //! Overloads of this method are provided for the cases where `*this`
+ //! is a reference, a rvalue-reference and their `const` counterparts.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/optional/value.cpp
+ constexpr T& operator*();
+
+ //! Return the contents of an `optional`, with a fallback result.
+ //!
+ //! If `*this` contains a value, that value is returned. Otherwise,
+ //! the default value provided is returned.
+ //!
+ //! @note
+ //! Overloads of this method are provided for the cases where `*this`
+ //! is a reference, a rvalue-reference and their `const` counterparts.
+ //!
+ //!
+ //! @param default_
+ //! The default value to return if `*this` does not contain a value.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/optional/value_or.cpp
+ template <typename U>
+ constexpr decltype(auto) value_or(U&& default_);
+
+ //! Equivalent to `hana::chain`.
+ template <typename ...T, typename F>
+ friend constexpr auto operator|(optional<T...>, F);
+
+ //! Equivalent to `hana::equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator==(X&& x, Y&& y);
+
+ //! Equivalent to `hana::not_equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator!=(X&& x, Y&& y);
+
+ //! Equivalent to `hana::less`
+ template <typename X, typename Y>
+ friend constexpr auto operator<(X&& x, Y&& y);
+
+ //! Equivalent to `hana::greater`
+ template <typename X, typename Y>
+ friend constexpr auto operator>(X&& x, Y&& y);
+
+ //! Equivalent to `hana::less_equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator<=(X&& x, Y&& y);
+
+ //! Equivalent to `hana::greater_equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator>=(X&& x, Y&& y);
+ };
+#else
+ template <typename ...T>
+ struct optional;
+#endif
+
+ //! Tag representing a `hana::optional`.
+ //! @relates hana::optional
+ struct optional_tag { };
+
+ //! Create an optional value.
+ //! @relates hana::optional
+ //!
+ //! Specifically, `make<optional_tag>()` is equivalent to `nothing`, and
+ //! `make<optional_tag>(x)` is equivalent to `just(x)`. This is provided
+ //! for consistency with the other `make<...>` functions.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/optional/make.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <>
+ constexpr auto make<optional_tag> = []([auto&& x]) {
+ return optional<std::decay<decltype(x)>::type>{forwarded(x)};
+ };
+#endif
+
+ //! Alias to `make<optional_tag>`; provided for convenience.
+ //! @relates hana::optional
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/optional/make.cpp
+ constexpr auto make_optional = make<optional_tag>;
+
+ //! Create an optional value containing `x`.
+ //! @relates hana::optional
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/optional/just.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto just = [](auto&& x) {
+ return optional<std::decay<decltype(x)>::type>{forwarded(x)};
+ };
+#else
+ struct make_just_t {
+ template <typename T>
+ constexpr auto operator()(T&&) const;
+ };
+
+ constexpr make_just_t just{};
+#endif
+
+ //! An empty optional value.
+ //! @relates hana::optional
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/optional/nothing.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr optional<> nothing{};
+#else
+ template <>
+ struct optional<> : detail::operators::adl<optional<>> {
+ // 5.3.1, Constructors
+ constexpr optional() = default;
+ constexpr optional(optional const&) = default;
+ constexpr optional(optional&&) = default;
+
+ // 5.3.3, Assignment
+ constexpr optional& operator=(optional const&) = default;
+ constexpr optional& operator=(optional&&) = default;
+
+ // 5.3.5, Observers
+ constexpr decltype(nullptr) operator->() const { return nullptr; }
+
+ template <typename ...dummy>
+ constexpr auto value() const;
+
+ template <typename ...dummy>
+ constexpr auto operator*() const;
+
+ template <typename U>
+ constexpr U&& value_or(U&& u) const;
+ };
+
+ constexpr optional<> nothing{};
+#endif
+
+ //! Apply a function to the contents of an optional, with a fallback
+ //! result.
+ //! @relates hana::optional
+ //!
+ //! Specifically, `maybe` takes a default value, a function and an
+ //! optional value. If the optional value is `nothing`, the default
+ //! value is returned. Otherwise, the function is applied to the
+ //! content of the `just`.
+ //!
+ //!
+ //! @param default_
+ //! A default value returned if `m` is `nothing`.
+ //!
+ //! @param f
+ //! A function called as `f(x)` if and only if `m` is an optional value
+ //! of the form `just(x)`. In that case, the result returend by `maybe`
+ //! is the result of `f`.
+ //!
+ //! @param m
+ //! An optional value.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/optional/maybe.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto maybe = [](auto&& default_, auto&& f, auto&& m) -> decltype(auto) {
+ if (m is a just(x)) {
+ return forwarded(f)(forwarded(x));
+ else
+ return forwarded(default_);
+ }
+ };
+#else
+ struct maybe_t {
+ template <typename Def, typename F, typename T>
+ constexpr decltype(auto) operator()(Def&&, F&& f, optional<T> const& m) const
+ { return static_cast<F&&>(f)(m.value_); }
+
+ template <typename Def, typename F, typename T>
+ constexpr decltype(auto) operator()(Def&&, F&& f, optional<T>& m) const
+ { return static_cast<F&&>(f)(m.value_); }
+
+ template <typename Def, typename F, typename T>
+ constexpr decltype(auto) operator()(Def&&, F&& f, optional<T>&& m) const
+ { return static_cast<F&&>(f)(static_cast<optional<T>&&>(m).value_); }
+
+ template <typename Def, typename F>
+ constexpr Def operator()(Def&& def, F&&, optional<> const&) const
+ { return static_cast<Def&&>(def); }
+ };
+
+ constexpr maybe_t maybe{};
+#endif
+
+ //! Calls a function if the call expression is well-formed.
+ //! @relates hana::optional
+ //!
+ //! Given a function `f`, `sfinae` returns a new function applying `f`
+ //! to its arguments and returning `just` the result if the call is
+ //! well-formed, and `nothing` otherwise. In other words, `sfinae(f)(x...)`
+ //! is `just(f(x...))` if that expression is well-formed, and `nothing`
+ //! otherwise. Note, however, that it is possible for an expression
+ //! `f(x...)` to be well-formed as far as SFINAE is concerned, but
+ //! trying to actually compile `f(x...)` still fails. In this case,
+ //! `sfinae` won't be able to detect it and a hard failure is likely
+ //! to happen.
+ //!
+ //!
+ //! @note
+ //! The function given to `sfinae` must not return `void`, since
+ //! `just(void)` does not make sense. A compilation error is
+ //! triggered if the function returns void.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/optional/sfinae.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ auto sfinae = [](auto&& f) {
+ return [perfect-capture](auto&& ...x) {
+ if (decltype(forwarded(f)(forwarded(x)...)) is well-formed)
+ return just(forwarded(f)(forwarded(x)...));
+ else
+ return nothing;
+ };
+ };
+#else
+ struct sfinae_t {
+ template <typename F>
+ constexpr decltype(auto) operator()(F&& f) const;
+ };
+
+ constexpr sfinae_t sfinae{};
+#endif
+
+ //! Return whether an `optional` contains a value.
+ //! @relates hana::optional
+ //!
+ //! Specifically, returns a compile-time true-valued `Logical` if `m` is
+ //! of the form `just(x)` for some `x`, and a false-valued one otherwise.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/optional/is_just.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto is_just = [](auto const& m) {
+ return m is a just(x);
+ };
+#else
+ struct is_just_t {
+ template <typename ...T>
+ constexpr auto operator()(optional<T...> const&) const;
+ };
+
+ constexpr is_just_t is_just{};
+#endif
+
+ //! Return whether an `optional` is empty.
+ //! @relates hana::optional
+ //!
+ //! Specifically, returns a compile-time true-valued `Logical` if `m` is
+ //! a `nothing`, and a false-valued one otherwise.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/optional/is_nothing.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto is_nothing = [](auto const& m) {
+ return m is a nothing;
+ };
+#else
+ struct is_nothing_t {
+ template <typename ...T>
+ constexpr auto operator()(optional<T...> const&) const;
+ };
+
+ constexpr is_nothing_t is_nothing{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_OPTIONAL_HPP
diff --git a/boost/hana/fwd/or.hpp b/boost/hana/fwd/or.hpp
new file mode 100644
index 0000000000..1d2ad1a348
--- /dev/null
+++ b/boost/hana/fwd/or.hpp
@@ -0,0 +1,53 @@
+/*!
+@file
+Forward declares `boost::hana::or_`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_OR_HPP
+#define BOOST_HANA_FWD_OR_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Return whether any of the arguments is true-valued.
+ //! @ingroup group-Logical
+ //!
+ //! `or_` can be called with one argument or more. When called with
+ //! two arguments, `or_` uses tag-dispatching to find the right
+ //! implementation. Otherwise,
+ //! @code
+ //! or_(x) == x
+ //! or_(x, y, ...z) == or_(or_(x, y), z...)
+ //! @endcode
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/or.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto or_ = [](auto&& x, auto&& ...y) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename L, typename = void>
+ struct or_impl : or_impl<L, when<true>> { };
+
+ struct or_t {
+ template <typename X, typename Y>
+ constexpr decltype(auto) operator()(X&& x, Y&& y) const;
+
+ template <typename X, typename ...Y>
+ constexpr decltype(auto) operator()(X&& x, Y&& ...y) const;
+ };
+
+ constexpr or_t or_{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_OR_HPP
diff --git a/boost/hana/fwd/ordering.hpp b/boost/hana/fwd/ordering.hpp
new file mode 100644
index 0000000000..6e9f25dfa0
--- /dev/null
+++ b/boost/hana/fwd/ordering.hpp
@@ -0,0 +1,65 @@
+/*!
+@file
+Forward declares `boost::hana::ordering`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_ORDERING_HPP
+#define BOOST_HANA_FWD_ORDERING_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns a function performing `less` after applying a transformation
+ //! to both arguments.
+ //! @ingroup group-Orderable
+ //!
+ //! `ordering` creates a total order based on the result of applying a
+ //! function to some objects, which is especially useful in conjunction
+ //! with algorithms that accept a custom predicate that must represent
+ //! a total order.
+ //!
+ //! Specifically, `ordering` is such that
+ //! @code
+ //! ordering(f) == less ^on^ f
+ //! @endcode
+ //! or, equivalently,
+ //! @code
+ //! ordering(f)(x, y) == less(f(x), f(y))
+ //! @endcode
+ //!
+ //! @note
+ //! This is not a tag-dispatched method (hence it can't be customized),
+ //! but just a convenience function provided with the `Orderable` concept.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a Logical `Bool` and an Orderable `B`, the signature is
+ //! @f$ \mathrm{ordering} : (A \to B) \to (A \times A \to Bool) @f$.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/ordering.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto ordering = [](auto&& f) {
+ return [perfect-capture](auto&& x, auto&& y) -> decltype(auto) {
+ return less(f(forwarded(x)), f(forwarded(y)));
+ };
+ };
+#else
+ struct ordering_t {
+ template <typename F>
+ constexpr auto operator()(F&& f) const;
+ };
+
+ constexpr ordering_t ordering{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_ORDERING_HPP
diff --git a/boost/hana/fwd/pair.hpp b/boost/hana/fwd/pair.hpp
new file mode 100644
index 0000000000..0a36da1875
--- /dev/null
+++ b/boost/hana/fwd/pair.hpp
@@ -0,0 +1,153 @@
+/*!
+@file
+Forward declares `boost::hana::pair`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_PAIR_HPP
+#define BOOST_HANA_FWD_PAIR_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-datatypes
+ //! Generic container for two elements.
+ //!
+ //! `hana::pair` is conceptually the same as `std::pair`. However,
+ //! `hana::pair` automatically compresses the storage of empty types,
+ //! and as a result it does not have the `.first` and `.second` members.
+ //! Instead, one must use the `hana::first` and `hana::second` free
+ //! functions to access the elements of a pair.
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! 1. `Comparable`\n
+ //! Two pairs `(x, y)` and `(x', y')` are equal if and only if both
+ //! `x == x'` and `y == y'`.
+ //! @include example/pair/comparable.cpp
+ //!
+ //! 2. `Orderable`\n
+ //! Pairs are ordered as-if they were 2-element tuples, using a
+ //! lexicographical ordering.
+ //! @include example/pair/orderable.cpp
+ //!
+ //! 3. `Foldable`\n
+ //! Folding a pair is equivalent to folding a 2-element tuple. In other
+ //! words:
+ //! @code
+ //! fold_left(make_pair(x, y), s, f) == f(f(s, x), y)
+ //! fold_right(make_pair(x, y), s, f) == f(x, f(y, s))
+ //! @endcode
+ //! Example:
+ //! @include example/pair/foldable.cpp
+ //!
+ //! 4. `Product`\n
+ //! The model of `Product` is the simplest one possible; the first element
+ //! of a pair `(x, y)` is `x`, and its second element is `y`.
+ //! @include example/pair/product.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename First, typename Second>
+ struct pair {
+ //! Default constructs the `pair`. Only exists when both elements
+ //! of the pair are default constructible.
+ constexpr pair();
+
+ //! Initialize each element of the pair with the corresponding element.
+ //! Only exists when both elements of the pair are copy-constructible.
+ constexpr pair(First const& first, Second const& second);
+
+ //! Initialize both elements of the pair by perfect-forwarding the
+ //! corresponding argument. Only exists when both arguments are
+ //! implicitly-convertible to the corresponding element of the pair.
+ template <typename T, typename U>
+ constexpr pair(T&& t, U&& u);
+
+ //! Copy-initialize a pair from another pair. Only exists when both
+ //! elements of the source pair are implicitly convertible to the
+ //! corresponding element of the constructed pair.
+ template <typename T, typename U>
+ constexpr pair(pair<T, U> const& other);
+
+ //! Move-initialize a pair from another pair. Only exists when both
+ //! elements of the source pair are implicitly convertible to the
+ //! corresponding element of the constructed pair.
+ template <typename T, typename U>
+ constexpr pair(pair<T, U>&& other);
+
+ //! Assign a pair to another pair. Only exists when both elements
+ //! of the destination pair are assignable from the corresponding
+ //! element in the source pair.
+ template <typename T, typename U>
+ constexpr pair& operator=(pair<T, U> const& other);
+
+ //! Move-assign a pair to another pair. Only exists when both elements
+ //! of the destination pair are move-assignable from the corresponding
+ //! element in the source pair.
+ template <typename T, typename U>
+ constexpr pair& operator=(pair<T, U>&& other);
+
+ //! Equivalent to `hana::equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator==(X&& x, Y&& y);
+
+ //! Equivalent to `hana::not_equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator!=(X&& x, Y&& y);
+
+ //! Equivalent to `hana::less`
+ template <typename X, typename Y>
+ friend constexpr auto operator<(X&& x, Y&& y);
+
+ //! Equivalent to `hana::greater`
+ template <typename X, typename Y>
+ friend constexpr auto operator>(X&& x, Y&& y);
+
+ //! Equivalent to `hana::less_equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator<=(X&& x, Y&& y);
+
+ //! Equivalent to `hana::greater_equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator>=(X&& x, Y&& y);
+ };
+#else
+ template <typename First, typename Second>
+ struct pair;
+#endif
+
+ //! Tag representing `hana::pair`.
+ //! @relates hana::pair
+ struct pair_tag { };
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ //! Creates a `hana::pair` with the given elements.
+ //! @relates hana::pair
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/pair/make.cpp
+ template <>
+ constexpr auto make<pair_tag> = [](auto&& first, auto&& second)
+ -> hana::pair<std::decay_t<decltype(first)>, std::decay_t<decltype(second)>>
+ {
+ return {forwarded(first), forwarded(second)};
+ };
+#endif
+
+ //! Alias to `make<pair_tag>`; provided for convenience.
+ //! @relates hana::pair
+ //!
+ //! Example
+ //! -------
+ //! @include example/pair/make.cpp
+ constexpr auto make_pair = make<pair_tag>;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_PAIR_HPP
diff --git a/boost/hana/fwd/partition.hpp b/boost/hana/fwd/partition.hpp
new file mode 100644
index 0000000000..d1fa9e7b1c
--- /dev/null
+++ b/boost/hana/fwd/partition.hpp
@@ -0,0 +1,89 @@
+/*!
+@file
+Forward declares `boost::hana::partition`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_PARTITION_HPP
+#define BOOST_HANA_FWD_PARTITION_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/detail/nested_by_fwd.hpp>
+
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Partition a sequence based on a `predicate`.
+ //! @ingroup group-Sequence
+ //!
+ //! Specifically, returns an unspecified `Product` whose first element is
+ //! a sequence of the elements satisfying the predicate, and whose second
+ //! element is a sequence of the elements that do not satisfy the predicate.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a Sequence `S(T)`, an `IntegralConstant` `Bool` holding a value
+ //! of type `bool`, and a predicate \f$ T \to Bool \f$, `partition` has
+ //! the following signature:
+ //! \f[
+ //! \mathtt{partition} : S(T) \times (T \to Bool) \to S(T) \times S(T)
+ //! \f]
+ //!
+ //! @param xs
+ //! The sequence to be partitioned.
+ //!
+ //! @param predicate
+ //! A function called as `predicate(x)` for each element `x` in the
+ //! sequence, and returning whether `x` should be added to the sequence
+ //! in the first component or in the second component of the resulting
+ //! pair. In the current version of the library, `predicate` must return
+ //! an `IntegralConstant` holding a value convertible to `bool`.
+ //!
+ //!
+ //! Syntactic sugar (`partition.by`)
+ //! --------------------------------
+ //! `partition` can be called in an alternate way, which provides a nice
+ //! syntax in some cases where the predicate is short:
+ //! @code
+ //! partition.by(predicate, xs) == partition(xs, predicate)
+ //! partition.by(predicate) == partition(-, predicate)
+ //! @endcode
+ //!
+ //! where `partition(-, predicate)` denotes the partial application of
+ //! `partition` to `predicate`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/partition.cpp
+ //!
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.partition.compile.json">
+ //! </div>
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto partition = [](auto&& xs, auto&& predicate) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct partition_impl : partition_impl<S, when<true>> { };
+
+ struct partition_t : detail::nested_by<partition_t> {
+ template <typename Xs, typename Pred>
+ constexpr auto operator()(Xs&& xs, Pred&& pred) const;
+ };
+
+ constexpr partition_t partition{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_PARTITION_HPP
diff --git a/boost/hana/fwd/permutations.hpp b/boost/hana/fwd/permutations.hpp
new file mode 100644
index 0000000000..af2805d333
--- /dev/null
+++ b/boost/hana/fwd/permutations.hpp
@@ -0,0 +1,50 @@
+/*!
+@file
+Forward declares `boost::hana::permutations`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_PERMUTATIONS_HPP
+#define BOOST_HANA_FWD_PERMUTATIONS_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Return a sequence of all the permutations of the given sequence.
+ //! @ingroup group-Sequence
+ //!
+ //! Specifically, `permutations(xs)` is a sequence whose elements are
+ //! permutations of the original sequence `xs`. The permutations are not
+ //! guaranteed to be in any specific order. Also note that the number
+ //! of permutations grows very rapidly as the length of the original
+ //! sequence increases. The growth rate is `O(length(xs)!)`; with a
+ //! sequence `xs` of length only 8, `permutations(xs)` contains over
+ //! 40 000 elements!
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/permutations.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto permutations = [](auto&& xs) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct permutations_impl : permutations_impl<S, when<true>> { };
+
+ struct permutations_t {
+ template <typename Xs>
+ constexpr auto operator()(Xs&& xs) const;
+ };
+
+ constexpr permutations_t permutations{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_PERMUTATIONS_HPP
diff --git a/boost/hana/fwd/plus.hpp b/boost/hana/fwd/plus.hpp
new file mode 100644
index 0000000000..e1a6e058f2
--- /dev/null
+++ b/boost/hana/fwd/plus.hpp
@@ -0,0 +1,63 @@
+/*!
+@file
+Forward declares `boost::hana::plus`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_PLUS_HPP
+#define BOOST_HANA_FWD_PLUS_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Associative binary operation on a `Monoid`.
+ //! @ingroup group-Monoid
+ //!
+ //! @param x, y
+ //! Two objects to combine with the `Monoid`'s binary operation.
+ //!
+ //!
+ //! Cross-type version of the method
+ //! --------------------------------
+ //! The `plus` method is "overloaded" to handle distinct data types
+ //! with certain properties. Specifically, `plus` is defined for
+ //! _distinct_ data types `A` and `B` such that
+ //! 1. `A` and `B` share a common data type `C`, as determined by the
+ //! `common` metafunction
+ //! 2. `A`, `B` and `C` are all `Monoid`s when taken individually
+ //! 3. `to<C> : A -> B` and `to<C> : B -> C` are `Monoid`-embeddings, as
+ //! determined by the `is_embedding` metafunction.
+ //!
+ //! The definition of `plus` for data types satisfying the above
+ //! properties is obtained by setting
+ //! @code
+ //! plus(x, y) = plus(to<C>(x), to<C>(y))
+ //! @endcode
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/plus.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto plus = [](auto&& x, auto&& y) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename U, typename = void>
+ struct plus_impl : plus_impl<T, U, when<true>> { };
+
+ struct plus_t {
+ template <typename X, typename Y>
+ constexpr decltype(auto) operator()(X&& x, Y&& y) const;
+ };
+
+ constexpr plus_t plus{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_PLUS_HPP
diff --git a/boost/hana/fwd/power.hpp b/boost/hana/fwd/power.hpp
new file mode 100644
index 0000000000..77ae209a90
--- /dev/null
+++ b/boost/hana/fwd/power.hpp
@@ -0,0 +1,56 @@
+/*!
+@file
+Forward declares `boost::hana::power`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_POWER_HPP
+#define BOOST_HANA_FWD_POWER_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Elevate a ring element to its `n`th power.
+ //! @ingroup group-Ring
+ //!
+ //! Specifically, `power(x, n)`, is equivalent to multiplying `x` with
+ //! itself `n` times using the Ring's multiplication. If the power is
+ //! equal to `zero`, the Ring's identity (`one`) is returned.
+ //!
+ //! @param x
+ //! A `Ring` element that is elevated to its `n`th power.
+ //!
+ //! @param n
+ //! A non-negative `IntegralConstant` representing the power to which `x`
+ //! is elevated.
+ //!
+ //!
+ //! @note
+ //! Only the tag of `x` is used for tag-dispatching.
+ //!
+ //! Example
+ //! -------
+ //! @include example/power.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto power = [](auto&& x, auto const& n) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename R, typename = void>
+ struct power_impl : power_impl<R, when<true>> { };
+
+ struct power_t {
+ template <typename X, typename N>
+ constexpr decltype(auto) operator()(X&& x, N const& n) const;
+ };
+
+ constexpr power_t power{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_POWER_HPP
diff --git a/boost/hana/fwd/prefix.hpp b/boost/hana/fwd/prefix.hpp
new file mode 100644
index 0000000000..515739f077
--- /dev/null
+++ b/boost/hana/fwd/prefix.hpp
@@ -0,0 +1,72 @@
+/*!
+@file
+Forward declares `boost::hana::prefix`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_PREFIX_HPP
+#define BOOST_HANA_FWD_PREFIX_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Inserts a value before each element of a monadic structure.
+ //! @ingroup group-MonadPlus
+ //!
+ //! Given a monadic structure `xs` and a value `z` called the prefix,
+ //! `prefix` returns a new monadic structure. `prefix` satisfies
+ //! @code
+ //! prefix(xs, z) == flatten(transform(xs, [](auto x) {
+ //! return concat(lift<M>(z), lift<M>(x));
+ //! }))
+ //! @endcode
+ //!
+ //! For sequences, this simply corresponds to inserting the prefix before
+ //! each element of the sequence. For example, given a sequence
+ //! `[x1, ..., xn]`, `prefix` will return
+ //! @code
+ //! [z, x1, z, x2, ..., z, xn]
+ //! @endcode
+ //! As explained above, this can be generalized to other MonadPlus models,
+ //! with various levels of interest.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a MonadPlus `M`, the signature is
+ //! @f$ \mathrm{prefix} : M(T) \times T \to M(T) @f$.
+ //!
+ //! @param xs
+ //! A monadic structure.
+ //!
+ //! @param pref
+ //! A value (the prefix) to insert before each element of a monadic
+ //! structure.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/prefix.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto prefix = [](auto&& xs, auto&& pref) {
+ return tag-dispatched;
+ };
+#else
+ template <typename M, typename = void>
+ struct prefix_impl : prefix_impl<M, when<true>> { };
+
+ struct prefix_t {
+ template <typename Xs, typename Pref>
+ constexpr auto operator()(Xs&& xs, Pref&& pref) const;
+ };
+
+ constexpr prefix_t prefix{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_PREFIX_HPP
diff --git a/boost/hana/fwd/prepend.hpp b/boost/hana/fwd/prepend.hpp
new file mode 100644
index 0000000000..445dae921d
--- /dev/null
+++ b/boost/hana/fwd/prepend.hpp
@@ -0,0 +1,73 @@
+/*!
+@file
+Forward declares `boost::hana::prepend`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_PREPEND_HPP
+#define BOOST_HANA_FWD_PREPEND_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Prepend an element to a monadic structure.
+ //! @ingroup group-MonadPlus
+ //!
+ //! Given a monadic structure `xs` and an element `x`, `prepend` returns
+ //! a new monadic structure which is the result of lifting `x` into the
+ //! monadic structure and then combining that (to the left) with `xs`.
+ //! In other words,
+ //! @code
+ //! prepend(xs, x) == concat(lift<Xs>(x), xs)
+ //! @endcode
+ //!
+ //! For sequences, this has the intuitive behavior of simply prepending
+ //! an element to the beginning of the sequence, hence the name.
+ //!
+ //! > #### Rationale for not calling this `push_front`
+ //! > While `push_front` is the de-facto name used in the standard library,
+ //! > it also strongly suggests mutation of the underlying sequence, which
+ //! > is not the case here. The author also finds that `push_front`
+ //! > suggests too strongly the sole interpretation of putting an
+ //! > element to the front of a sequence, whereas `prepend` is slightly
+ //! > more nuanced and bears its name better for e.g. `hana::optional`.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a MonadPlus `M`, the signature is
+ //! @f$ \mathtt{prepend} : M(T) \times T \to M(T) @f$.
+ //!
+ //! @param xs
+ //! A monadic structure that will be combined to the right of the element.
+ //!
+ //! @param x
+ //! An element to combine to the left of the monadic structure.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/prepend.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto prepend = [](auto&& xs, auto&& x) {
+ return tag-dispatched;
+ };
+#else
+ template <typename M, typename = void>
+ struct prepend_impl : prepend_impl<M, when<true>> { };
+
+ struct prepend_t {
+ template <typename Xs, typename X>
+ constexpr auto operator()(Xs&& xs, X&& x) const;
+ };
+
+ constexpr prepend_t prepend{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_PREPEND_HPP
diff --git a/boost/hana/fwd/product.hpp b/boost/hana/fwd/product.hpp
new file mode 100644
index 0000000000..3549e5b2a2
--- /dev/null
+++ b/boost/hana/fwd/product.hpp
@@ -0,0 +1,78 @@
+/*!
+@file
+Forward declares `boost::hana::product`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_PRODUCT_HPP
+#define BOOST_HANA_FWD_PRODUCT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/fwd/integral_constant.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Compute the product of the numbers of a structure.
+ //! @ingroup group-Foldable
+ //!
+ //! More generally, `product` will take any foldable structure containing
+ //! objects forming a Ring and reduce them using the Ring's binary
+ //! operation. The initial state for folding is the identity of the
+ //! Ring's operation. It is sometimes necessary to specify the Ring to
+ //! use; this is possible by using `product<R>`. If no Ring is specified,
+ //! the structure will use the Ring formed by the elements it contains
+ //! (if it knows it), or `integral_constant_tag<int>` otherwise.
+ //! Hence,
+ //! @code
+ //! product<R>(xs) = fold_left(xs, one<R or inferred Ring>(), mult)
+ //! product<> = product<integral_constant_tag<int>>
+ //! @endcode
+ //!
+ //! For numbers, this will just compute the product of the numbers in the
+ //! `xs` structure.
+ //!
+ //! @note
+ //! The elements of the structure are not actually required to be in the
+ //! same Ring, but it must be possible to perform `mult` on any two
+ //! adjacent elements of the structure, which requires each pair of
+ //! adjacent element to at least have a common Ring embedding. The
+ //! meaning of "adjacent" as used here is that two elements of the
+ //! structure `x` and `y` are adjacent if and only if they are adjacent
+ //! in the linearization of that structure, as documented by the Iterable
+ //! concept.
+ //!
+ //! @note
+ //! See the documentation for `sum` to understand why the Ring must
+ //! sometimes be specified explicitly.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/product.cpp
+ //!
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.product.compile.json">
+ //! </div>
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto product = see documentation;
+#else
+ template <typename T, typename = void>
+ struct product_impl : product_impl<T, when<true>> { };
+
+ template <typename R>
+ struct product_t;
+
+ template <typename R = integral_constant_tag<int>>
+ constexpr product_t<R> product{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_PRODUCT_HPP
diff --git a/boost/hana/fwd/range.hpp b/boost/hana/fwd/range.hpp
new file mode 100644
index 0000000000..4ddb5a96b8
--- /dev/null
+++ b/boost/hana/fwd/range.hpp
@@ -0,0 +1,149 @@
+/*!
+@file
+Forward declares `boost::hana::range`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_RANGE_HPP
+#define BOOST_HANA_FWD_RANGE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+#include <boost/hana/fwd/integral_constant.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ //! @ingroup group-datatypes
+ //! Compile-time half-open interval of `hana::integral_constant`s.
+ //!
+ //! A `range` represents a half-open interval of the form `[from, to)`
+ //! containing `hana::integral_constant`s of a given type. The `[from, to)`
+ //! notation represents the values starting at `from` (inclusively) up
+ //! to but excluding `from`. In other words, it is a bit like the list
+ //! `from, from+1, ..., to-1`.
+ //!
+ //! In particular, note that the bounds of the range can be any
+ //! `hana::integral_constant`s (negative numbers are allowed) and the
+ //! range does not have to start at zero. The only requirement is that
+ //! `from <= to`.
+ //!
+ //! @note
+ //! The representation of `hana::range` is implementation defined. In
+ //! particular, one should not take for granted the number and types
+ //! of template parameters. The proper way to create a `hana::range`
+ //! is to use `hana::range_c` or `hana::make_range`.
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! 1. `Comparable`\n
+ //! Two ranges are equal if and only if they are both empty or they both
+ //! span the same interval.
+ //! @include example/range/comparable.cpp
+ //!
+ //! 2. `Foldable`\n
+ //! Folding a `range` is equivalent to folding a list of the
+ //! `integral_constant`s in the interval it spans.
+ //! @include example/range/foldable.cpp
+ //!
+ //! 3. `Iterable`\n
+ //! Iterating over a `range` is equivalent to iterating over a list of
+ //! the values it spans. In other words, iterating over the range
+ //! `[from, to)` is equivalent to iterating over a list containing
+ //! `from, from+1, from+2, ..., to-1`. Also note that `operator[]` can
+ //! be used in place of the `at` function.
+ //! @include example/range/iterable.cpp
+ //!
+ //! 4. `Searchable`\n
+ //! Searching a `range` is equivalent to searching a list of the values
+ //! in the range `[from, to)`, but it is much more compile-time efficient.
+ //! @include example/range/searchable.cpp
+ template <typename T, T from, T to>
+ struct range {
+ //! Equivalent to `hana::equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator==(X&& x, Y&& y);
+
+ //! Equivalent to `hana::not_equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator!=(X&& x, Y&& y);
+
+ //! Equivalent to `hana::at`
+ template <typename N>
+ constexpr decltype(auto) operator[](N&& n);
+ };
+#else
+ template <typename T, T from, T to>
+ struct range;
+#endif
+
+ //! Tag representing a `hana::range`.
+ //! @relates hana::range
+ struct range_tag { };
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ //! Create a `hana::range` representing a half-open interval of
+ //! `integral_constant`s.
+ //! @relates hana::range
+ //!
+ //! Given two `IntegralConstant`s `from` and `to`, `make<range_tag>`
+ //! returns a `hana::range` representing the half-open interval of
+ //! `integral_constant`s `[from, to)`. `from` and `to` must form a
+ //! valid interval, which means that `from <= to` must be true. Otherwise,
+ //! a compilation error is triggered. Also note that if `from` and `to`
+ //! are `IntegralConstant`s with different underlying integral types,
+ //! the created range contains `integral_constant`s whose underlying
+ //! type is their common type.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/range/make.cpp
+ template <>
+ constexpr auto make<range_tag> = [](auto const& from, auto const& to) {
+ return range<implementation_defined>{implementation_defined};
+ };
+#endif
+
+ //! Alias to `make<range_tag>`; provided for convenience.
+ //! @relates hana::range
+ constexpr auto make_range = make<range_tag>;
+
+ //! Shorthand to create a `hana::range` with the given bounds.
+ //! @relates hana::range
+ //!
+ //! This shorthand is provided for convenience only and it is equivalent
+ //! to `make_range`. Specifically, `range_c<T, from, to>` is such that
+ //! @code
+ //! range_c<T, from, to> == make_range(integral_c<T, from>, integral_c<T, to>)
+ //! @endcode
+ //!
+ //!
+ //! @tparam T
+ //! The underlying integral type of the `integral_constant`s in the
+ //! created range.
+ //!
+ //! @tparam from
+ //! The inclusive lower bound of the created range.
+ //!
+ //! @tparam to
+ //! The exclusive upper bound of the created range.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/range/range_c.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename T, T from, T to>
+ constexpr auto range_c = make_range(integral_c<T, from>, integral_c<T, to>);
+#else
+ template <typename T, T from, T to>
+ constexpr range<T, from, to> range_c{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_RANGE_HPP
diff --git a/boost/hana/fwd/remove.hpp b/boost/hana/fwd/remove.hpp
new file mode 100644
index 0000000000..7f9191d4ab
--- /dev/null
+++ b/boost/hana/fwd/remove.hpp
@@ -0,0 +1,70 @@
+/*!
+@file
+Forward declares `boost::hana::remove`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_REMOVE_HPP
+#define BOOST_HANA_FWD_REMOVE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Remove all the elements of a monadic structure that are equal to some
+ //! value.
+ //! @ingroup group-MonadPlus
+ //!
+ //! Given a monadic structure `xs` and a `value`, `remove` returns a new
+ //! monadic structure equal to `xs` without all its elements that are
+ //! equal to the given `value`. `remove` is equivalent to `remove_if`
+ //! with the `equal.to(value)` predicate, i.e.
+ //! @code
+ //! remove(xs, value) == remove_if(xs, equal.to(value))
+ //! @endcode
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a MonadPlus `M` and a value of type `T`, the signature is
+ //! \f$
+ //! \mathrm{remove} : M(T) \times T \to M(T)
+ //! \f$
+ //!
+ //! @param xs
+ //! A monadic structure to remove some elements from.
+ //!
+ //! @param value
+ //! A value that is compared to every element `x` of the structure.
+ //! Elements of the structure that are equal to that value are removed
+ //! from the structure. This requires every element to be Comparable
+ //! with `value`. Furthermore, in the current version of the library,
+ //! comparing `value` with any element of the structure must yield a
+ //! compile-time Logical.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/remove.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto remove = [](auto&& xs, auto&& value) {
+ return tag-dispatched;
+ };
+#else
+ template <typename M, typename = void>
+ struct remove_impl : remove_impl<M, when<true>> { };
+
+ struct remove_t {
+ template <typename Xs, typename Value>
+ constexpr auto operator()(Xs&& xs, Value&& value) const;
+ };
+
+ constexpr remove_t remove{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_REMOVE_HPP
diff --git a/boost/hana/fwd/remove_at.hpp b/boost/hana/fwd/remove_at.hpp
new file mode 100644
index 0000000000..6e25e4db45
--- /dev/null
+++ b/boost/hana/fwd/remove_at.hpp
@@ -0,0 +1,82 @@
+/*!
+@file
+Forward declares `boost::hana::remove_at` and `boost::hana::remove_at_c`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_REMOVE_AT_HPP
+#define BOOST_HANA_FWD_REMOVE_AT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+#include <cstddef>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Remove the element at a given index from a sequence.
+ //! @ingroup group-Sequence
+ //!
+ //! `remove_at` returns a new sequence identical to the original, except
+ //! that the element at the given index is removed. Specifically,
+ //! `remove_at([x0, ..., xn-1, xn, xn+1, ..., xm], n)` is a new
+ //! sequence equivalent to `[x0, ..., xn-1, xn+1, ..., xm]`.
+ //!
+ //! @note
+ //! The behavior is undefined if the index is out of the bounds of the
+ //! sequence.
+ //!
+ //!
+ //! @param xs
+ //! A sequence from which an element is to be removed.
+ //!
+ //! @param n
+ //! An non-negative `IntegralConstant` representing the index of the
+ //! element to be removed from the sequence. The behavior is undefined
+ //! if that index is not in the bounds of the sequence.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/remove_at.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto remove_at = [](auto&& xs, auto const& n) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct remove_at_impl : remove_at_impl<S, when<true>> { };
+
+ struct remove_at_t {
+ template <typename Xs, typename N>
+ constexpr auto operator()(Xs&& xs, N const& n) const;
+ };
+
+ constexpr remove_at_t remove_at{};
+#endif
+
+ //! Equivalent to `remove_at`; provided for convenience.
+ //! @ingroup group-Sequence
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/remove_at_c.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <std::size_t n>
+ constexpr auto remove_at_c = [](auto&& xs) {
+ return hana::remove_at(forwarded(xs), hana::size_c<n>);
+ };
+#else
+ template <std::size_t n>
+ struct remove_at_c_t;
+
+ template <std::size_t n>
+ constexpr remove_at_c_t<n> remove_at_c{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_REMOVE_AT_HPP
diff --git a/boost/hana/fwd/remove_if.hpp b/boost/hana/fwd/remove_if.hpp
new file mode 100644
index 0000000000..4d6a9722cc
--- /dev/null
+++ b/boost/hana/fwd/remove_if.hpp
@@ -0,0 +1,69 @@
+/*!
+@file
+Forward declares `boost::hana::remove_if`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_REMOVE_IF_HPP
+#define BOOST_HANA_FWD_REMOVE_IF_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Remove all the elements of a monadic structure that satisfy some
+ //! predicate.
+ //! @ingroup group-MonadPlus
+ //!
+ //! Given a monadic structure `xs` and a unary predicate, `remove_if`
+ //! returns a new monadic structure equal to `xs` without all its elements
+ //! that satisfy the predicate. This is equivalent to `filter` with a
+ //! negated predicate, i.e.
+ //! @code
+ //! remove_if(xs, predicate) == filter(xs, negated predicated)
+ //! @endcode
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a MonadPlus `M` and a predicate of type \f$ T \to Bool \f$ for
+ //! some compile-time Logical `Bool`, the signature is
+ //! \f$
+ //! \mathrm{remove\_if} : M(T) \times (T \to Bool) \to M(T)
+ //! \f$
+ //!
+ //! @param xs
+ //! A monadic structure to remove some elements from.
+ //!
+ //! @param predicate
+ //! A unary predicate called as `predicate(x)`, where `x` is an element
+ //! of the structure, and returning whether `x` should be removed from
+ //! the structure. In the current version of the library, `predicate`
+ //! must return a compile-time Logical.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/remove_if.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto remove_if = [](auto&& xs, auto&& predicate) {
+ return tag-dispatched;
+ };
+#else
+ template <typename M, typename = void>
+ struct remove_if_impl : remove_if_impl<M, when<true>> { };
+
+ struct remove_if_t {
+ template <typename Xs, typename Pred>
+ constexpr auto operator()(Xs&& xs, Pred&& pred) const;
+ };
+
+ constexpr remove_if_t remove_if{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_REMOVE_IF_HPP
diff --git a/boost/hana/fwd/remove_range.hpp b/boost/hana/fwd/remove_range.hpp
new file mode 100644
index 0000000000..5274a0e579
--- /dev/null
+++ b/boost/hana/fwd/remove_range.hpp
@@ -0,0 +1,85 @@
+/*!
+@file
+Forward declares `boost::hana::remove_range` and `boost::hana::remove_range_c`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_REMOVE_RANGE_HPP
+#define BOOST_HANA_FWD_REMOVE_RANGE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+#include <cstddef>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Remove the elements inside a given range of indices from a sequence.
+ //! @ingroup group-Sequence
+ //!
+ //! `remove_range` returns a new sequence identical to the original,
+ //! except that elements at indices in the provided range are removed.
+ //! Specifically, `remove_range([x0, ..., xn], from, to)` is a new
+ //! sequence equivalent to `[x0, ..., x_from-1, x_to, ..., xn]`.
+ //!
+ //!
+ //! @note
+ //! The behavior is undefined if the range contains any index out of the
+ //! bounds of the sequence.
+ //!
+ //!
+ //! @param xs
+ //! A sequence from which elements are removed.
+ //!
+ //! @param [from, to)
+ //! An half-open interval of `IntegralConstant`s representing the indices
+ //! of the elements to be removed from the sequence. The `IntegralConstant`s
+ //! in the half-open interval must be non-negative and in the bounds of
+ //! the sequence. The half-open interval must also be valid, meaning that
+ //! `from <= to`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/remove_range.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto remove_range = [](auto&& xs, auto const& from, auto const& to) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct remove_range_impl : remove_range_impl<S, when<true>> { };
+
+ struct remove_range_t {
+ template <typename Xs, typename From, typename To>
+ constexpr auto operator()(Xs&& xs, From const& from, To const& to) const;
+ };
+
+ constexpr remove_range_t remove_range{};
+#endif
+
+ //! Equivalent to `remove_range`; provided for convenience.
+ //! @ingroup group-Sequence
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/remove_range_c.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <std::size_t from, std::size_t to>
+ constexpr auto remove_range_c = [](auto&& xs) {
+ return hana::remove_range(forwarded(xs), hana::size_c<from>, hana::size_c<to>);
+ };
+#else
+ template <std::size_t from, std::size_t to>
+ struct remove_range_c_t;
+
+ template <std::size_t from, std::size_t to>
+ constexpr remove_range_c_t<from, to> remove_range_c{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_REMOVE_RANGE_HPP
diff --git a/boost/hana/fwd/repeat.hpp b/boost/hana/fwd/repeat.hpp
new file mode 100644
index 0000000000..dbb39eea0b
--- /dev/null
+++ b/boost/hana/fwd/repeat.hpp
@@ -0,0 +1,58 @@
+/*!
+@file
+Forward declares `boost::hana::repeat`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_REPEAT_HPP
+#define BOOST_HANA_FWD_REPEAT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Invokes a nullary function `n` times.
+ //! @ingroup group-IntegralConstant
+ //!
+ //! Given an `IntegralConstant` `n` and a nullary function `f`,
+ //! `repeat(n, f)` will call `f` `n` times. In particular, any
+ //! decent compiler should expand `repeat(n, f)` to
+ //! @code
+ //! f(); f(); ... f(); // n times total
+ //! @endcode
+ //!
+ //!
+ //! @param n
+ //! An `IntegralConstant` holding a non-negative value representing
+ //! the number of times `f` should be repeatedly invoked.
+ //!
+ //! @param f
+ //! A function to repeatedly invoke `n` times. `f` is allowed to have
+ //! side effects.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/repeat.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto repeat = [](auto const& n, auto&& f) -> void {
+ f(); f(); ... f(); // n times total
+ };
+#else
+ template <typename N, typename = void>
+ struct repeat_impl : repeat_impl<N, when<true>> { };
+
+ struct repeat_t {
+ template <typename N, typename F>
+ constexpr void operator()(N const& n, F&& f) const;
+ };
+
+ constexpr repeat_t repeat{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_REPEAT_HPP
diff --git a/boost/hana/fwd/replace.hpp b/boost/hana/fwd/replace.hpp
new file mode 100644
index 0000000000..81eec5b1ae
--- /dev/null
+++ b/boost/hana/fwd/replace.hpp
@@ -0,0 +1,64 @@
+/*!
+@file
+Forward declares `boost::hana::replace`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_REPLACE_HPP
+#define BOOST_HANA_FWD_REPLACE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Replace all the elements of a structure that compare equal
+ //! to some `value` with some new fixed value.
+ //! @ingroup group-Functor
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given `F` a Functor and `U` a type that can be compared with `T`,
+ //! the signature is
+ //! \f$
+ //! \mathtt{replace} : F(T) \times U \times T \to F(T)
+ //! \f$
+ //!
+ //! @param xs
+ //! The structure to replace elements of.
+ //!
+ //! @param oldval
+ //! An object compared with each element of the structure. Elements
+ //! of the structure that compare equal to `oldval` are replaced
+ //! by `newval` in the new structure.
+ //!
+ //! @param newval
+ //! A value by which every element `x` of the structure that compares
+ //! equal to `oldval` is replaced.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/replace.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto replace = [](auto&& xs, auto&& oldval, auto&& newval) {
+ return tag-dispatched;
+ };
+#else
+ template <typename Xs, typename = void>
+ struct replace_impl : replace_impl<Xs, when<true>> { };
+
+ struct replace_t {
+ template <typename Xs, typename OldVal, typename NewVal>
+ constexpr auto operator()(Xs&& xs, OldVal&& oldval, NewVal&& newval) const;
+ };
+
+ constexpr replace_t replace{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_REPLACE_HPP
diff --git a/boost/hana/fwd/replace_if.hpp b/boost/hana/fwd/replace_if.hpp
new file mode 100644
index 0000000000..36df3eb40a
--- /dev/null
+++ b/boost/hana/fwd/replace_if.hpp
@@ -0,0 +1,63 @@
+/*!
+@file
+Forward declares `boost::hana::replace_if`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_REPLACE_IF_HPP
+#define BOOST_HANA_FWD_REPLACE_IF_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Replace all the elements of a structure satisfying a `predicate`
+ //! with a fixed value.
+ //! @ingroup group-Functor
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given `F` a Functor and `Bool` a Logical, the signature is
+ //! \f$
+ //! \mathtt{replace_if} : F(T) \times (T \to Bool) \times T \to F(T)
+ //! \f$
+ //!
+ //! @param xs
+ //! The structure to replace elements of.
+ //!
+ //! @param predicate
+ //! A function called as `predicate(x)` for element(s) `x` of the
+ //! structure and returning a `Logical` representing whether `x`
+ //! should be replaced by `value`.
+ //!
+ //! @param value
+ //! A value by which every element `x` of the structure for which
+ //! `predicate` returns a true-valued `Logical` is replaced.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/replace_if.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto replace_if = [](auto&& xs, auto&& predicate, auto&& value) {
+ return tag-dispatched;
+ };
+#else
+ template <typename Xs, typename = void>
+ struct replace_if_impl : replace_if_impl<Xs, when<true>> { };
+
+ struct replace_if_t {
+ template <typename Xs, typename Pred, typename Value>
+ constexpr auto operator()(Xs&& xs, Pred&& pred, Value&& value) const;
+ };
+
+ constexpr replace_if_t replace_if{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_REPLACE_IF_HPP
diff --git a/boost/hana/fwd/replicate.hpp b/boost/hana/fwd/replicate.hpp
new file mode 100644
index 0000000000..0580d90601
--- /dev/null
+++ b/boost/hana/fwd/replicate.hpp
@@ -0,0 +1,75 @@
+/*!
+@file
+Forward declares `boost::hana::replicate`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_REPLICATE_HPP
+#define BOOST_HANA_FWD_REPLICATE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Create a monadic structure by combining a lifted value with itself
+ //! `n` times.
+ //! @ingroup group-MonadPlus
+ //!
+ //! Given a value `x`, a non-negative `IntegralConstant` `n` and the tag
+ //! of a monadic structure `M`, `replicate` creates a new monadic structure
+ //! which is the result of combining `x` with itself `n` times inside the
+ //! monadic structure. In other words, `replicate` simply `lift`s `x` into
+ //! the monadic structure, and then combines that with itself `n` times:
+ //! @code
+ //! replicate<M>(x, n) == cycle(lift<M>(x), n)
+ //! @endcode
+ //!
+ //! If `n` is zero, then the identity of the `concat` operation is returned.
+ //! In the case of sequences, this corresponds to creating a new sequence
+ //! holding `n` copies of `x`.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given an `IntegralConstant` `C` and MonadPlus `M`, the signature is
+ //! @f$ \mathtt{replicate}_M : T \times C \to M(T) @f$.
+ //!
+ //! @tparam M
+ //! The tag of the returned monadic structure. It must be a
+ //! model of the MonadPlus concept.
+ //!
+ //! @param x
+ //! The value to lift into a monadic structure and then combine with
+ //! itself.
+ //!
+ //! @param n
+ //! A non-negative `IntegralConstant` representing the number of times to
+ //! combine `lift<M>(x)` with itself. If `n == 0`, `replicate` returns
+ //! `empty<M>()`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/replicate.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename M>
+ constexpr auto replicate = [](auto&& x, auto const& n) {
+ return tag-dispatched;
+ };
+#else
+ template <typename M, typename = void>
+ struct replicate_impl : replicate_impl<M, when<true>> { };
+
+ template <typename M>
+ struct replicate_t;
+
+ template <typename M>
+ constexpr replicate_t<M> replicate{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_REPLICATE_HPP
diff --git a/boost/hana/fwd/reverse.hpp b/boost/hana/fwd/reverse.hpp
new file mode 100644
index 0000000000..0c5bb5c7f9
--- /dev/null
+++ b/boost/hana/fwd/reverse.hpp
@@ -0,0 +1,49 @@
+/*!
+@file
+Forward declares `boost::hana::reverse`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_REVERSE_HPP
+#define BOOST_HANA_FWD_REVERSE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Reverse a sequence.
+ //! @ingroup group-Sequence
+ //!
+ //! Specifically, `reverse(xs)` is a new sequence containing the same
+ //! elements as `xs`, except in reverse order.
+ //!
+ //!
+ //! @param xs
+ //! The sequence to reverse.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/reverse.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto reverse = [](auto&& xs) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct reverse_impl : reverse_impl<S, when<true>> { };
+
+ struct reverse_t {
+ template <typename Xs>
+ constexpr auto operator()(Xs&& xs) const;
+ };
+
+ constexpr reverse_t reverse{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_REVERSE_HPP
diff --git a/boost/hana/fwd/reverse_fold.hpp b/boost/hana/fwd/reverse_fold.hpp
new file mode 100644
index 0000000000..c5a770b576
--- /dev/null
+++ b/boost/hana/fwd/reverse_fold.hpp
@@ -0,0 +1,84 @@
+/*!
+@file
+Forward declares `boost::hana::reverse_fold`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_REVERSE_FOLD_HPP
+#define BOOST_HANA_FWD_REVERSE_FOLD_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Equivalent to `reverse_fold` in Boost.Fusion and Boost.MPL.
+ //! @ingroup group-Foldable
+ //!
+ //! This method has the same semantics as `reverse_fold` in Boost.Fusion
+ //! and Boost.MPL, with the extension that an initial state is not
+ //! required. This method is equivalent to `fold_right`, except that
+ //! the accumulating function must take its arguments in reverse order,
+ //! to match the order used in Fusion. In other words,
+ //! @code
+ //! reverse_fold(sequence, state, f) == fold_right(sequence, state, flip(f))
+ //! reverse_fold(sequence, f) == fold_right(sequence, flip(f))
+ //! @endcode
+ //!
+ //! @note
+ //! This method is a convenience alias to `fold_right`. As an alias,
+ //! `reverse_fold` is not tag-dispatched on its own and `fold_right`
+ //! should be customized instead.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a `Foldable` `F` and an optional initial state of tag `S`,
+ //! the signatures for `reverse_fold` are
+ //! \f[
+ //! \mathtt{reverse\_fold} : F(T) \times S \times (S \times T \to S) \to S
+ //! \f]
+ //!
+ //! for the variant with an initial state, and
+ //! \f[
+ //! \mathtt{reverse\_fold} : F(T) \times (T \times T \to T) \to T
+ //! \f]
+ //!
+ //! for the variant without an initial state.
+ //!
+ //! @param xs
+ //! The structure to fold.
+ //!
+ //! @param state
+ //! The initial value used for folding.
+ //!
+ //! @param f
+ //! A binary function called as `f(state, x)`, where `state` is the
+ //! result accumulated so far and `x` is an element in the structure.
+ //! For reverse folds without an initial state, the function is called as
+ //! `f(x1, x2)`, where `x1` and `x2` are elements of the structure.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/reverse_fold.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto reverse_fold = [](auto&& xs[, auto&& state], auto&& f) -> decltype(auto) {
+ return fold_right(forwarded(xs), forwarded(state), flip(forwarded(f)));
+ };
+#else
+ struct reverse_fold_t {
+ template <typename Xs, typename S, typename F>
+ constexpr decltype(auto) operator()(Xs&& xs, S&& s, F&& f) const;
+
+ template <typename Xs, typename F>
+ constexpr decltype(auto) operator()(Xs&& xs, F&& f) const;
+ };
+
+ constexpr reverse_fold_t reverse_fold{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_REVERSE_FOLD_HPP
diff --git a/boost/hana/fwd/scan_left.hpp b/boost/hana/fwd/scan_left.hpp
new file mode 100644
index 0000000000..4ec8987a92
--- /dev/null
+++ b/boost/hana/fwd/scan_left.hpp
@@ -0,0 +1,105 @@
+/*!
+@file
+Forward declares `boost::hana::scan_left`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_SCAN_LEFT_HPP
+#define BOOST_HANA_FWD_SCAN_LEFT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Fold a Sequence to the left and return a list containing the
+ //! successive reduction states.
+ //! @ingroup group-Sequence
+ //!
+ //! Like `fold_left`, `scan_left` reduces a sequence to a single value
+ //! using a binary operation. However, unlike `fold_left`, it builds up
+ //! a sequence of the intermediary results computed along the way and
+ //! returns that instead of only the final reduction state. Like
+ //! `fold_left`, `scan_left` can be used with or without an initial
+ //! reduction state.
+ //!
+ //! When the sequence is empty, two things may arise. If an initial state
+ //! was provided, a singleton list containing that state is returned.
+ //! Otherwise, if no initial state was provided, an empty list is
+ //! returned. In particular, unlike for `fold_left`, using `scan_left`
+ //! on an empty sequence without an initial state is not an error.
+ //!
+ //! More specifically, `scan_left([x1, ..., xn], state, f)` is a sequence
+ //! whose `i`th element is equivalent to `fold_left([x1, ..., xi], state, f)`.
+ //! The no-state variant is handled in an analogous way. For illustration,
+ //! consider this left fold on a short sequence:
+ //! @code
+ //! fold_left([x1, x2, x3], state, f) == f(f(f(state, x1), x2), x3)
+ //! @endcode
+ //!
+ //! The analogous sequence generated with `scan_left` will be
+ //! @code
+ //! scan_left([x1, x2, x3], state, f) == [
+ //! state,
+ //! f(state, x1),
+ //! f(f(state, x1), x2),
+ //! f(f(f(state, x1), x2), x3)
+ //! ]
+ //! @endcode
+ //!
+ //! Similarly, consider this left fold (without an initial state) on
+ //! a short sequence:
+ //! @code
+ //! fold_left([x1, x2, x3, x4], f) == f(f(f(x1, x2), x3), x4)
+ //! @endcode
+ //!
+ //! The analogous sequence generated with `scan_left` will be
+ //! @code
+ //! scan_left([x1, x2, x3, x4], f) == [
+ //! x1,
+ //! f(x1, x2),
+ //! f(f(x1, x2), x3),
+ //! f(f(f(x1, x2), x3), x4)
+ //! ]
+ //! @endcode
+ //!
+ //! @param xs
+ //! The sequence to scan from the left.
+ //!
+ //! @param state
+ //! The (optional) initial reduction state.
+ //!
+ //! @param f
+ //! A binary function called as `f(state, x)`, where `state` is the
+ //! result accumulated so far and `x` is an element in the sequence.
+ //! If no initial state is provided, `f` is called as `f(x1, x2)`,
+ //! where `x1` and `x2` are both elements of the sequence.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/scan_left.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto scan_left = [](auto&& xs[, auto&& state], auto const& f) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct scan_left_impl : scan_left_impl<S, when<true>> { };
+
+ struct scan_left_t {
+ template <typename Xs, typename State, typename F>
+ constexpr auto operator()(Xs&& xs, State&& state, F const& f) const;
+
+ template <typename Xs, typename F>
+ constexpr auto operator()(Xs&& xs, F const& f) const;
+ };
+
+ constexpr scan_left_t scan_left{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_SCAN_LEFT_HPP
diff --git a/boost/hana/fwd/scan_right.hpp b/boost/hana/fwd/scan_right.hpp
new file mode 100644
index 0000000000..f23dfd1104
--- /dev/null
+++ b/boost/hana/fwd/scan_right.hpp
@@ -0,0 +1,105 @@
+/*!
+@file
+Forward declares `boost::hana::scan_right`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_SCAN_RIGHT_HPP
+#define BOOST_HANA_FWD_SCAN_RIGHT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Fold a Sequence to the right and return a list containing the
+ //! successive reduction states.
+ //! @ingroup group-Sequence
+ //!
+ //! Like `fold_right`, `scan_right` reduces a sequence to a single value
+ //! using a binary operation. However, unlike `fold_right`, it builds up
+ //! a sequence of the intermediary results computed along the way and
+ //! returns that instead of only the final reduction state. Like
+ //! `fold_right`, `scan_right` can be used with or without an initial
+ //! reduction state.
+ //!
+ //! When the sequence is empty, two things may arise. If an initial state
+ //! was provided, a singleton list containing that state is returned.
+ //! Otherwise, if no initial state was provided, an empty list is
+ //! returned. In particular, unlike for `fold_right`, using `scan_right`
+ //! on an empty sequence without an initial state is not an error.
+ //!
+ //! More specifically, `scan_right([x1, ..., xn], state, f)` is a sequence
+ //! whose `i`th element is equivalent to `fold_right([x1, ..., xi], state, f)`.
+ //! The no-state variant is handled in an analogous way. For illustration,
+ //! consider this right fold on a short sequence:
+ //! @code
+ //! fold_right([x1, x2, x3], state, f) == f(x1, f(x2, f(x3, state)))
+ //! @endcode
+ //!
+ //! The analogous sequence generated with `scan_right` will be
+ //! @code
+ //! scan_right([x1, x2, x3], state, f) == [
+ //! f(x1, f(x2, f(x3, state))),
+ //! f(x2, f(x3, state)),
+ //! f(x3, state),
+ //! state
+ //! ]
+ //! @endcode
+ //!
+ //! Similarly, consider this right fold (without an initial state) on
+ //! a short sequence:
+ //! @code
+ //! fold_right([x1, x2, x3, x4], f) == f(x1, f(x2, f(x3, x4)))
+ //! @endcode
+ //!
+ //! The analogous sequence generated with `scan_right` will be
+ //! @code
+ //! scan_right([x1, x2, x3, x4], f) == [
+ //! f(x1, f(x2, f(x3, x4))),
+ //! f(x2, f(x3, x4)),
+ //! f(x3, x4),
+ //! x4
+ //! ]
+ //! @endcode
+ //!
+ //! @param xs
+ //! The sequence to scan from the right.
+ //!
+ //! @param state
+ //! The (optional) initial reduction state.
+ //!
+ //! @param f
+ //! A binary function called as `f(x, state)`, where `state` is the
+ //! result accumulated so far and `x` is an element in the sequence.
+ //! When no initial state is provided, `f` is called as `f(x1, x2)`,
+ //! where `x1` and `x2` are elements of the sequence.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/scan_right.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto scan_right = [](auto&& xs[, auto&& state], auto const& f) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct scan_right_impl : scan_right_impl<S, when<true>> { };
+
+ struct scan_right_t {
+ template <typename Xs, typename State, typename F>
+ constexpr auto operator()(Xs&& xs, State&& state, F const& f) const;
+
+ template <typename Xs, typename F>
+ constexpr auto operator()(Xs&& xs, F const& f) const;
+ };
+
+ constexpr scan_right_t scan_right{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_SCAN_RIGHT_HPP
diff --git a/boost/hana/fwd/second.hpp b/boost/hana/fwd/second.hpp
new file mode 100644
index 0000000000..edbbaa36fe
--- /dev/null
+++ b/boost/hana/fwd/second.hpp
@@ -0,0 +1,48 @@
+/*!
+@file
+Forward declares `boost::hana::second`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_SECOND_HPP
+#define BOOST_HANA_FWD_SECOND_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns the second element of a pair.
+ //! @ingroup group-Product
+ //!
+ //! Note that if the `Product` actually stores the elements it contains,
+ //! `hana::second` is required to return a lvalue reference, a lvalue
+ //! reference to const or a rvalue reference to the second element, where
+ //! the type of reference must match that of the pair passed to `second`.
+ //! If the `Product` does not store the elements it contains (i.e. it
+ //! generates them on demand), this requirement is dropped.
+ //!
+ //! Example
+ //! -------
+ //! @include example/second.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto second = [](auto&& product) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename P, typename = void>
+ struct second_impl : second_impl<P, when<true>> { };
+
+ struct second_t {
+ template <typename Pair>
+ constexpr decltype(auto) operator()(Pair&& pair) const;
+ };
+
+ constexpr second_t second{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_SECOND_HPP
diff --git a/boost/hana/fwd/set.hpp b/boost/hana/fwd/set.hpp
new file mode 100644
index 0000000000..5b96e9da06
--- /dev/null
+++ b/boost/hana/fwd/set.hpp
@@ -0,0 +1,194 @@
+/*!
+@file
+Forward declares `boost::hana::set`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_SET_HPP
+#define BOOST_HANA_FWD_SET_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/fwd/core/to.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+#include <boost/hana/fwd/erase_key.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-datatypes
+ //! Basic unordered container requiring unique, `Comparable` and
+ //! `Hashable` keys.
+ //!
+ //! A set is an unordered container that can hold heterogeneous keys.
+ //! A set requires (and ensures) that no duplicates are present when
+ //! inserting new keys.
+ //!
+ //! @note
+ //! The actual representation of a `hana::set` is implementation-defined.
+ //! In particular, one should not take for granted the order of the
+ //! template parameters and the presence of any additional constructors
+ //! or assignment operators than what is documented. The canonical way of
+ //! creating a `hana::set` is through `hana::make_set`.
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! 1. `Comparable`\n
+ //! Two sets are equal iff they contain the same elements, regardless of
+ //! the order.
+ //! @include example/set/comparable.cpp
+ //!
+ //! 2. Foldable\n
+ //! Folding a set is equivalent to folding the sequence of its values.
+ //! However, note that the values are not required to be in any specific
+ //! order, so using the folds provided here with an operation that is not
+ //! both commutative and associative will yield non-deterministic behavior.
+ //! @include example/set/foldable.cpp
+ //!
+ //! 3. Searchable\n
+ //! The elements in a set act as both its keys and its values. Since the
+ //! elements of a set are unique, searching for an element will return
+ //! either the only element which is equal to the searched value, or
+ //! `nothing`. Also note that `operator[]` can be used instead of the
+ //! `at_key` function.
+ //! @include example/set/searchable.cpp
+ //!
+ //!
+ //! Conversion from any `Foldable`
+ //! ------------------------------
+ //! Any `Foldable` structure can be converted into a `hana::set` with
+ //! `to<set_tag>`. The elements of the structure must all be compile-time
+ //! `Comparable`. If the structure contains duplicate elements, only
+ //! the first occurence will appear in the resulting set. More
+ //! specifically, conversion from a `Foldable` is equivalent to
+ //! @code
+ //! to<set_tag>(xs) == fold_left(xs, make_set(), insert)
+ //! @endcode
+ //!
+ //! __Example__
+ //! @include example/set/to.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename implementation_defined>
+ struct set {
+ //! Copy-construct a set from another set. This constructor only
+ //! exists when all the elements of the set are copy-constructible.
+ constexpr set(set const& other) = default;
+
+ //! Move-construct a set from another set. This constructor only
+ //! exists when all the elements of the set are move-constructible.
+ constexpr set(set&& other) = default;
+
+ //! Equivalent to `hana::equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator==(X&& x, Y&& y);
+
+ //! Equivalent to `hana::not_equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator!=(X&& x, Y&& y);
+
+ //! Equivalent to `hana::at_key`
+ template <typename Key>
+ constexpr decltype(auto) operator[](Key&& key);
+ };
+#else
+ template <typename ...Xs>
+ struct set;
+#endif
+
+ //! Tag representing the `hana::set` container.
+ //! @relates hana::set
+ struct set_tag { };
+
+ //! Function object for creating a `hana::set`.
+ //! @relates hana::set
+ //!
+ //! Given zero or more values `xs...`, `make<set_tag>` returns a `set`
+ //! containing those values. The values must all be compile-time
+ //! `Comparable`, and no duplicate values may be provided. To create
+ //! a `set` from a sequence with possible duplicates, use `to<set_tag>`
+ //! instead.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/set/make.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <>
+ constexpr auto make<set_tag> = [](auto&& ...xs) {
+ return set<implementation_defined>{forwarded(xs)...};
+ };
+#endif
+
+ //! Equivalent to `make<set_tag>`; provided for convenience.
+ //! @relates hana::set
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/set/make.cpp
+ constexpr auto make_set = make<set_tag>;
+
+ //! Insert an element in a `hana::set`.
+ //! @relates hana::set
+ //!
+ //! If the set already contains an element that compares equal, then
+ //! nothing is done and the set is returned as is.
+ //!
+ //!
+ //! @param set
+ //! The set in which to insert a value.
+ //!
+ //! @param element
+ //! The value to insert. It must be compile-time `Comparable`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/set/insert.cpp
+ //!
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.insert.compile.json">
+ //! </div>
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto insert = [](auto&& set, auto&& element) {
+ return tag-dispatched;
+ };
+#endif
+
+ //! Remove an element from a `hana::set`.
+ //! @relates hana::set
+ //!
+ //! Returns a new set containing all the elements of the original,
+ //! except the one comparing `equal` to the given element. If the set
+ //! does not contain such an element, a new set equal to the original
+ //! set is returned.
+ //!
+ //!
+ //! @param set
+ //! The set in which to remove a value.
+ //!
+ //! @param element
+ //! The value to remove. It must be compile-time `Comparable`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/set/erase_key.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto erase_key = [](auto&& set, auto&& element) {
+ return tag-dispatched;
+ };
+#endif
+
+ //! Equivalent to `to<set_tag>`; provided for convenience.
+ //! @relates hana::set
+ constexpr auto to_set = to<set_tag>;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_SET_HPP
diff --git a/boost/hana/fwd/size.hpp b/boost/hana/fwd/size.hpp
new file mode 100644
index 0000000000..b3c4e3ba96
--- /dev/null
+++ b/boost/hana/fwd/size.hpp
@@ -0,0 +1,33 @@
+/*!
+@file
+Forward declares `boost::hana::size`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_SIZE_HPP
+#define BOOST_HANA_FWD_SIZE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/fwd/length.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Equivalent to `length`; provided for consistency with the
+ //! standard library.
+ //! @ingroup group-Foldable
+ //!
+ //! This method is an alias to `length` provided for convenience and
+ //! consistency with the standard library. As an alias, `size` is not
+ //! tag-dispatched on its own and `length` should be customized instead.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/size.cpp
+ constexpr auto size = hana::length;
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_SIZE_HPP
diff --git a/boost/hana/fwd/slice.hpp b/boost/hana/fwd/slice.hpp
new file mode 100644
index 0000000000..82eae5b29a
--- /dev/null
+++ b/boost/hana/fwd/slice.hpp
@@ -0,0 +1,105 @@
+/*!
+@file
+Forward declares `boost::hana::slice` and `boost::hana::slice_c`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_SLICE_HPP
+#define BOOST_HANA_FWD_SLICE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+#include <cstddef>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Extract the elements of a `Sequence` at the given indices.
+ //! @ingroup group-Sequence
+ //!
+ //! Given an arbitrary sequence of `indices`, `slice` returns a new
+ //! sequence of the elements of the original sequence that appear at
+ //! those indices. In other words,
+ //! @code
+ //! slice([x1, ..., xn], [i1, ..., ik]) == [x_i1, ..., x_ik]
+ //! @endcode
+ //!
+ //! The indices do not have to be ordered or contiguous in any particular
+ //! way, but they must not be out of the bounds of the sequence. It is
+ //! also possible to specify the same index multiple times, in which case
+ //! the element at this index will be repeatedly included in the resulting
+ //! sequence.
+ //!
+ //!
+ //! @param xs
+ //! The sequence from which a subsequence is extracted.
+ //!
+ //! @param indices
+ //! A compile-time `Foldable` containing non-negative `IntegralConstant`s
+ //! representing the indices. The indices are 0-based, and they must all
+ //! be in bounds of the `xs` sequence. Note that any `Foldable` will
+ //! really do (no need for an `Iterable`, for example); the linearization
+ //! of the `indices` is used to determine the order of the elements
+ //! included in the slice.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/slice.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto slice = [](auto&& xs, auto&& indices) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct slice_impl : slice_impl<S, when<true>> { };
+
+ struct slice_t {
+ template <typename Xs, typename Indices>
+ constexpr auto operator()(Xs&& xs, Indices&& indices) const;
+ };
+
+ constexpr slice_t slice{};
+#endif
+
+ //! Shorthand to `slice` a contiguous range of elements.
+ //! @ingroup group-Sequence
+ //!
+ //! `slice_c` is simply a shorthand to slice a contiguous range of
+ //! elements. In particular, `slice_c<from, to>(xs)` is equivalent to
+ //! `slice(xs, range_c<std::size_t, from, to>)`, which simply slices
+ //! all the elements of `xs` contained in the half-open interval
+ //! delimited by `[from, to)`. Like for `slice`, the indices used with
+ //! `slice_c` are 0-based and they must be in the bounds of the sequence
+ //! being sliced.
+ //!
+ //!
+ //! @tparam from
+ //! The index of the first element in the slice.
+ //!
+ //! @tparam to
+ //! One-past the index of the last element in the slice. It must hold
+ //! that `from <= to`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/slice_c.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <std::size_t from, std::size_t to>
+ constexpr auto slice_c = [](auto&& xs) {
+ return hana::slice(forwarded(xs), hana::range_c<std::size_t, from, to>);
+ };
+#else
+ template <std::size_t from, std::size_t to>
+ struct slice_c_t;
+
+ template <std::size_t from, std::size_t to>
+ constexpr slice_c_t<from, to> slice_c{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_SLICE_HPP
diff --git a/boost/hana/fwd/sort.hpp b/boost/hana/fwd/sort.hpp
new file mode 100644
index 0000000000..785b28a568
--- /dev/null
+++ b/boost/hana/fwd/sort.hpp
@@ -0,0 +1,110 @@
+/*!
+@file
+Forward declares `boost::hana::sort`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_SORT_HPP
+#define BOOST_HANA_FWD_SORT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/detail/nested_by_fwd.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Sort a sequence, optionally based on a custom `predicate`.
+ //! @ingroup group-Sequence
+ //!
+ //! Given a Sequence and an optional predicate (by default `less`), `sort`
+ //! returns a new sequence containing the same elements as the original,
+ //! except they are ordered in such a way that if `x` comes before `y` in
+ //! the sequence, then either `predicate(x, y)` is true, or both
+ //! `predicate(x, y)` and `predicate(y, x)` are false.
+ //!
+ //! Also note that the sort is guaranteed to be stable. Hence, if `x`
+ //! comes before `y` in the original sequence and both `predicate(x, y)`
+ //! and `predicate(y, x)` are false, then `x` will come before `y` in the
+ //! resulting sequence.
+ //!
+ //! If no predicate is provided, the elements in the sequence must all be
+ //! compile-time `Orderable`.
+ //!
+ //! Signature
+ //! ---------
+ //! Given a `Sequence` `S(T)`, a boolean `IntegralConstant` `Bool` and a
+ //! binary predicate \f$ T \times T \to Bool \f$, `sort` has the following
+ //! signatures. For the variant with a provided predicate,
+ //! \f[
+ //! \mathtt{sort} : S(T) \times (T \times T \to Bool) \to S(T)
+ //! \f]
+ //!
+ //! for the variant without a custom predicate, `T` is required to be
+ //! `Orderable`. The signature is then
+ //! \f[
+ //! \mathtt{sort} : S(T) \to S(T)
+ //! \f]
+ //!
+ //! @param xs
+ //! The sequence to sort.
+ //!
+ //! @param predicate
+ //! A function called as `predicate(x, y)` for two elements `x` and `y` of
+ //! the sequence, and returning a boolean `IntegralConstant` representing
+ //! whether `x` is to be considered _less_ than `y`, i.e. whether `x` should
+ //! appear _before_ `y` in the resulting sequence. More specifically,
+ //! `predicate` must define a [strict weak ordering][1] on the elements
+ //! of the sequence. When the predicate is not specified, this defaults
+ //! to `less`. In the current version of the library, the predicate has
+ //! to return an `IntegralConstant` holding a value convertible to a `bool`.
+ //!
+ //!
+ //! Syntactic sugar (`sort.by`)
+ //! ---------------------------
+ //! `sort` can be called in a third way, which provides a nice syntax
+ //! especially when working with the `ordering` combinator:
+ //! @code
+ //! sort.by(predicate, xs) == sort(xs, predicate)
+ //! sort.by(predicate) == sort(-, predicate)
+ //! @endcode
+ //!
+ //! where `sort(-, predicate)` denotes the partial application of
+ //! `sort` to `predicate`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/sort.cpp
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.sort.compile.json">
+ //! </div>
+ //!
+ //! [1]: http://en.wikipedia.org/wiki/Strict_weak_ordering
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto sort = [](auto&& xs[, auto&& predicate]) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct sort_impl : sort_impl<S, when<true>> { };
+
+ struct sort_t : detail::nested_by<sort_t> {
+ template <typename Xs>
+ constexpr auto operator()(Xs&& xs) const;
+
+ template <typename Xs, typename Predicate>
+ constexpr auto operator()(Xs&& xs, Predicate&& pred) const;
+ };
+
+ constexpr sort_t sort{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_SORT_HPP
diff --git a/boost/hana/fwd/span.hpp b/boost/hana/fwd/span.hpp
new file mode 100644
index 0000000000..2a46ebd88a
--- /dev/null
+++ b/boost/hana/fwd/span.hpp
@@ -0,0 +1,85 @@
+/*!
+@file
+Forward declares `boost::hana::span`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_SPAN_HPP
+#define BOOST_HANA_FWD_SPAN_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/detail/nested_by_fwd.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns a `Product` containing the longest prefix of a sequence
+ //! satisfying a predicate, and the rest of the sequence.
+ //! @ingroup group-Sequence
+ //!
+ //! The first component of the returned `Product` is a sequence for which
+ //! all elements satisfy the given predicate. The second component of the
+ //! returned `Product` is a sequence containing the remainder of the
+ //! argument. Both or either sequences may be empty, depending on the
+ //! input argument. More specifically,
+ //! @code
+ //! span(xs, predicate) == make_pair(take_while(xs, predicate),
+ //! drop_while(xs, predicate))
+ //! @endcode
+ //! except that `make_pair` may be an arbitrary `Product`.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a `Sequence` `S(T)`, a `Logical` `Bool` and a predicate
+ //! \f$ T \to Bool \f$, `span` has the following signature:
+ //! \f[
+ //! \mathtt{span} : S(T) \times (T \to Bool) \to S(T) \times S(T)
+ //! \f]
+ //!
+ //! @param xs
+ //! The sequence to break into two parts.
+ //!
+ //! @param predicate
+ //! A function called as `predicate(x)`, where `x` is an element of the
+ //! sequence, and returning a `Logical. In the current implementation of
+ //! the library, `predicate` has to return a compile-time `Logical`.
+ //!
+ //!
+ //! Syntactic sugar (`span.by`)
+ //! ---------------------------
+ //! `span` can be called in an alternate way, which provides a nice syntax
+ //! in some cases where the predicate is short:
+ //! @code
+ //! span.by(predicate, xs) == span(xs, predicate)
+ //! span.by(predicate) == span(-, predicate)
+ //! @endcode
+ //!
+ //! where `span(-, predicate)` denotes the partial application of
+ //! `span` to `predicate`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/span.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto span = [](auto&& xs, auto&& predicate) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct span_impl : span_impl<S, when<true>> { };
+
+ struct span_t : detail::nested_by<span_t> {
+ template <typename Xs, typename Pred>
+ constexpr auto operator()(Xs&& xs, Pred&& pred) const;
+ };
+
+ constexpr span_t span{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_SPAN_HPP
diff --git a/boost/hana/fwd/string.hpp b/boost/hana/fwd/string.hpp
new file mode 100644
index 0000000000..f96494b165
--- /dev/null
+++ b/boost/hana/fwd/string.hpp
@@ -0,0 +1,240 @@
+/*!
+@file
+Forward declares `boost::hana::string`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_STRING_HPP
+#define BOOST_HANA_FWD_STRING_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ //! @ingroup group-datatypes
+ //! Compile-time string.
+ //!
+ //! Conceptually, a `hana::string` is like a tuple holding
+ //! `integral_constant`s of underlying type `char`. However, the
+ //! interface of `hana::string` is not as rich as that of a tuple,
+ //! because a string can only hold compile-time characters as opposed
+ //! to any kind of object.
+ //!
+ //! Compile-time strings are used for simple purposes like being keys in a
+ //! `hana::map` or tagging the members of a `Struct`. However, you might
+ //! find that `hana::string` does not provide enough functionality to be
+ //! used as a full-blown compile-time string implementation (e.g. regexp
+ //! matching or substring finding). Indeed, providing a comprehensive
+ //! string interface is a lot of job, and it is out of the scope of the
+ //! library for the time being.
+ //!
+ //!
+ //! @note
+ //! The representation of `hana::string` is implementation-defined.
+ //! In particular, one should not take for granted that the template
+ //! parameters are `char`s. The proper way to access the contents of
+ //! a `hana::string` as character constants is to use `hana::unpack`
+ //! or `hana::to<char const*>`, as documented below.
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! For most purposes, a `hana::string` is functionally equivalent to a
+ //! tuple holding `Constant`s of underlying type `char`.
+ //!
+ //! 1. `Comparable`\n
+ //! Two strings are equal if and only if they have the same number of
+ //! characters and characters at corresponding indices are equal.
+ //! @include example/string/comparable.cpp
+ //!
+ //! 2. `Orderable`\n
+ //! The total order implemented for `Orderable` is the usual
+ //! lexicographical comparison of strings.
+ //! @include example/string/orderable.cpp
+ //!
+ //! 3. `Foldable`\n
+ //! Folding a string is equivalent to folding the sequence of its
+ //! characters.
+ //! @include example/string/foldable.cpp
+ //!
+ //! 4. `Iterable`\n
+ //! Iterating over a string is equivalent to iterating over the sequence
+ //! of its characters. Also note that `operator[]` can be used instead of
+ //! the `at` function.
+ //! @include example/string/iterable.cpp
+ //!
+ //! 5. `Searchable`\n
+ //! Searching through a string is equivalent to searching through the
+ //! sequence of its characters.
+ //! @include example/string/searchable.cpp
+ //!
+ //! 6. `Hashable`\n
+ //! The hash of a compile-time string is a type uniquely representing
+ //! that string.
+ //! @include example/string/hashable.cpp
+ //!
+ //!
+ //! Conversion to `char const*`
+ //! ---------------------------
+ //! A `hana::string` can be converted to a `constexpr` null-delimited
+ //! string of type `char const*` by using `to<char const*>`. This makes
+ //! it easy to turn a compile-time string into a runtime string. However,
+ //! note that this conversion is not an embedding, because `char const*`
+ //! does not model the same concepts as `hana::string` does.
+ //! @include example/string/to.cpp
+ //!
+ //!
+ //! > #### Rationale for `hana::string` not being a `Constant`
+ //! > The underlying type held by a `hana::string` could be either
+ //! > `char const*` or some other constexpr-enabled string-like container.
+ //! > In the first case, `hana::string` can not be a `Constant` because
+ //! > the models of several concepts would not be respected by the
+ //! > underlying type, causing `value` not to be structure-preserving.
+ //! > Providing an underlying value of constexpr-enabled string-like
+ //! > container type like `std::string_view` would be great, but that's
+ //! > a bit complicated for the time being.
+ template <typename implementation_defined>
+ struct string {
+ //! Equivalent to `hana::equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator==(X&& x, Y&& y);
+
+ //! Equivalent to `hana::not_equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator!=(X&& x, Y&& y);
+
+ //! Equivalent to `hana::less`
+ template <typename X, typename Y>
+ friend constexpr auto operator<(X&& x, Y&& y);
+
+ //! Equivalent to `hana::greater`
+ template <typename X, typename Y>
+ friend constexpr auto operator>(X&& x, Y&& y);
+
+ //! Equivalent to `hana::less_equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator<=(X&& x, Y&& y);
+
+ //! Equivalent to `hana::greater_equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator>=(X&& x, Y&& y);
+
+ //! Equivalent to `hana::at`
+ template <typename N>
+ constexpr decltype(auto) operator[](N&& n);
+ };
+#else
+ template <char ...s>
+ struct string;
+#endif
+
+ //! Tag representing a compile-time string.
+ //! @relates hana::string
+ struct string_tag { };
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ //! Create a compile-time `hana::string` from a parameter pack of `char`
+ //! `integral_constant`s.
+ //! @relates hana::string
+ //!
+ //! Given zero or more `integral_constant`s of underlying type `char`,
+ //! `make<string_tag>` creates a `hana::string` containing those characters.
+ //! This is provided mostly for consistency with the rest of the library,
+ //! as `hana::string_c` is more convenient to use in most cases.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/string/make.cpp
+ template <>
+ constexpr auto make<string_tag> = [](auto&& ...chars) {
+ return string<implementation_defined>{};
+ };
+#endif
+
+ //! Alias to `make<string_tag>`; provided for convenience.
+ //! @relates hana::string
+ constexpr auto make_string = make<string_tag>;
+
+ //! Create a compile-time string from a parameter pack of characters.
+ //! @relates hana::string
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/string/string_c.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <char ...s>
+ constexpr string<implementation_defined> string_c{};
+#else
+ template <char ...s>
+ constexpr string<s...> string_c{};
+#endif
+
+ //! Create a compile-time string from a string literal.
+ //! @relates hana::string
+ //!
+ //! This macro is a more convenient alternative to `string_c` for creating
+ //! compile-time strings. However, since this macro uses a lambda
+ //! internally, it can't be used in an unevaluated context.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/string/macro.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ auto BOOST_HANA_STRING(s) = see documentation;
+ #define BOOST_HANA_STRING(s) see documentation
+
+ // Note:
+ // The trick above seems to exploit a bug in Doxygen, which makes the
+ // BOOST_HANA_STRING macro appear in the related objects of hana::string
+ // (as we want it to).
+#else
+ // defined in <boost/hana/string.hpp>
+#endif
+
+#ifdef BOOST_HANA_CONFIG_ENABLE_STRING_UDL
+ namespace literals {
+ //! Creates a compile-time string from a string literal.
+ //! @relatesalso boost::hana::string
+ //!
+ //! The string literal is parsed at compile-time and the result is
+ //! returned as a `hana::string`. This feature is an extension that
+ //! is disabled by default; see below for details.
+ //!
+ //! @note
+ //! Only narrow string literals are supported right now; support for
+ //! fancier types of string literals like wide or UTF-XX might be
+ //! added in the future if there is a demand for it. See [this issue]
+ //! [Hana.issue80] if you need this.
+ //!
+ //! @warning
+ //! This user-defined literal is an extension which requires a special
+ //! string literal operator that is not part of the standard yet.
+ //! That operator is supported by both Clang and GCC, and several
+ //! proposals were made for it to enter C++17. However, since it is
+ //! not standard, it is disabled by default and defining the
+ //! `BOOST_HANA_CONFIG_ENABLE_STRING_UDL` config macro is required
+ //! to get this operator. Hence, if you want to stay safe, just use
+ //! the `BOOST_HANA_STRING` macro instead. If you want to be fast and
+ //! furious (I do), define `BOOST_HANA_CONFIG_ENABLE_STRING_UDL`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/string/literal.cpp
+ //!
+ //! [Hana.issue80]: https://github.com/boostorg/hana/issues/80
+ template <typename CharT, CharT ...s>
+ constexpr auto operator"" _s();
+ }
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_STRING_HPP
diff --git a/boost/hana/fwd/suffix.hpp b/boost/hana/fwd/suffix.hpp
new file mode 100644
index 0000000000..ec3002aeef
--- /dev/null
+++ b/boost/hana/fwd/suffix.hpp
@@ -0,0 +1,72 @@
+/*!
+@file
+Forward declares `boost::hana::suffix`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_SUFFIX_HPP
+#define BOOST_HANA_FWD_SUFFIX_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Inserts a value after each element of a monadic structure.
+ //! @ingroup group-MonadPlus
+ //!
+ //! Given a monadic structure `xs` and a value `z` (called the suffix),
+ //! `suffix` returns a new monadic structure such that
+ //! @code
+ //! suffix(xs, z) == flatten(transform(xs, [](auto x) {
+ //! return concat(lift<M>(x), lift<M>(z));
+ //! }))
+ //! @endcode
+ //!
+ //! For sequences, this simply corresponds to inserting the suffix after
+ //! each element of the sequence. For example, given a sequence
+ //! `[x1, ..., xn]`, `suffix` will return
+ //! @code
+ //! [x1, z, x2, z, ..., xn, z]
+ //! @endcode
+ //! As explained above, this can be generalized to other MonadPlus models,
+ //! with various levels of interest.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a MonadPlus `M`, the signature is
+ //! @f$ \mathtt{suffix} : M(T) \times T \to M(T) @f$.
+ //!
+ //! @param xs
+ //! A monadic structure.
+ //!
+ //! @param sfx
+ //! A value (the suffix) to insert after each element of a monadic
+ //! structure.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/suffix.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto suffix = [](auto&& xs, auto&& sfx) {
+ return tag-dispatched;
+ };
+#else
+ template <typename M, typename = void>
+ struct suffix_impl : suffix_impl<M, when<true>> { };
+
+ struct suffix_t {
+ template <typename Xs, typename Sfx>
+ constexpr auto operator()(Xs&& xs, Sfx&& sfx) const;
+ };
+
+ constexpr suffix_t suffix{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_SUFFIX_HPP
diff --git a/boost/hana/fwd/sum.hpp b/boost/hana/fwd/sum.hpp
new file mode 100644
index 0000000000..273f43c77b
--- /dev/null
+++ b/boost/hana/fwd/sum.hpp
@@ -0,0 +1,79 @@
+/*!
+@file
+Forward declares `boost::hana::sum`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_SUM_HPP
+#define BOOST_HANA_FWD_SUM_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/fwd/integral_constant.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Compute the sum of the numbers of a structure.
+ //! @ingroup group-Foldable
+ //!
+ //! More generally, `sum` will take any foldable structure containing
+ //! objects forming a Monoid and reduce them using the Monoid's binary
+ //! operation. The initial state for folding is the identity of the
+ //! Monoid. It is sometimes necessary to specify the Monoid to use;
+ //! this is possible by using `sum<M>`. If no Monoid is specified,
+ //! the structure will use the Monoid formed by the elements it contains
+ //! (if it knows it), or `integral_constant_tag<int>` otherwise. Hence,
+ //! @code
+ //! sum<M>(xs) = fold_left(xs, zero<M or inferred Monoid>(), plus)
+ //! sum<> = sum<integral_constant_tag<int>>
+ //! @endcode
+ //!
+ //! For numbers, this will just compute the sum of the numbers in the
+ //! `xs` structure.
+ //!
+ //!
+ //! @note
+ //! The elements of the structure are not actually required to be in the
+ //! same Monoid, but it must be possible to perform `plus` on any two
+ //! adjacent elements of the structure, which requires each pair of
+ //! adjacent element to at least have a common Monoid embedding. The
+ //! meaning of "adjacent" as used here is that two elements of the
+ //! structure `x` and `y` are adjacent if and only if they are adjacent
+ //! in the linearization of that structure, as documented by the Iterable
+ //! concept.
+ //!
+ //!
+ //! Why must we sometimes specify the `Monoid` by using `sum<M>`?
+ //! -------------------------------------------------------------
+ //! This is because sequence tags like `tuple_tag` are not parameterized
+ //! (by design). Hence, we do not know what kind of objects are in the
+ //! sequence, so we can't know a `0` value of which type should be
+ //! returned when the sequence is empty. Therefore, the type of the
+ //! `0` to return in the empty case must be specified explicitly. Other
+ //! foldable structures like `hana::range`s will ignore the suggested
+ //! Monoid because they know the tag of the objects they contain. This
+ //! inconsistent behavior is a limitation of the current design with
+ //! non-parameterized tags, but we have no good solution for now.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/sum.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto sum = see documentation;
+#else
+ template <typename T, typename = void>
+ struct sum_impl : sum_impl<T, when<true>> { };
+
+ template <typename M>
+ struct sum_t;
+
+ template <typename M = integral_constant_tag<int>>
+ constexpr sum_t<M> sum{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_SUM_HPP
diff --git a/boost/hana/fwd/symmetric_difference.hpp b/boost/hana/fwd/symmetric_difference.hpp
new file mode 100644
index 0000000000..e0ba2c7c91
--- /dev/null
+++ b/boost/hana/fwd/symmetric_difference.hpp
@@ -0,0 +1,62 @@
+/*!
+@file
+Forward declares `boost::hana::symmetric_difference`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_SYMMETRIC_DIFFERENCE_HPP
+#define BOOST_HANA_FWD_SYMMETRIC_DIFFERENCE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns the symmetric set-theoretic difference of two sets.
+ //! @relates hana::set
+ //!
+ //! Given two sets `xs` and `ys`, `symmetric_difference(xs, ys)` is a new
+ //! set containing all the elements of `xs` that are not contained in `ys`,
+ //! and all the elements of `ys` that are not contained in `xs`. The
+ //! symmetric difference of two sets satisfies the following:
+ //! @code
+ //! symmetric_difference(xs, ys) == union_(difference(xs, ys), difference(ys, xs))
+ //! @endcode
+ //!
+ //!
+ //! @param xs, ys
+ //! Two sets to compute the symmetric difference of.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/symmetric_difference.cpp
+ //!
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.symmetric_difference.compile.json">
+ //! </div>
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto symmetric_difference = [](auto&& xs, auto&& ys) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct symmetric_difference_impl : symmetric_difference_impl<S, when<true>> { };
+
+ struct symmetric_difference_t {
+ template <typename Xs, typename Ys>
+ constexpr auto operator()(Xs&& xs, Ys&& ys) const;
+ };
+
+ constexpr symmetric_difference_t symmetric_difference{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_SYMMETRIC_DIFFERENCE_HPP
diff --git a/boost/hana/fwd/take_back.hpp b/boost/hana/fwd/take_back.hpp
new file mode 100644
index 0000000000..60560aa3d9
--- /dev/null
+++ b/boost/hana/fwd/take_back.hpp
@@ -0,0 +1,58 @@
+/*!
+@file
+Forward declares `boost::hana::take_back`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_TAKE_BACK_HPP
+#define BOOST_HANA_FWD_TAKE_BACK_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+#include <cstddef>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns the last `n` elements of a sequence, or the whole sequence
+ //! if the sequence has less than `n` elements.
+ //! @ingroup group-Sequence
+ //!
+ //! Given a `Sequence` `xs` and an `IntegralConstant` `n`, `take_back(xs, n)`
+ //! is a new sequence containing the last `n` elements of `xs`, in the
+ //! same order. If `length(xs) <= n`, the whole sequence is returned and
+ //! no error is triggered.
+ //!
+ //!
+ //! @param xs
+ //! The sequence to take the elements from.
+ //!
+ //! @param n
+ //! A non-negative `IntegralConstant` representing the number of elements
+ //! to keep in the resulting sequence.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/take_back.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto take_back = [](auto&& xs, auto const& n) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct take_back_impl : take_back_impl<S, when<true>> { };
+
+ struct take_back_t {
+ template <typename Xs, typename N>
+ constexpr auto operator()(Xs&& xs, N const& n) const;
+ };
+
+ constexpr take_back_t take_back{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_TAKE_BACK_HPP
diff --git a/boost/hana/fwd/take_front.hpp b/boost/hana/fwd/take_front.hpp
new file mode 100644
index 0000000000..fe46b35133
--- /dev/null
+++ b/boost/hana/fwd/take_front.hpp
@@ -0,0 +1,78 @@
+/*!
+@file
+Forward declares `boost::hana::take_front` and `boost::hana::take_front_c`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_TAKE_FRONT_HPP
+#define BOOST_HANA_FWD_TAKE_FRONT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+#include <cstddef>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns the first `n` elements of a sequence, or the whole sequence
+ //! if the sequence has less than `n` elements.
+ //! @ingroup group-Sequence
+ //!
+ //! Given a `Sequence` `xs` and an `IntegralConstant` `n`, `take_front(xs, n)`
+ //! is a new sequence containing the first `n` elements of `xs`, in the
+ //! same order. If `length(xs) <= n`, the whole sequence is returned and
+ //! no error is triggered.
+ //!
+ //!
+ //! @param xs
+ //! The sequence to take the elements from.
+ //!
+ //! @param n
+ //! A non-negative `IntegralConstant` representing the number of elements
+ //! to keep in the resulting sequence.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/take_front.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto take_front = [](auto&& xs, auto const& n) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct take_front_impl : take_front_impl<S, when<true>> { };
+
+ struct take_front_t {
+ template <typename Xs, typename N>
+ constexpr auto operator()(Xs&& xs, N const& n) const;
+ };
+
+ constexpr take_front_t take_front{};
+#endif
+
+ //! Equivalent to `take_front`; provided for convenience.
+ //! @ingroup group-Sequence
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/take_front_c.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <std::size_t n>
+ constexpr auto take_front_c = [](auto&& xs) {
+ return hana::take_front(forwarded(xs), hana::size_c<n>);
+ };
+#else
+ template <std::size_t n>
+ struct take_front_c_t;
+
+ template <std::size_t n>
+ constexpr take_front_c_t<n> take_front_c{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_TAKE_FRONT_HPP
diff --git a/boost/hana/fwd/take_while.hpp b/boost/hana/fwd/take_while.hpp
new file mode 100644
index 0000000000..7807512cc4
--- /dev/null
+++ b/boost/hana/fwd/take_while.hpp
@@ -0,0 +1,56 @@
+/*!
+@file
+Forward declares `boost::hana::take_while`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_TAKE_WHILE_HPP
+#define BOOST_HANA_FWD_TAKE_WHILE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Take elements from a sequence while the `predicate` is satisfied.
+ //! @ingroup group-Sequence
+ //!
+ //! Specifically, `take_while` returns a new sequence containing the
+ //! longest prefix of `xs` in which all the elements satisfy the given
+ //! predicate.
+ //!
+ //!
+ //! @param xs
+ //! The sequence to take elements from.
+ //!
+ //! @param predicate
+ //! A function called as `predicate(x)`, where `x` is an element of the
+ //! sequence, and returning a `Logical` representing whether `x` should be
+ //! included in the resulting sequence. In the current version of the
+ //! library, `predicate` has to return a `Constant Logical`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/take_while.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto take_while = [](auto&& xs, auto&& predicate) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct take_while_impl : take_while_impl<S, when<true>> { };
+
+ struct take_while_t {
+ template <typename Xs, typename Pred>
+ constexpr auto operator()(Xs&& xs, Pred&& pred) const;
+ };
+
+ constexpr take_while_t take_while{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_TAKE_WHILE_HPP
diff --git a/boost/hana/fwd/tap.hpp b/boost/hana/fwd/tap.hpp
new file mode 100644
index 0000000000..0f186c021b
--- /dev/null
+++ b/boost/hana/fwd/tap.hpp
@@ -0,0 +1,65 @@
+/*!
+@file
+Forward declares `boost::hana::tap`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_TAP_HPP
+#define BOOST_HANA_FWD_TAP_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Tap inside a monadic chain.
+ //! @ingroup group-Monad
+ //!
+ //! Given a function `f`, `tap<M>` returns a new function which performs
+ //! `f` on its argument and then returns the argument lifted in the `M`
+ //! `Monad`. Combined with the property that `chain(m, lift<M>) == m`,
+ //! this provides a way of executing an action inside a monadic chain
+ //! without influencing its overall result. This is useful to e.g. insert
+ //! debug statements or perform actions that are not tied to the chain but
+ //! that need to be executed inside of it.
+ //!
+ //! @note
+ //! Since C++ is not a pure language, it is possible to perform side
+ //! effects inside the `f` function. Actually, side effects are the
+ //! only reason why one might want to use `tap`. However, one should
+ //! not rely on the side effects being done in any specific order.
+ //!
+ //!
+ //! @tparam M
+ //! The tag (a `Monad`) of the monads in the tapped monadic chain.
+ //!
+ //! @param f
+ //! A function to be executed inside a monadic chain. It will be called
+ //! as `f(x)`, where `x` is a value inside the previous monad in the
+ //! chain. The result of `f` is always discarded.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/tap.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename M>
+ constexpr auto tap = [](auto&& f) {
+ return tag-dispatched;
+ };
+#else
+ template <typename M, typename = void>
+ struct tap_impl : tap_impl<M, when<true>> { };
+
+ template <typename M>
+ struct tap_t;
+
+ template <typename M>
+ constexpr tap_t<M> tap{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_TAP_HPP
diff --git a/boost/hana/fwd/then.hpp b/boost/hana/fwd/then.hpp
new file mode 100644
index 0000000000..83768e6ffb
--- /dev/null
+++ b/boost/hana/fwd/then.hpp
@@ -0,0 +1,52 @@
+/*!
+@file
+Forward declares `boost::hana::then`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_THEN_HPP
+#define BOOST_HANA_FWD_THEN_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Sequentially compose two monadic actions, discarding any value
+ //! produced by the first but not its effects.
+ //! @ingroup group-Monad
+ //!
+ //!
+ //! @param before
+ //! The first `Monad` in the monadic composition chain. The result of
+ //! this monad is ignored, but its effects are combined with that of the
+ //! second monad.
+ //!
+ //! @param xs
+ //! The second `Monad` in the monadic composition chain.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/then.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto then = [](auto&& before, auto&& xs) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename M, typename = void>
+ struct then_impl : then_impl<M, when<true>> { };
+
+ struct then_t {
+ template <typename Before, typename Xs>
+ constexpr decltype(auto) operator()(Before&& before, Xs&& xs) const;
+ };
+
+ constexpr then_t then{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_THEN_HPP
diff --git a/boost/hana/fwd/transform.hpp b/boost/hana/fwd/transform.hpp
new file mode 100644
index 0000000000..5606ddf82c
--- /dev/null
+++ b/boost/hana/fwd/transform.hpp
@@ -0,0 +1,64 @@
+/*!
+@file
+Forward declares `boost::hana::transform`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_TRANSFORM_HPP
+#define BOOST_HANA_FWD_TRANSFORM_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Map a function over a `Functor`.
+ //! @ingroup group-Functor
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given `F` a Functor, the signature is
+ //! \f$
+ //! \mathtt{transform} : F(T) \times (T \to U) \to F(U)
+ //! \f$
+ //!
+ //! @param xs
+ //! The structure to map `f` over.
+ //!
+ //! @param f
+ //! A function called as `f(x)` on element(s) `x` of the structure,
+ //! and returning a new value to replace `x` in the structure.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/transform.cpp
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.transform.compile.json">
+ //! </div>
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto transform = [](auto&& xs, auto&& f) {
+ return tag-dispatched;
+ };
+#else
+ template <typename Xs, typename = void>
+ struct transform_impl : transform_impl<Xs, when<true>> { };
+
+ struct transform_t {
+ template <typename Xs, typename F>
+ constexpr auto operator()(Xs&& xs, F&& f) const;
+ };
+
+ constexpr transform_t transform{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_TRANSFORM_HPP
diff --git a/boost/hana/fwd/tuple.hpp b/boost/hana/fwd/tuple.hpp
new file mode 100644
index 0000000000..1624b3d296
--- /dev/null
+++ b/boost/hana/fwd/tuple.hpp
@@ -0,0 +1,224 @@
+/*!
+@file
+Forward declares `boost::hana::tuple`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_TUPLE_HPP
+#define BOOST_HANA_FWD_TUPLE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+#include <boost/hana/fwd/core/to.hpp>
+#include <boost/hana/fwd/integral_constant.hpp>
+#include <boost/hana/fwd/type.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-datatypes
+ //! General purpose index-based heterogeneous sequence with a fixed length.
+ //!
+ //! The tuple is the bread and butter for static metaprogramming.
+ //! Conceptually, it is like a `std::tuple`; it is a container able
+ //! of holding objects of different types and whose size is fixed at
+ //! compile-time. However, Hana's tuple provides much more functionality
+ //! than its `std` counterpart, and it is also much more efficient than
+ //! all standard library implementations tested so far.
+ //!
+ //! Tuples are index-based sequences. If you need an associative
+ //! sequence with a key-based access, then you should consider
+ //! `hana::map` or `hana::set` instead.
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! `Sequence`, and all the concepts it refines
+ //!
+ //!
+ //! Provided operators
+ //! ------------------
+ //! For convenience, the following operators are provided:
+ //! @code
+ //! xs == ys -> equal(xs, ys)
+ //! xs != ys -> not_equal(xs, ys)
+ //!
+ //! xs < ys -> less(xs, ys)
+ //! xs <= ys -> less_equal(xs, ys)
+ //! xs > ys -> greater(xs, ys)
+ //! xs >= ys -> greater_equal(xs, ys)
+ //!
+ //! xs | f -> chain(xs, f)
+ //!
+ //! xs[n] -> at(xs, n)
+ //! @endcode
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/tuple/tuple.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename ...Xn>
+ struct tuple {
+ //! Default constructs the `tuple`. Only exists when all the elements
+ //! of the tuple are default constructible.
+ constexpr tuple();
+
+ //! Initialize each element of the tuple with the corresponding element
+ //! from `xn...`. Only exists when all the elements of the tuple are
+ //! copy-constructible.
+ //!
+ //! @note
+ //! Unlike the corresponding constructor for `std::tuple`, this
+ //! constructor is not explicit. This allows returning a tuple
+ //! from a function with the brace-initialization syntax.
+ constexpr tuple(Xn const& ...xn);
+
+ //! Initialize each element of the tuple by perfect-forwarding the
+ //! corresponding element in `yn...`. Only exists when all the
+ //! elements of the created tuple are constructible from the
+ //! corresponding perfect-forwarded value.
+ //!
+ //! @note
+ //! Unlike the corresponding constructor for `std::tuple`, this
+ //! constructor is not explicit. This allows returning a tuple
+ //! from a function with the brace-initialization syntax.
+ template <typename ...Yn>
+ constexpr tuple(Yn&& ...yn);
+
+ //! Copy-initialize a tuple from another tuple. Only exists when all
+ //! the elements of the constructed tuple are copy-constructible from
+ //! the corresponding element in the source tuple.
+ template <typename ...Yn>
+ constexpr tuple(tuple<Yn...> const& other);
+
+ //! Move-initialize a tuple from another tuple. Only exists when all
+ //! the elements of the constructed tuple are move-constructible from
+ //! the corresponding element in the source tuple.
+ template <typename ...Yn>
+ constexpr tuple(tuple<Yn...>&& other);
+
+ //! Assign a tuple to another tuple. Only exists when all the elements
+ //! of the destination tuple are assignable from the corresponding
+ //! element in the source tuple.
+ template <typename ...Yn>
+ constexpr tuple& operator=(tuple<Yn...> const& other);
+
+ //! Move-assign a tuple to another tuple. Only exists when all the
+ //! elements of the destination tuple are move-assignable from the
+ //! corresponding element in the source tuple.
+ template <typename ...Yn>
+ constexpr tuple& operator=(tuple<Yn...>&& other);
+
+ //! Equivalent to `hana::chain`.
+ template <typename ...T, typename F>
+ friend constexpr auto operator|(tuple<T...>, F);
+
+ //! Equivalent to `hana::equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator==(X&& x, Y&& y);
+
+ //! Equivalent to `hana::not_equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator!=(X&& x, Y&& y);
+
+ //! Equivalent to `hana::less`
+ template <typename X, typename Y>
+ friend constexpr auto operator<(X&& x, Y&& y);
+
+ //! Equivalent to `hana::greater`
+ template <typename X, typename Y>
+ friend constexpr auto operator>(X&& x, Y&& y);
+
+ //! Equivalent to `hana::less_equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator<=(X&& x, Y&& y);
+
+ //! Equivalent to `hana::greater_equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator>=(X&& x, Y&& y);
+
+ //! Equivalent to `hana::at`
+ template <typename N>
+ constexpr decltype(auto) operator[](N&& n);
+ };
+#else
+ template <typename ...Xn>
+ struct tuple;
+#endif
+
+ //! Tag representing `hana::tuple`s.
+ //! @related tuple
+ struct tuple_tag { };
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ //! Function object for creating a `tuple`.
+ //! @relates hana::tuple
+ //!
+ //! Given zero or more objects `xs...`, `make<tuple_tag>` returns a new tuple
+ //! containing those objects. The elements are held by value inside the
+ //! resulting tuple, and they are hence copied or moved in. This is
+ //! analogous to `std::make_tuple` for creating Hana tuples.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/tuple/make.cpp
+ template <>
+ constexpr auto make<tuple_tag> = [](auto&& ...xs) {
+ return tuple<std::decay_t<decltype(xs)>...>{forwarded(xs)...};
+ };
+#endif
+
+ //! Alias to `make<tuple_tag>`; provided for convenience.
+ //! @relates hana::tuple
+ constexpr auto make_tuple = make<tuple_tag>;
+
+ //! Equivalent to `to<tuple_tag>`; provided for convenience.
+ //! @relates hana::tuple
+ constexpr auto to_tuple = to<tuple_tag>;
+
+ //! Create a tuple specialized for holding `hana::type`s.
+ //! @relates hana::tuple
+ //!
+ //! This is functionally equivalent to `make<tuple_tag>(type_c<T>...)`, except
+ //! that using `tuple_t` allows the library to perform some compile-time
+ //! optimizations. Also note that the type of the objects returned by
+ //! `tuple_t` and an equivalent call to `make<tuple_tag>` may differ.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/tuple/tuple_t.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename ...T>
+ constexpr implementation_defined tuple_t{};
+#else
+ template <typename ...T>
+ constexpr hana::tuple<hana::type<T>...> tuple_t{};
+#endif
+
+ //! Create a tuple specialized for holding `hana::integral_constant`s.
+ //! @relates hana::tuple
+ //!
+ //! This is functionally equivalent to `make<tuple_tag>(integral_c<T, v>...)`,
+ //! except that using `tuple_c` allows the library to perform some
+ //! compile-time optimizations. Also note that the type of the objects
+ //! returned by `tuple_c` and an equivalent call to `make<tuple_tag>` may differ.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/tuple/tuple_c.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename T, T ...v>
+ constexpr implementation_defined tuple_c{};
+#else
+ template <typename T, T ...v>
+ constexpr hana::tuple<hana::integral_constant<T, v>...> tuple_c{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_TUPLE_HPP
diff --git a/boost/hana/fwd/type.hpp b/boost/hana/fwd/type.hpp
new file mode 100644
index 0000000000..1c9536aae9
--- /dev/null
+++ b/boost/hana/fwd/type.hpp
@@ -0,0 +1,478 @@
+/*!
+@file
+Forward declares `boost::hana::type` and related utilities.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_TYPE_HPP
+#define BOOST_HANA_FWD_TYPE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Base class of `hana::type`; used for pattern-matching.
+ //! @relates hana::type
+ //!
+ //! Example
+ //! -------
+ //! @include example/type/basic_type.cpp
+ template <typename T>
+ struct basic_type;
+
+ //! @ingroup group-datatypes
+ //! C++ type in value-level representation.
+ //!
+ //! A `type` is a special kind of object representing a C++ type like
+ //! `int`, `void`, `std::vector<float>` or anything else you can imagine.
+ //!
+ //! This page explains how `type`s work at a low level. To gain
+ //! intuition about type-level metaprogramming in Hana, you should
+ //! read the [tutorial section](@ref tutorial-type) on type-level
+ //! computations.
+ //!
+ //!
+ //! @note
+ //! For subtle reasons having to do with ADL, the actual representation of
+ //! `hana::type` is implementation-defined. In particular, `hana::type`
+ //! may be a dependent type, so one should not attempt to do pattern
+ //! matching on it. However, one can assume that `hana::type` _inherits_
+ //! from `hana::basic_type`, which can be useful when declaring overloaded
+ //! functions:
+ //! @code
+ //! template <typename T>
+ //! void f(hana::basic_type<T>) {
+ //! // do something with T
+ //! }
+ //! @endcode
+ //!
+ //!
+ //! @anchor type_lvalues_and_rvalues
+ //! Lvalues and rvalues
+ //! -------------------
+ //! When storing `type`s in heterogeneous containers, some algorithms
+ //! will return references to those objects. Since we are primarily
+ //! interested in accessing their nested `::%type`, receiving a reference
+ //! is undesirable; we would end up trying to fetch the nested `::%type`
+ //! inside a reference type, which is a compilation error:
+ //! @code
+ //! auto ts = make_tuple(type_c<int>, type_c<char>);
+ //! using T = decltype(ts[0_c])::type; // error: 'ts[0_c]' is a reference!
+ //! @endcode
+ //!
+ //! For this reason, `type`s provide an overload of the unary `+`
+ //! operator that can be used to turn a lvalue into a rvalue. So when
+ //! using a result which might be a reference to a `type` object, one
+ //! can use `+` to make sure a rvalue is obtained before fetching its
+ //! nested `::%type`:
+ //! @code
+ //! auto ts = make_tuple(type_c<int>, type_c<char>);
+ //! using T = decltype(+ts[0_c])::type; // ok: '+ts[0_c]' is an rvalue
+ //! @endcode
+ //!
+ //!
+ //! Modeled concepts
+ //! ----------------
+ //! 1. `Comparable`\n
+ //! Two types are equal if and only if they represent the same C++ type.
+ //! Hence, equality is equivalent to the `std::is_same` type trait.
+ //! @include example/type/comparable.cpp
+ //!
+ //! 2. `Hashable`\n
+ //! The hash of a type is just that type itself. In other words, `hash`
+ //! is the identity function on `hana::type`s.
+ //! @include example/type/hashable.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename T>
+ struct type {
+ //! Returns rvalue of self.
+ //! See @ref type_lvalues_and_rvalues "description".
+ constexpr auto operator+() const;
+
+ //! Equivalent to `hana::equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator==(X&& x, Y&& y);
+
+ //! Equivalent to `hana::not_equal`
+ template <typename X, typename Y>
+ friend constexpr auto operator!=(X&& x, Y&& y);
+ };
+#else
+ template <typename T>
+ struct type_impl;
+
+ template <typename T>
+ using type = typename type_impl<T>::_;
+#endif
+
+ //! Tag representing `hana::type`.
+ //! @relates hana::type
+ struct type_tag { };
+
+ //! Creates an object representing the C++ type `T`.
+ //! @relates hana::type
+ template <typename T>
+ constexpr type<T> type_c{};
+
+ //! `decltype` keyword, lifted to Hana.
+ //! @relates hana::type
+ //!
+ //! `decltype_` is somewhat equivalent to `decltype` in that it returns
+ //! the type of an object, except it returns it as a `hana::type` which
+ //! is a first-class citizen of Hana instead of a raw C++ type.
+ //! Specifically, given an object `x`, `decltype_` satisfies
+ //! @code
+ //! decltype_(x) == type_c<decltype(x) with references stripped>
+ //! @endcode
+ //!
+ //! As you can see, `decltype_` will strip any reference from the
+ //! object's actual type. The reason for doing so is explained below.
+ //! However, any `cv`-qualifiers will be retained. Also, when given a
+ //! `hana::type`, `decltype_` is just the identity function. Hence,
+ //! for any C++ type `T`,
+ //! @code
+ //! decltype_(type_c<T>) == type_c<T>
+ //! @endcode
+ //!
+ //! In conjunction with the way `metafunction` & al. are specified, this
+ //! behavior makes it easier to interact with both types and values at
+ //! the same time. However, it does make it impossible to create a `type`
+ //! containing another `type` with `decltype_`. In other words, it is
+ //! not possible to create a `type_c<decltype(type_c<T>)>` with this
+ //! utility, because `decltype_(type_c<T>)` would be just `type_c<T>`
+ //! instead of `type_c<decltype(type_c<T>)>`. This use case is assumed
+ //! to be rare and a hand-coded function can be used if this is needed.
+ //!
+ //!
+ //! ### Rationale for stripping the references
+ //! The rules for template argument deduction are such that a perfect
+ //! solution that always matches `decltype` is impossible. Hence, we
+ //! have to settle on a solution that's good and and consistent enough
+ //! for our needs. One case where matching `decltype`'s behavior is
+ //! impossible is when the argument is a plain, unparenthesized variable
+ //! or function parameter. In that case, `decltype_`'s argument will be
+ //! deduced as a reference to that variable, but `decltype` would have
+ //! given us the actual type of that variable, without references. Also,
+ //! given the current definition of `metafunction` & al., it would be
+ //! mostly useless if `decltype_` could return a reference, because it
+ //! is unlikely that `F` expects a reference in its simplest use case:
+ //! @code
+ //! int i = 0;
+ //! auto result = metafunction<F>(i);
+ //! @endcode
+ //!
+ //! Hence, always discarding references seems to be the least painful
+ //! solution.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/type/decltype.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto decltype_ = see documentation;
+#else
+ struct decltype_t {
+ template <typename T>
+ constexpr auto operator()(T&&) const;
+ };
+
+ constexpr decltype_t decltype_{};
+#endif
+
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ //! Equivalent to `decltype_`, provided for convenience.
+ //! @relates hana::type
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/type/make.cpp
+ template <>
+ constexpr auto make<type_tag> = hana::decltype_;
+#endif
+
+ //! Equivalent to `make<type_tag>`, provided for convenience.
+ //! @relates hana::type
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/type/make.cpp
+ constexpr auto make_type = hana::make<type_tag>;
+
+ //! `sizeof` keyword, lifted to Hana.
+ //! @relates hana::type
+ //!
+ //! `sizeof_` is somewhat equivalent to `sizeof` in that it returns the
+ //! size of an expression or type, but it takes an arbitrary expression
+ //! or a `hana::type` and returns its size as an `integral_constant`.
+ //! Specifically, given an expression `expr`, `sizeof_` satisfies
+ //! @code
+ //! sizeof_(expr) == size_t<sizeof(decltype(expr) with references stripped)>
+ //! @endcode
+ //!
+ //! However, given a `type`, `sizeof_` will simply fetch the size
+ //! of the C++ type represented by that object. In other words,
+ //! @code
+ //! sizeof_(type_c<T>) == size_t<sizeof(T)>
+ //! @endcode
+ //!
+ //! The behavior of `sizeof_` is consistent with that of `decltype_`.
+ //! In particular, see `decltype_`'s documentation to understand why
+ //! references are always stripped by `sizeof_`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/type/sizeof.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto sizeof_ = [](auto&& x) {
+ using T = typename decltype(hana::decltype_(x))::type;
+ return hana::size_c<sizeof(T)>;
+ };
+#else
+ struct sizeof_t {
+ template <typename T>
+ constexpr auto operator()(T&&) const;
+ };
+
+ constexpr sizeof_t sizeof_{};
+#endif
+
+ //! `alignof` keyword, lifted to Hana.
+ //! @relates hana::type
+ //!
+ //! `alignof_` is somewhat equivalent to `alignof` in that it returns the
+ //! alignment required by any instance of a type, but it takes a `type`
+ //! and returns its alignment as an `integral_constant`. Like `sizeof`
+ //! which works for expressions and type-ids, `alignof_` can also be
+ //! called on an arbitrary expression. Specifically, given an expression
+ //! `expr` and a C++ type `T`, `alignof_` satisfies
+ //! @code
+ //! alignof_(expr) == size_t<alignof(decltype(expr) with references stripped)>
+ //! alignof_(type_c<T>) == size_t<alignof(T)>
+ //! @endcode
+ //!
+ //! The behavior of `alignof_` is consistent with that of `decltype_`.
+ //! In particular, see `decltype_`'s documentation to understand why
+ //! references are always stripped by `alignof_`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/type/alignof.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto alignof_ = [](auto&& x) {
+ using T = typename decltype(hana::decltype_(x))::type;
+ return hana::size_c<alignof(T)>;
+ };
+#else
+ struct alignof_t {
+ template <typename T>
+ constexpr auto operator()(T&&) const;
+ };
+
+ constexpr alignof_t alignof_{};
+#endif
+
+ //! Checks whether a SFINAE-friendly expression is valid.
+ //! @relates hana::type
+ //!
+ //! Given a SFINAE-friendly function, `is_valid` returns whether the
+ //! function call is valid with the given arguments. Specifically, given
+ //! a function `f` and arguments `args...`,
+ //! @code
+ //! is_valid(f, args...) == whether f(args...) is valid
+ //! @endcode
+ //!
+ //! The result is returned as a compile-time `Logical`. Furthermore,
+ //! `is_valid` can be used in curried form as follows:
+ //! @code
+ //! is_valid(f)(args...)
+ //! @endcode
+ //!
+ //! This syntax makes it easy to create functions that check the validity
+ //! of a generic expression on any given argument(s).
+ //!
+ //! @warning
+ //! To check whether calling a nullary function `f` is valid, one should
+ //! use the `is_valid(f)()` syntax. Indeed, `is_valid(f /* no args */)`
+ //! will be interpreted as the currying of `is_valid` to `f` rather than
+ //! the application of `is_valid` to `f` and no arguments.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/type/is_valid.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto is_valid = [](auto&& f) {
+ return [](auto&& ...args) {
+ return whether f(args...) is a valid expression;
+ };
+ };
+#else
+ struct is_valid_t {
+ template <typename F>
+ constexpr auto operator()(F&&) const;
+
+ template <typename F, typename ...Args>
+ constexpr auto operator()(F&&, Args&&...) const;
+ };
+
+ constexpr is_valid_t is_valid{};
+#endif
+
+ //! Lift a template to a Metafunction.
+ //! @ingroup group-Metafunction
+ //!
+ //! Given a template class or template alias `f`, `template_<f>` is a
+ //! `Metafunction` satisfying
+ //! @code
+ //! template_<f>(type_c<x>...) == type_c<f<x...>>
+ //! decltype(template_<f>)::apply<x...>::type == f<x...>
+ //! @endcode
+ //!
+ //! @note
+ //! `template_` can't be SFINAE-friendly right now because of
+ //! [Core issue 1430][1].
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/type/template.cpp
+ //!
+ //! [1]: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1430
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <template <typename ...> class F>
+ constexpr auto template_ = [](basic_type<T>-or-T ...) {
+ return hana::type_c<F<T...>>;
+ };
+#else
+ template <template <typename ...> class F>
+ struct template_t;
+
+ template <template <typename ...> class F>
+ constexpr template_t<F> template_{};
+#endif
+
+ //! Lift a MPL-style metafunction to a Metafunction.
+ //! @ingroup group-Metafunction
+ //!
+ //! Given a MPL-style metafunction, `metafunction<f>` is a `Metafunction`
+ //! satisfying
+ //! @code
+ //! metafunction<f>(type_c<x>...) == type_c<f<x...>::type>
+ //! decltype(metafunction<f>)::apply<x...>::type == f<x...>::type
+ //! @endcode
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/type/metafunction.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <template <typename ...> class F>
+ constexpr auto metafunction = [](basic_type<T>-or-T ...) {
+ return hana::type_c<typename F<T...>::type>;
+ };
+#else
+ template <template <typename ...> class f>
+ struct metafunction_t;
+
+ template <template <typename ...> class f>
+ constexpr metafunction_t<f> metafunction{};
+#endif
+
+ //! Lift a MPL-style metafunction class to a Metafunction.
+ //! @ingroup group-Metafunction
+ //!
+ //! Given a MPL-style metafunction class, `metafunction_class<f>` is a
+ //! `Metafunction` satisfying
+ //! @code
+ //! metafunction_class<f>(type_c<x>...) == type_c<f::apply<x...>::type>
+ //! decltype(metafunction_class<f>)::apply<x...>::type == f::apply<x...>::type
+ //! @endcode
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/type/metafunction_class.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename F>
+ constexpr auto metafunction_class = [](basic_type<T>-or-T ...) {
+ return hana::type_c<typename F::template apply<T...>::type>;
+ };
+#else
+ template <typename F>
+ struct metafunction_class_t
+ : metafunction_t<F::template apply>
+ { };
+
+ template <typename F>
+ constexpr metafunction_class_t<F> metafunction_class{};
+#endif
+
+ //! Turn a `Metafunction` into a function taking `type`s and returning a
+ //! default-constructed object.
+ //! @ingroup group-Metafunction
+ //!
+ //! Given a `Metafunction` `f`, `integral` returns a new `Metafunction`
+ //! that default-constructs an object of the type returned by `f`. More
+ //! specifically, the following holds:
+ //! @code
+ //! integral(f)(t...) == decltype(f(t...))::type{}
+ //! @endcode
+ //!
+ //! The principal use case for `integral` is to transform `Metafunction`s
+ //! returning a type that inherits from a meaningful base like
+ //! `std::integral_constant` into functions returning e.g. a
+ //! `hana::integral_constant`.
+ //!
+ //! @note
+ //! - This is not a `Metafunction` because it does not return a `type`.
+ //! As such, it would not make sense to make `decltype(integral(f))`
+ //! a MPL metafunction class like the usual `Metafunction`s are.
+ //!
+ //! - When using `integral` with metafunctions returning
+ //! `std::integral_constant`s, don't forget to include the
+ //! boost/hana/ext/std/integral_constant.hpp header to ensure
+ //! Hana can interoperate with the result.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/type/integral.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto integral = [](auto f) {
+ return [](basic_type<T>-or-T ...) {
+ return decltype(f)::apply<T...>::type{};
+ };
+ };
+#else
+ template <typename F>
+ struct integral_t;
+
+ struct make_integral_t {
+ template <typename F>
+ constexpr integral_t<F> operator()(F const&) const
+ { return {}; }
+ };
+
+ constexpr make_integral_t integral{};
+#endif
+
+ //! Alias to `integral(metafunction<F>)`, provided for convenience.
+ //! @ingroup group-Metafunction
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/type/trait.cpp
+ template <template <typename ...> class F>
+ constexpr auto trait = hana::integral(hana::metafunction<F>);
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_TYPE_HPP
diff --git a/boost/hana/fwd/unfold_left.hpp b/boost/hana/fwd/unfold_left.hpp
new file mode 100644
index 0000000000..3e68e549d5
--- /dev/null
+++ b/boost/hana/fwd/unfold_left.hpp
@@ -0,0 +1,85 @@
+/*!
+@file
+Forward declares `boost::hana::unfold_left`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_UNFOLD_LEFT_HPP
+#define BOOST_HANA_FWD_UNFOLD_LEFT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Dual operation to `fold_left` for sequences.
+ //! @ingroup group-Sequence
+ //!
+ //! While `fold_left` reduces a structure to a summary value from the left,
+ //! `unfold_left` builds a sequence from a seed value and a function,
+ //! starting from the left.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a `Sequence` `S`, an initial value `state` of tag `I`, an
+ //! arbitrary Product `P` and a function \f$ f : I \to P(I, T) \f$,
+ //! `unfold_left<S>` has the following signature:
+ //! \f[
+ //! \mathtt{unfold\_left}_S : I \times (I \to P(I, T)) \to S(T)
+ //! \f]
+ //!
+ //! @tparam S
+ //! The tag of the sequence to build up.
+ //!
+ //! @param state
+ //! An initial value to build the sequence from.
+ //!
+ //! @param f
+ //! A function called as `f(state)`, where `state` is an initial value,
+ //! and returning
+ //! 1. `nothing` if it is done producing the sequence.
+ //! 2. otherwise, `just(make<P>(state, x))`, where `state` is the new
+ //! initial value used in the next call to `f`, `x` is an element to
+ //! be appended to the resulting sequence, and `P` is an arbitrary
+ //! `Product`.
+ //!
+ //!
+ //! Fun fact
+ //! ---------
+ //! In some cases, `unfold_left` can undo a `fold_left` operation:
+ //! @code
+ //! unfold_left<S>(fold_left(xs, state, f), g) == xs
+ //! @endcode
+ //!
+ //! if the following holds
+ //! @code
+ //! g(f(x, y)) == just(make_pair(x, y))
+ //! g(state) == nothing
+ //! @endcode
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/unfold_left.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename S>
+ constexpr auto unfold_left = [](auto&& state, auto&& f) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct unfold_left_impl : unfold_left_impl<S, when<true>> { };
+
+ template <typename S>
+ struct unfold_left_t;
+
+ template <typename S>
+ constexpr unfold_left_t<S> unfold_left{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_UNFOLD_LEFT_HPP
diff --git a/boost/hana/fwd/unfold_right.hpp b/boost/hana/fwd/unfold_right.hpp
new file mode 100644
index 0000000000..b688d7606f
--- /dev/null
+++ b/boost/hana/fwd/unfold_right.hpp
@@ -0,0 +1,85 @@
+/*!
+@file
+Forward declares `boost::hana::unfold_right`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_UNFOLD_RIGHT_HPP
+#define BOOST_HANA_FWD_UNFOLD_RIGHT_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Dual operation to `fold_right` for sequences.
+ //! @ingroup group-Sequence
+ //!
+ //! While `fold_right` reduces a structure to a summary value from the
+ //! right, `unfold_right` builds a sequence from a seed value and a
+ //! function, starting from the right.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a `Sequence` `S`, an initial value `state` of tag `I`, an
+ //! arbitrary Product `P` and a function \f$ f : I \to P(T, I) \f$,
+ //! `unfold_right<S>` has the following signature:
+ //! \f[
+ //! \mathtt{unfold\_right}_S : I \times (I \to P(T, I)) \to S(T)
+ //! \f]
+ //!
+ //! @tparam S
+ //! The tag of the sequence to build up.
+ //!
+ //! @param state
+ //! An initial value to build the sequence from.
+ //!
+ //! @param f
+ //! A function called as `f(state)`, where `state` is an initial value,
+ //! and returning
+ //! 1. `nothing` if it is done producing the sequence.
+ //! 2. otherwise, `just(make<P>(x, state))`, where `state` is the new
+ //! initial value used in the next call to `f`, `x` is an element to
+ //! be prepended to the resulting sequence, and `P` is an arbitrary
+ //! `Product`.
+ //!
+ //!
+ //! Fun fact
+ //! ---------
+ //! In some cases, `unfold_right` can undo a `fold_right` operation:
+ //! @code
+ //! unfold_right<S>(fold_right(xs, state, f), g) == xs
+ //! @endcode
+ //!
+ //! if the following holds
+ //! @code
+ //! g(f(x, y)) == just(make_pair(x, y))
+ //! g(state) == nothing
+ //! @endcode
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/unfold_right.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename S>
+ constexpr auto unfold_right = [](auto&& state, auto&& f) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct unfold_right_impl : unfold_right_impl<S, when<true>> { };
+
+ template <typename S>
+ struct unfold_right_t;
+
+ template <typename S>
+ constexpr unfold_right_t<S> unfold_right{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_UNFOLD_RIGHT_HPP
diff --git a/boost/hana/fwd/union.hpp b/boost/hana/fwd/union.hpp
new file mode 100644
index 0000000000..b6d63023a1
--- /dev/null
+++ b/boost/hana/fwd/union.hpp
@@ -0,0 +1,61 @@
+/*!
+@file
+Forward declares `boost::hana::union_`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_UNION_HPP
+#define BOOST_HANA_FWD_UNION_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Returns the union of two sets.
+ //! @relates hana::set
+ //!
+ //! Given two sets `xs` and `ys`, `union_(xs, ys)` is a new set containing
+ //! all the elements of `xs` and all the elements of `ys`, without
+ //! duplicates. For any object `x`, the following holds:
+ //! @code
+ //! x ^in^ union_(xs, ys) if and only if x ^in^ xs || x ^in^ ys
+ //! @endcode
+ //!
+ //!
+ //! @param xs, ys
+ //! Two sets to compute the union of.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/union.cpp
+ //!
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.union.compile.json">
+ //! </div>
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto union_ = [](auto&& xs, auto&& ys) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct union_impl : union_impl<S, when<true>> { };
+
+ struct union_t {
+ template <typename Xs, typename Ys>
+ constexpr auto operator()(Xs&& xs, Ys&& ys) const;
+ };
+
+ constexpr union_t union_{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_UNION_HPP
diff --git a/boost/hana/fwd/unique.hpp b/boost/hana/fwd/unique.hpp
new file mode 100644
index 0000000000..4271f23a9e
--- /dev/null
+++ b/boost/hana/fwd/unique.hpp
@@ -0,0 +1,91 @@
+/*!
+@file
+Forward declares `boost::hana::unique`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_UNIQUE_HPP
+#define BOOST_HANA_FWD_UNIQUE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/detail/nested_by_fwd.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Removes all consecutive duplicate elements from a Sequence.
+ //! @ingroup group-Sequence
+ //!
+ //! Given a `Sequence` and an optional binary predicate, `unique` returns
+ //! a new sequence containing only the first element of every subrange
+ //! of the original sequence whose elements are all equal. In other words,
+ //! it turns a sequence of the form `[a, a, b, c, c, c, d, d, d, a]` into
+ //! a sequence `[a, b, c, d, a]`. The equality of two elements is
+ //! determined by the provided `predicate`, or by `equal` if no
+ //! `predicate` is provided.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! Given a `Sequence` `S(T)`, a `Logical` `Bool` and a binary predicate
+ //! \f$ T \times T \to Bool \f$, `unique` has the following signature:
+ //! \f[
+ //! \mathtt{unique} : S(T) \times (T \times T \to Bool) \to S(T)
+ //! \f]
+ //!
+ //! @param xs
+ //! The sequence from which to remove consecutive duplicates.
+ //!
+ //! @param predicate
+ //! A function called as `predicate(x, y)`, where `x` and `y` are adjacent
+ //! elements of the sequence, and returning a `Logical` representing
+ //! whether `x` and `y` should be considered equal. `predicate` should
+ //! define an [equivalence relation][1] over the elements of the sequence.
+ //! In the current implementation of the library, `predicate` has to
+ //! return a compile-time `Logical`. This parameter is optional; it
+ //! defaults to `equal` if it is not provided, which then requires the
+ //! elements of the sequence to be compile-time `Comparable`.
+ //!
+ //!
+ //! Syntactic sugar (`unique.by`)
+ //! -----------------------------
+ //! `unique` can be called in an alternate way, which provides a nice
+ //! syntax, especially in conjunction with the `comparing` combinator:
+ //! @code
+ //! unique.by(predicate, xs) == unique(xs, predicate)
+ //! unique.by(predicate) == unique(-, predicate)
+ //! @endcode
+ //!
+ //! where `unique(-, predicate)` denotes the partial application of
+ //! `unique` to `predicate`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/unique.cpp
+ //!
+ //! [1]: http://en.wikipedia.org/wiki/Equivalence_relation#Definition
+#if defined(BOOST_HANA_DOXYGEN_INVOKED)
+ constexpr auto unique = [](auto&& xs[, auto&& predicate]) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct unique_impl : unique_impl<S, when<true>> { };
+
+ struct unique_t : detail::nested_by<unique_t> {
+ template <typename Xs>
+ constexpr auto operator()(Xs&& xs) const;
+
+ template <typename Xs, typename Predicate>
+ constexpr auto operator()(Xs&& xs, Predicate&& predicate) const;
+ };
+
+ constexpr unique_t unique{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_UNIQUE_HPP
diff --git a/boost/hana/fwd/unpack.hpp b/boost/hana/fwd/unpack.hpp
new file mode 100644
index 0000000000..43a4941f3e
--- /dev/null
+++ b/boost/hana/fwd/unpack.hpp
@@ -0,0 +1,103 @@
+/*!
+@file
+Forward declares `boost::hana::unpack`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_UNPACK_HPP
+#define BOOST_HANA_FWD_UNPACK_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Invoke a function with the elements of a Foldable as arguments.
+ //! @ingroup group-Foldable
+ //!
+ //! Given a function and a foldable structure whose length can be known at
+ //! compile-time, `unpack` invokes the function with the contents of that
+ //! structure. In other words, `unpack(xs, f)` is equivalent to `f(x...)`,
+ //! where `x...` are the elements of the structure. The length of the
+ //! structure must be known at compile-time, because the version of `f`'s
+ //! `operator()` that will be compiled depends on the number of arguments
+ //! it is called with, which has to be known at compile-time.
+ //!
+ //! To create a function that accepts a foldable instead of variadic
+ //! arguments, see `fuse` instead.
+ //!
+ //!
+ //! @param xs
+ //! The structure to expand into the function.
+ //!
+ //! @param f
+ //! A function to be invoked as `f(x...)`, where `x...` are the elements
+ //! of the structure as-if they had been linearized with `to<tuple_tag>`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/unpack.cpp
+ //!
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.unpack.compile.json">
+ //! </div>
+ //!
+ //!
+ //! Rationale: `unpack`'s name and parameter order
+ //! ----------------------------------------------
+ //! It has been suggested a couple of times that `unpack` be called
+ //! `apply` instead, and that the parameter order be reversed to match
+ //! that of the [proposed std::apply function][1]. However, the name
+ //! `apply` is already used to denote normal function application, an use
+ //! which is consistent with the Boost MPL library and with the rest of
+ //! the world, especially the functional programming community.
+ //! Furthermore, the author of this library considers the proposed
+ //! `std::apply` to have both an unfortunate name and an unfortunate
+ //! parameter order. Indeed, taking the function as the first argument
+ //! means that using `std::apply` with a lambda function looks like
+ //! @code
+ //! std::apply([](auto ...args) {
+ //! use(args...);
+ //! }, tuple);
+ //! @endcode
+ //!
+ //! which is undeniably ugly because of the trailing `, tuple)` part
+ //! on the last line. On the other hand, taking the function as a
+ //! second argument allows one to write
+ //! @code
+ //! hana::unpack(tuple, [](auto ...args) {
+ //! use(args...);
+ //! });
+ //! @endcode
+ //!
+ //! which looks much nicer. Because of these observations, the author
+ //! of this library feels justified to use `unpack` instead of `apply`,
+ //! and to use a sane parameter order.
+ //!
+ //! [1]: http://en.cppreference.com/w/cpp/experimental/apply
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto unpack = [](auto&& xs, auto&& f) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename = void>
+ struct unpack_impl : unpack_impl<T, when<true>> { };
+
+ struct unpack_t {
+ template <typename Xs, typename F>
+ constexpr decltype(auto) operator()(Xs&& xs, F&& f) const;
+ };
+
+ constexpr unpack_t unpack{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_UNPACK_HPP
diff --git a/boost/hana/fwd/value.hpp b/boost/hana/fwd/value.hpp
new file mode 100644
index 0000000000..4a64507c7b
--- /dev/null
+++ b/boost/hana/fwd/value.hpp
@@ -0,0 +1,100 @@
+/*!
+@file
+Forward declares `boost::hana::value`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_VALUE_HPP
+#define BOOST_HANA_FWD_VALUE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Return the compile-time value associated to a constant.
+ //! @ingroup group-Constant
+ //!
+ //! This function returns the value associated to a `Constant`. That
+ //! value is always a constant expression. The normal way of using
+ //! `value` on an object `c` is
+ //! @code
+ //! constexpr auto result = hana::value<decltype(c)>();
+ //! @endcode
+ //!
+ //! However, for convenience, an overload of `value` is provided so that
+ //! it can be called as:
+ //! @code
+ //! constexpr auto result = hana::value(c);
+ //! @endcode
+ //!
+ //! This overload works by taking a `const&` to its argument, and then
+ //! forwarding to the first version of `value`. Since it does not use
+ //! its argument, the result can still be a constant expression, even
+ //! if the argument is not a constant expression.
+ //!
+ //! @note
+ //! `value<T>()` is tag-dispatched as `value_impl<C>::%apply<T>()`, where
+ //! `C` is the tag of `T`.
+ //!
+ //! @note
+ //! `hana::value` is an overloaded function, not a function object.
+ //! Hence, it can't be passed to higher-order algorithms. If you need
+ //! an equivalent function object, use `hana::value_of` instead.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/value.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename T>
+ constexpr auto value = []() -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename C, typename = void>
+ struct value_impl : value_impl<C, when<true>> { };
+
+ template <typename T>
+ constexpr decltype(auto) value();
+
+ template <typename T>
+ constexpr decltype(auto) value(T const&)
+ { return hana::value<T>(); }
+#endif
+
+ //! Equivalent to `value`, but can be passed to higher-order algorithms.
+ //! @ingroup group-Constant
+ //!
+ //! This function object is equivalent to `value`, except it can be passed
+ //! to higher order algorithms because it is a function object. `value`
+ //! can't be passed to higher-order algorithms because it is implemented
+ //! as an overloaded function.
+ //!
+ //! @note
+ //! This function is a simple alias to `value`, and hence it is not
+ //! tag-dispatched and can't be customized.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/value_of.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto value_of = [](auto const& c) -> decltype(auto) {
+ return hana::value(c);
+ };
+#else
+ struct value_of_t {
+ template <typename T>
+ constexpr decltype(auto) operator()(T const&) const
+ { return hana::value<T>(); }
+ };
+
+ constexpr value_of_t value_of{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_VALUE_HPP
diff --git a/boost/hana/fwd/while.hpp b/boost/hana/fwd/while.hpp
new file mode 100644
index 0000000000..e9efc4464d
--- /dev/null
+++ b/boost/hana/fwd/while.hpp
@@ -0,0 +1,71 @@
+/*!
+@file
+Forward declares `boost::hana::while_`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_WHILE_HPP
+#define BOOST_HANA_FWD_WHILE_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Apply a function to an initial state while some predicate is satisfied.
+ //! @ingroup group-Logical
+ //!
+ //! This method is a natural extension of the `while` language construct
+ //! to manipulate a state whose type may change from one iteration to
+ //! another. However, note that having a state whose type changes from
+ //! one iteration to the other is only possible as long as the predicate
+ //! returns a `Logical` whose truth value is known at compile-time.
+ //!
+ //! Specifically, `while_(pred, state, f)` is equivalent to
+ //! @code
+ //! f(...f(f(state)))
+ //! @endcode
+ //! where `f` is iterated as long as `pred(f(...))` is a true-valued
+ //! `Logical`.
+ //!
+ //!
+ //! @param pred
+ //! A predicate called on the state or on the result of applying `f` a
+ //! certain number of times to the state, and returning whether `f`
+ //! should be applied one more time.
+ //!
+ //! @param state
+ //! The initial state on which `f` is applied.
+ //!
+ //! @param f
+ //! A function that is iterated on the initial state. Note that the
+ //! return type of `f` may change from one iteration to the other,
+ //! but only while `pred` returns a compile-time `Logical`. In other
+ //! words, `decltype(f(stateN))` may differ from `decltype(f(stateN+1))`,
+ //! but only if `pred(f(stateN))` returns a compile-time `Logical`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/while.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto while_ = [](auto&& pred, auto&& state, auto&& f) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename L, typename = void>
+ struct while_impl : while_impl<L, when<true>> { };
+
+ struct while_t {
+ template <typename Pred, typename State, typename F>
+ constexpr decltype(auto) operator()(Pred&& pred, State&& state, F&& f) const;
+ };
+
+ constexpr while_t while_{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_WHILE_HPP
diff --git a/boost/hana/fwd/zero.hpp b/boost/hana/fwd/zero.hpp
new file mode 100644
index 0000000000..dc35dd4d6d
--- /dev/null
+++ b/boost/hana/fwd/zero.hpp
@@ -0,0 +1,45 @@
+/*!
+@file
+Forward declares `boost::hana::zero`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_ZERO_HPP
+#define BOOST_HANA_FWD_ZERO_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Identity of `plus`.
+ //! @ingroup group-Monoid
+ //!
+ //! @tparam M
+ //! The tag (a `Monoid`) of the returned identity.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/zero.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <typename M>
+ constexpr auto zero = []() -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename M, typename = void>
+ struct zero_impl : zero_impl<M, when<true>> { };
+
+ template <typename M>
+ struct zero_t;
+
+ template <typename M>
+ constexpr zero_t<M> zero{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_ZERO_HPP
diff --git a/boost/hana/fwd/zip.hpp b/boost/hana/fwd/zip.hpp
new file mode 100644
index 0000000000..e5d1c8d178
--- /dev/null
+++ b/boost/hana/fwd/zip.hpp
@@ -0,0 +1,61 @@
+/*!
+@file
+Forward declares `boost::hana::zip`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_ZIP_HPP
+#define BOOST_HANA_FWD_ZIP_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Zip one sequence or more.
+ //! @ingroup group-Sequence
+ //!
+ //! Given `n` sequences `s1, ..., sn`, `zip` produces a sequence whose
+ //! `i`-th element is a tuple of `(s1[i], ..., sn[i])`, where `sk[i]`
+ //! denotes the `i`-th element of the `k`-th sequence. In other words,
+ //! `zip` produces a sequence of the form
+ //! @code
+ //! [
+ //! make_tuple(s1[0], ..., sn[0]),
+ //! make_tuple(s1[1], ..., sn[1]),
+ //! ...
+ //! make_tuple(s1[M], ..., sn[M])
+ //! ]
+ //! @endcode
+ //! where `M` is the length of the sequences, which are all assumed to
+ //! have the same length. Assuming the sequences to all have the same size
+ //! allows the library to perform some optimizations. To zip sequences
+ //! that may have different lengths, `zip_shortest` should be used
+ //! instead. Also note that it is an error to provide no sequence at all,
+ //! i.e. `zip` expects at least one sequence.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/zip.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto zip = [](auto&& x1, ..., auto&& xn) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct zip_impl : zip_impl<S, when<true>> { };
+
+ struct zip_t {
+ template <typename Xs, typename ...Ys>
+ constexpr auto operator()(Xs&& xs, Ys&& ...ys) const;
+ };
+
+ constexpr zip_t zip{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_ZIP_HPP
diff --git a/boost/hana/fwd/zip_shortest.hpp b/boost/hana/fwd/zip_shortest.hpp
new file mode 100644
index 0000000000..33dbd6220b
--- /dev/null
+++ b/boost/hana/fwd/zip_shortest.hpp
@@ -0,0 +1,61 @@
+/*!
+@file
+Forward declares `boost::hana::zip_shortest`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_ZIP_SHORTEST_HPP
+#define BOOST_HANA_FWD_ZIP_SHORTEST_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Zip one sequence or more.
+ //! @ingroup group-Sequence
+ //!
+ //! Given `n` sequences `s1, ..., sn`, `zip_shortest` produces a sequence
+ //! whose `i`-th element is a tuple of `(s1[i], ..., sn[i])`, where `sk[i]`
+ //! denotes the `i`-th element of the `k`-th sequence. In other words,
+ //! `zip_shortest` produces a sequence of the form
+ //! @code
+ //! [
+ //! make_tuple(s1[0], ..., sn[0]),
+ //! make_tuple(s1[1], ..., sn[1]),
+ //! ...
+ //! make_tuple(s1[M], ..., sn[M])
+ //! ]
+ //! @endcode
+ //! where `M` is the length of the shortest sequence. Hence, the returned
+ //! sequence stops when the shortest input sequence is exhausted. If you
+ //! know that all the sequences you are about to zip have the same length,
+ //! you should use `zip` instead, since it can be more optimized. Also
+ //! note that it is an error to provide no sequence at all, i.e.
+ //! `zip_shortest` expects at least one sequence.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/zip_shortest.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto zip_shortest = [](auto&& x1, ..., auto&& xn) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct zip_shortest_impl : zip_shortest_impl<S, when<true>> { };
+
+ struct zip_shortest_t {
+ template <typename Xs, typename ...Ys>
+ constexpr auto operator()(Xs&& xs, Ys&& ...ys) const;
+ };
+
+ constexpr zip_shortest_t zip_shortest{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_ZIP_SHORTEST_HPP
diff --git a/boost/hana/fwd/zip_shortest_with.hpp b/boost/hana/fwd/zip_shortest_with.hpp
new file mode 100644
index 0000000000..65c2e2acda
--- /dev/null
+++ b/boost/hana/fwd/zip_shortest_with.hpp
@@ -0,0 +1,62 @@
+/*!
+@file
+Forward declares `boost::hana::zip_shortest_with`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_ZIP_SHORTEST_WITH_HPP
+#define BOOST_HANA_FWD_ZIP_SHORTEST_WITH_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Zip one sequence or more with a given function.
+ //! @ingroup group-Sequence
+ //!
+ //! Given a `n`-ary function `f` and `n` sequences `s1, ..., sn`,
+ //! `zip_shortest_with` produces a sequence whose `i`-th element is
+ //! `f(s1[i], ..., sn[i])`, where `sk[i]` denotes the `i`-th element of
+ //! the `k`-th sequence. In other words, `zip_shortest_with` produces a
+ //! sequence of the form
+ //! @code
+ //! [
+ //! f(s1[0], ..., sn[0]),
+ //! f(s1[1], ..., sn[1]),
+ //! ...
+ //! f(s1[M], ..., sn[M])
+ //! ]
+ //! @endcode
+ //! where `M` is the length of the shortest sequence. Hence, the returned
+ //! sequence stops when the shortest input sequence is exhausted. If you
+ //! know that all the sequences you are about to zip have the same length,
+ //! you should use `zip_with` instead, since it can be more optimized.
+ //! Also note that it is an error to provide no sequence at all, i.e.
+ //! `zip_shortest_with` expects at least one sequence.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/zip_shortest_with.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto zip_shortest_with = [](auto&& f, auto&& x1, ..., auto&& xn) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct zip_shortest_with_impl : zip_shortest_with_impl<S, when<true>> { };
+
+ struct zip_shortest_with_t {
+ template <typename F, typename Xs, typename ...Ys>
+ constexpr auto operator()(F&& f, Xs&& xs, Ys&& ...ys) const;
+ };
+
+ constexpr zip_shortest_with_t zip_shortest_with{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_ZIP_SHORTEST_WITH_HPP
diff --git a/boost/hana/fwd/zip_with.hpp b/boost/hana/fwd/zip_with.hpp
new file mode 100644
index 0000000000..19dd314aa6
--- /dev/null
+++ b/boost/hana/fwd/zip_with.hpp
@@ -0,0 +1,62 @@
+/*!
+@file
+Forward declares `boost::hana::zip_with`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_FWD_ZIP_WITH_HPP
+#define BOOST_HANA_FWD_ZIP_WITH_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Zip one sequence or more with a given function.
+ //! @ingroup group-Sequence
+ //!
+ //! Given a `n`-ary function `f` and `n` sequences `s1, ..., sn`,
+ //! `zip_with` produces a sequence whose `i`-th element is
+ //! `f(s1[i], ..., sn[i])`, where `sk[i]` denotes the `i`-th element of
+ //! the `k`-th sequence. In other words, `zip_with` produces a sequence
+ //! of the form
+ //! @code
+ //! [
+ //! f(s1[0], ..., sn[0]),
+ //! f(s1[1], ..., sn[1]),
+ //! ...
+ //! f(s1[M], ..., sn[M])
+ //! ]
+ //! @endcode
+ //! where `M` is the length of the sequences, which are all assumed to
+ //! have the same length. Assuming the sequences to all have the same size
+ //! allows the library to perform some optimizations. To zip sequences
+ //! that may have different lengths, `zip_shortest_with` should be used
+ //! instead. Also note that it is an error to provide no sequence at all,
+ //! i.e. `zip_with` expects at least one sequence.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/zip_with.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto zip_with = [](auto&& f, auto&& x1, ..., auto&& xn) {
+ return tag-dispatched;
+ };
+#else
+ template <typename S, typename = void>
+ struct zip_with_impl : zip_with_impl<S, when<true>> { };
+
+ struct zip_with_t {
+ template <typename F, typename Xs, typename ...Ys>
+ constexpr auto operator()(F&& f, Xs&& xs, Ys&& ...ys) const;
+ };
+
+ constexpr zip_with_t zip_with{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_ZIP_WITH_HPP
diff --git a/boost/hana/greater.hpp b/boost/hana/greater.hpp
new file mode 100644
index 0000000000..ee75bb806a
--- /dev/null
+++ b/boost/hana/greater.hpp
@@ -0,0 +1,71 @@
+/*!
+@file
+Defines `boost::hana::greater`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_GREATER_HPP
+#define BOOST_HANA_GREATER_HPP
+
+#include <boost/hana/fwd/greater.hpp>
+
+#include <boost/hana/concept/orderable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/common.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/concepts.hpp>
+#include <boost/hana/detail/has_common_embedding.hpp>
+#include <boost/hana/detail/nested_than.hpp> // required by fwd decl
+#include <boost/hana/if.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename X, typename Y>
+ constexpr decltype(auto) greater_t::operator()(X&& x, Y&& y) const {
+ using T = typename hana::tag_of<X>::type;
+ using U = typename hana::tag_of<Y>::type;
+ using Greater = BOOST_HANA_DISPATCH_IF(decltype(greater_impl<T, U>{}),
+ hana::Orderable<T>::value &&
+ hana::Orderable<U>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Orderable<T>::value,
+ "hana::greater(x, y) requires 'x' to be Orderable");
+
+ static_assert(hana::Orderable<U>::value,
+ "hana::greater(x, y) requires 'y' to be Orderable");
+ #endif
+
+ return Greater::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
+ }
+ //! @endcond
+ template <typename T, typename U, bool condition>
+ struct greater_impl<T, U, when<condition>> : default_ {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y) {
+ return hana::less(static_cast<Y&&>(y),
+ static_cast<X&&>(x));
+ }
+ };
+
+ // Cross-type overload
+ template <typename T, typename U>
+ struct greater_impl<T, U, when<
+ detail::has_nontrivial_common_embedding<Orderable, T, U>::value
+ >> {
+ using C = typename hana::common<T, U>::type;
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y) {
+ return hana::greater(hana::to<C>(static_cast<X&&>(x)),
+ hana::to<C>(static_cast<Y&&>(y)));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_GREATER_HPP
diff --git a/boost/hana/greater_equal.hpp b/boost/hana/greater_equal.hpp
new file mode 100644
index 0000000000..116c890b49
--- /dev/null
+++ b/boost/hana/greater_equal.hpp
@@ -0,0 +1,74 @@
+/*!
+@file
+Defines `boost::hana::greater_equal`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_GREATER_EQUAL_HPP
+#define BOOST_HANA_GREATER_EQUAL_HPP
+
+#include <boost/hana/fwd/greater_equal.hpp>
+
+#include <boost/hana/concept/orderable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/common.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/concepts.hpp>
+#include <boost/hana/detail/has_common_embedding.hpp>
+#include <boost/hana/detail/nested_than.hpp> // required by fwd decl
+#include <boost/hana/if.hpp>
+#include <boost/hana/not.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename X, typename Y>
+ constexpr decltype(auto) greater_equal_t::operator()(X&& x, Y&& y) const {
+ using T = typename hana::tag_of<X>::type;
+ using U = typename hana::tag_of<Y>::type;
+ using GreaterEqual = BOOST_HANA_DISPATCH_IF(
+ decltype(greater_equal_impl<T, U>{}),
+ hana::Orderable<T>::value &&
+ hana::Orderable<U>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Orderable<T>::value,
+ "hana::greater_equal(x, y) requires 'x' to be Orderable");
+
+ static_assert(hana::Orderable<U>::value,
+ "hana::greater_equal(x, y) requires 'y' to be Orderable");
+ #endif
+
+ return GreaterEqual::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
+ }
+ //! @endcond
+
+ template <typename T, typename U, bool condition>
+ struct greater_equal_impl<T, U, when<condition>> : default_ {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X x, Y y) {
+ return hana::not_(hana::less(static_cast<X&&>(x),
+ static_cast<Y&&>(y)));
+ }
+ };
+
+ // Cross-type overload
+ template <typename T, typename U>
+ struct greater_equal_impl<T, U, when<
+ detail::has_nontrivial_common_embedding<Orderable, T, U>::value
+ >> {
+ using C = typename hana::common<T, U>::type;
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y) {
+ return hana::greater_equal(hana::to<C>(static_cast<X&&>(x)),
+ hana::to<C>(static_cast<Y&&>(y)));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_GREATER_EQUAL_HPP
diff --git a/boost/hana/group.hpp b/boost/hana/group.hpp
new file mode 100644
index 0000000000..66f005a347
--- /dev/null
+++ b/boost/hana/group.hpp
@@ -0,0 +1,157 @@
+/*!
+@file
+Defines `boost::hana::group`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_GROUP_HPP
+#define BOOST_HANA_GROUP_HPP
+
+#include <boost/hana/fwd/group.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/detail/algorithm.hpp>
+#include <boost/hana/detail/array.hpp>
+#include <boost/hana/detail/nested_by.hpp> // required by fwd decl
+#include <boost/hana/equal.hpp>
+#include <boost/hana/length.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs>
+ constexpr auto group_t::operator()(Xs&& xs) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Group = BOOST_HANA_DISPATCH_IF(group_impl<S>,
+ hana::Sequence<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::group(xs) requires 'xs' to be a Sequence");
+ #endif
+
+ return Group::apply(static_cast<Xs&&>(xs));
+ }
+
+ template <typename Xs, typename Predicate>
+ constexpr auto group_t::operator()(Xs&& xs, Predicate&& pred) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Group = BOOST_HANA_DISPATCH_IF(group_impl<S>,
+ hana::Sequence<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::group(xs, predicate) requires 'xs' to be a Sequence");
+ #endif
+
+ return Group::apply(static_cast<Xs&&>(xs),
+ static_cast<Predicate&&>(pred));
+ }
+ //! @endcond
+
+ namespace detail {
+ template <typename Xs, std::size_t ...i>
+ constexpr auto get_subsequence_(Xs&& xs, std::index_sequence<i...>) {
+ using S = typename hana::tag_of<Xs>::type;
+ return hana::make<S>(hana::at_c<i>(static_cast<Xs&&>(xs))...);
+ }
+
+ template <std::size_t offset, typename Indices>
+ struct offset_by;
+
+ template <std::size_t offset, std::size_t ...i>
+ struct offset_by<offset, std::index_sequence<i...>> {
+ using type = std::index_sequence<(offset + i)...>;
+ };
+
+ template <bool ...b>
+ struct group_indices {
+ static constexpr bool bs[] = {b...};
+ static constexpr std::size_t n_groups =
+ detail::count(bs, bs + sizeof(bs), false) + 1;
+
+ static constexpr auto compute_info() {
+ detail::array<std::size_t, n_groups> sizes{}, offsets{};
+ for (std::size_t g = 0, i = 0, offset = 0; g < n_groups; ++g) {
+ offsets[g] = offset;
+
+ sizes[g] = 1;
+ while (i < sizeof...(b) && bs[i++])
+ ++sizes[g];
+
+ offset += sizes[g];
+ }
+ return std::make_pair(offsets, sizes);
+ }
+
+ static constexpr auto info = compute_info();
+ static constexpr auto offsets = info.first;
+ static constexpr auto group_sizes = info.second;
+
+ template <typename S, typename Xs, std::size_t ...i>
+ static constexpr auto finish(Xs&& xs, std::index_sequence<i...>) {
+ return hana::make<S>(
+ detail::get_subsequence_(
+ static_cast<Xs&&>(xs),
+ typename offset_by<
+ offsets[i], std::make_index_sequence<group_sizes[i]>
+ >::type{}
+ )...
+ );
+ }
+ };
+ } // end namespace detail
+
+ template <typename S, bool condition>
+ struct group_impl<S, when<condition>> : default_ {
+ template <typename Xs, typename Pred, std::size_t ...i>
+ static constexpr auto
+ group_helper(Xs&& xs, Pred&& pred, std::index_sequence<0, i...>) {
+ using info = detail::group_indices<static_cast<bool>(decltype(
+ pred(hana::at_c<i - 1>(static_cast<Xs&&>(xs)),
+ hana::at_c<i>(static_cast<Xs&&>(xs)))
+ )::value)...>;
+ return info::template finish<S>(static_cast<Xs&&>(xs),
+ std::make_index_sequence<info::n_groups>{}
+ );
+ }
+
+ template <typename Xs, typename Pred>
+ static constexpr auto
+ group_helper(Xs&& xs, Pred&&, std::index_sequence<0>) {
+ return hana::make<S>(static_cast<Xs&&>(xs));
+ }
+
+ template <typename Xs, typename Pred>
+ static constexpr auto
+ group_helper(Xs&&, Pred&&, std::index_sequence<>) {
+ return hana::make<S>();
+ }
+
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs&& xs, Pred&& pred) {
+ constexpr std::size_t len = decltype(hana::length(xs))::value;
+ return group_helper(static_cast<Xs&&>(xs),
+ static_cast<Pred&&>(pred),
+ std::make_index_sequence<len>{});
+ }
+
+ template <typename Xs>
+ static constexpr auto apply(Xs&& xs)
+ { return group_impl::apply(static_cast<Xs&&>(xs), hana::equal); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_GROUP_HPP
diff --git a/boost/hana/hash.hpp b/boost/hana/hash.hpp
new file mode 100644
index 0000000000..538ef36eca
--- /dev/null
+++ b/boost/hana/hash.hpp
@@ -0,0 +1,114 @@
+/*!
+@file
+Defines `boost::hana::hash`.
+
+@copyright Jason Rice 2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_HASH_HPP
+#define BOOST_HANA_HASH_HPP
+
+#include <boost/hana/fwd/hash.hpp>
+
+#include <boost/hana/concept/hashable.hpp>
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/fwd/integral_constant.hpp>
+#include <boost/hana/type.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename X>
+ constexpr auto hash_t::operator()(X const& x) const {
+ using Tag = typename hana::tag_of<X>::type;
+ using Hash = BOOST_HANA_DISPATCH_IF(hash_impl<Tag>,
+ hana::Hashable<Tag>::value
+ );
+
+#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Hashable<Tag>::value,
+ "hana::hash(x) requires 'x' to be Hashable");
+#endif
+
+ return Hash::apply(x);
+ }
+ //! @endcond
+
+ template <typename Tag, bool condition>
+ struct hash_impl<Tag, when<condition>> : default_ {
+ template <typename X>
+ static constexpr auto apply(X const&) = delete;
+ };
+
+ namespace detail {
+ template <typename T, typename = void>
+ struct hash_integral_helper;
+
+ template <typename Member, typename T>
+ struct hash_integral_helper<Member T::*> {
+ template <typename X>
+ static constexpr auto apply(X const&) {
+ return hana::type_c<hana::integral_constant<Member T::*, X::value>>;
+ }
+ };
+
+ template <typename T>
+ struct hash_integral_helper<T,
+ typename std::enable_if<std::is_signed<T>::value>::type
+ > {
+ template <typename X>
+ static constexpr auto apply(X const&) {
+ constexpr signed long long x = X::value;
+ return hana::type_c<hana::integral_constant<signed long long, x>>;
+ }
+ };
+
+ template <typename T>
+ struct hash_integral_helper<T,
+ typename std::enable_if<std::is_unsigned<T>::value>::type
+ > {
+ template <typename X>
+ static constexpr auto apply(X const&) {
+ constexpr unsigned long long x = X::value;
+ return hana::type_c<hana::integral_constant<unsigned long long, x>>;
+ }
+ };
+
+ template <>
+ struct hash_integral_helper<bool> {
+ template <typename X>
+ static constexpr auto apply(X const&) {
+ return hana::type_c<hana::integral_constant<bool, X::value>>;
+ }
+ };
+
+ template <>
+ struct hash_integral_helper<char> {
+ template <typename X>
+ static constexpr auto apply(X const&) {
+ using T = std::conditional<std::is_signed<char>::value,
+ signed long long, unsigned long long
+ >::type;
+ constexpr T x = X::value;
+ return hana::type_c<hana::integral_constant<T, x>>;
+ }
+ };
+ }
+
+ template <typename Tag>
+ struct hash_impl<Tag, when<hana::IntegralConstant<Tag>::value>> {
+ template <typename X>
+ static constexpr auto apply(X const& x) {
+ using T = typename std::remove_cv<decltype(X::value)>::type;
+ return detail::hash_integral_helper<T>::apply(x);
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_HASH_HPP
diff --git a/boost/hana/if.hpp b/boost/hana/if.hpp
new file mode 100644
index 0000000000..f65b514be7
--- /dev/null
+++ b/boost/hana/if.hpp
@@ -0,0 +1,61 @@
+/*!
+@file
+Defines `boost::hana::if_`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_IF_HPP
+#define BOOST_HANA_IF_HPP
+
+#include <boost/hana/fwd/if.hpp>
+
+#include <boost/hana/concept/logical.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/eval_if.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Cond, typename Then, typename Else>
+ constexpr decltype(auto) if_t::operator()(Cond&& cond, Then&& then, Else&& else_) const {
+ using Bool = typename hana::tag_of<Cond>::type;
+ using If = BOOST_HANA_DISPATCH_IF(if_impl<Bool>,
+ hana::Logical<Bool>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Logical<Bool>::value,
+ "hana::if_(cond, then, else) requires 'cond' to be a Logical");
+ #endif
+
+ return If::apply(static_cast<Cond&&>(cond),
+ static_cast<Then&&>(then),
+ static_cast<Else&&>(else_));
+ }
+ //! @endcond
+
+ namespace detail {
+ template <typename T>
+ struct hold {
+ T value;
+ constexpr T&& operator()() && { return static_cast<T&&>(value); }
+ };
+ }
+
+ template <typename L, bool condition>
+ struct if_impl<L, when<condition>> : default_ {
+ template <typename C, typename T, typename E>
+ static constexpr auto apply(C&& c, T&& t, E&& e) {
+ return hana::eval_if(static_cast<C&&>(c),
+ detail::hold<T&&>{static_cast<T&&>(t)},
+ detail::hold<E&&>{static_cast<E&&>(e)}
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_IF_HPP
diff --git a/boost/hana/insert.hpp b/boost/hana/insert.hpp
new file mode 100644
index 0000000000..706549c5d6
--- /dev/null
+++ b/boost/hana/insert.hpp
@@ -0,0 +1,52 @@
+/*!
+@file
+Defines `boost::hana::insert`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_INSERT_HPP
+#define BOOST_HANA_INSERT_HPP
+
+#include <boost/hana/fwd/insert.hpp>
+
+#include <boost/hana/append.hpp>
+#include <boost/hana/concat.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/drop_front.hpp>
+#include <boost/hana/take_front.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Set, typename ...Args>
+ constexpr decltype(auto) insert_t::operator()(Set&& set, Args&& ...args) const {
+ return insert_impl<typename hana::tag_of<Set>::type>::apply(
+ static_cast<Set&&>(set),
+ static_cast<Args&&>(args)...
+ );
+ }
+ //! @endcond
+
+ template <typename T, bool condition>
+ struct insert_impl<T, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+
+ template <typename S>
+ struct insert_impl<S, when<Sequence<S>::value>> {
+ template <typename Xs, typename N, typename Element>
+ static constexpr auto apply(Xs&& xs, N const& n, Element&& e) {
+ return hana::concat(hana::append(hana::take_front(xs, n),
+ static_cast<Element&&>(e)),
+ hana::drop_front(xs, n));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_INSERT_HPP
diff --git a/boost/hana/insert_range.hpp b/boost/hana/insert_range.hpp
new file mode 100644
index 0000000000..a5e86a51a5
--- /dev/null
+++ b/boost/hana/insert_range.hpp
@@ -0,0 +1,64 @@
+/*!
+@file
+Defines `boost::hana::insert_range`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_INSERT_RANGE_HPP
+#define BOOST_HANA_INSERT_RANGE_HPP
+
+#include <boost/hana/fwd/insert_range.hpp>
+
+#include <boost/hana/concat.hpp>
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/drop_front.hpp>
+#include <boost/hana/take_front.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename N, typename Elements>
+ constexpr auto insert_range_t::operator()(Xs&& xs, N&& n, Elements&& elements) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using InsertRange = BOOST_HANA_DISPATCH_IF(insert_range_impl<S>,
+ hana::Sequence<Xs>::value &&
+ hana::Foldable<Elements>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<Xs>::value,
+ "hana::insert_range(xs, n, elements) requires 'xs' to be a Sequence");
+
+ static_assert(hana::Foldable<Elements>::value,
+ "hana::insert_range(xs, n, elements) requires 'elements' to be a Foldable");
+ #endif
+
+ return InsertRange::apply(static_cast<Xs&&>(xs),
+ static_cast<N&&>(n),
+ static_cast<Elements&&>(elements));
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct insert_range_impl<S, when<condition>> {
+ template <typename Xs, typename N, typename Elements>
+ static constexpr auto apply(Xs&& xs, N const& n, Elements&& e) {
+ return hana::concat(
+ hana::concat(
+ hana::take_front(xs, n),
+ hana::to<S>(static_cast<Elements&&>(e))
+ ),
+ hana::drop_front(xs, n)
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_INSERT_RANGE_HPP
diff --git a/boost/hana/integral_constant.hpp b/boost/hana/integral_constant.hpp
new file mode 100644
index 0000000000..2d8f4df7ca
--- /dev/null
+++ b/boost/hana/integral_constant.hpp
@@ -0,0 +1,15 @@
+/*!
+@file
+Defines `boost::hana::integral_constant`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_INTEGRAL_CONSTANT_HPP
+#define BOOST_HANA_INTEGRAL_CONSTANT_HPP
+
+#include <boost/hana/bool.hpp>
+
+#endif // !BOOST_HANA_INTEGRAL_CONSTANT_HPP
diff --git a/boost/hana/intersection.hpp b/boost/hana/intersection.hpp
new file mode 100644
index 0000000000..16d7d211be
--- /dev/null
+++ b/boost/hana/intersection.hpp
@@ -0,0 +1,39 @@
+/*!
+@file
+Defines `boost::hana::intersection`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_INTERSECTION_HPP
+#define BOOST_HANA_INTERSECTION_HPP
+
+#include <boost/hana/fwd/intersection.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Ys>
+ constexpr auto intersection_t::operator()(Xs&& xs, Ys&& ys) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Intersection = BOOST_HANA_DISPATCH_IF(intersection_impl<S>,
+ true
+ );
+
+ return Intersection::apply(static_cast<Xs&&>(xs), static_cast<Ys&&>(ys));
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct intersection_impl<S, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_INTERSECTION_HPP
diff --git a/boost/hana/intersperse.hpp b/boost/hana/intersperse.hpp
new file mode 100644
index 0000000000..2ef8eb329c
--- /dev/null
+++ b/boost/hana/intersperse.hpp
@@ -0,0 +1,76 @@
+/*!
+@file
+Defines `boost::hana::intersperse`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_INTERSPERSE_HPP
+#define BOOST_HANA_INTERSPERSE_HPP
+
+#include <boost/hana/fwd/intersperse.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/length.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Z>
+ constexpr auto intersperse_t::operator()(Xs&& xs, Z&& z) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Intersperse = BOOST_HANA_DISPATCH_IF(intersperse_impl<S>,
+ hana::Sequence<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::intersperse(xs, z) requires 'xs' to be a Sequence");
+ #endif
+
+ return Intersperse::apply(static_cast<Xs&&>(xs), static_cast<Z&&>(z));
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct intersperse_impl<S, when<condition>> : default_ {
+ template <std::size_t i, typename Xs, typename Z>
+ static constexpr decltype(auto)
+ pick(Xs&&, Z&& z, hana::false_ /* odd index */)
+ { return static_cast<Z&&>(z); }
+
+ template <std::size_t i, typename Xs, typename Z>
+ static constexpr decltype(auto)
+ pick(Xs&& xs, Z&&, hana::true_ /* even index */)
+ { return hana::at_c<(i + 1) / 2>(static_cast<Xs&&>(xs)); }
+
+ template <typename Xs, typename Z, std::size_t ...i>
+ static constexpr auto
+ intersperse_helper(Xs&& xs, Z&& z, std::index_sequence<i...>) {
+ return hana::make<S>(
+ pick<i>(static_cast<Xs&&>(xs), static_cast<Z&&>(z),
+ hana::bool_c<(i % 2 == 0)>)...
+ );
+ }
+
+ template <typename Xs, typename Z>
+ static constexpr auto apply(Xs&& xs, Z&& z) {
+ constexpr std::size_t size = decltype(hana::length(xs))::value;
+ constexpr std::size_t new_size = size == 0 ? 0 : (size * 2) - 1;
+ return intersperse_helper(static_cast<Xs&&>(xs), static_cast<Z&&>(z),
+ std::make_index_sequence<new_size>{});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_INTERSPERSE_HPP
diff --git a/boost/hana/is_disjoint.hpp b/boost/hana/is_disjoint.hpp
new file mode 100644
index 0000000000..dcea16c89b
--- /dev/null
+++ b/boost/hana/is_disjoint.hpp
@@ -0,0 +1,65 @@
+/*!
+@file
+Defines `boost::hana::is_disjoint`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_IS_DISJOINT_HPP
+#define BOOST_HANA_IS_DISJOINT_HPP
+
+#include <boost/hana/fwd/is_disjoint.hpp>
+
+#include <boost/hana/concept/searchable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/contains.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/none_of.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Ys>
+ constexpr auto is_disjoint_t::operator()(Xs&& xs, Ys&& ys) const {
+ using S1 = typename hana::tag_of<Xs>::type;
+ using S2 = typename hana::tag_of<Ys>::type;
+ using IsDisjoint = BOOST_HANA_DISPATCH_IF(
+ decltype(is_disjoint_impl<S1, S2>{}),
+ hana::Searchable<S1>::value &&
+ hana::Searchable<S2>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Searchable<S1>::value,
+ "hana::is_disjoint(xs, ys) requires 'xs' to be Searchable");
+
+ static_assert(hana::Searchable<S2>::value,
+ "hana::is_disjoint(xs, ys) requires 'ys' to be Searchable");
+ #endif
+
+ return IsDisjoint::apply(static_cast<Xs&&>(xs), static_cast<Ys&&>(ys));
+ }
+ //! @endcond
+
+ namespace detail {
+ template <typename Ys>
+ struct in_by_reference {
+ Ys const& ys;
+ template <typename X>
+ constexpr auto operator()(X const& x) const
+ { return hana::contains(ys, x); }
+ };
+ }
+
+ template <typename S1, typename S2, bool condition>
+ struct is_disjoint_impl<S1, S2, when<condition>> : default_ {
+ template <typename Xs, typename Ys>
+ static constexpr auto apply(Xs const& xs, Ys const& ys) {
+ return hana::none_of(xs, detail::in_by_reference<Ys>{ys});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_IS_DISJOINT_HPP
diff --git a/boost/hana/is_empty.hpp b/boost/hana/is_empty.hpp
new file mode 100644
index 0000000000..ac1051914b
--- /dev/null
+++ b/boost/hana/is_empty.hpp
@@ -0,0 +1,45 @@
+/*!
+@file
+Defines `boost::hana::is_empty`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_IS_EMPTY_HPP
+#define BOOST_HANA_IS_EMPTY_HPP
+
+#include <boost/hana/fwd/is_empty.hpp>
+
+#include <boost/hana/concept/iterable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs>
+ constexpr auto is_empty_t::operator()(Xs const& xs) const {
+ using It = typename hana::tag_of<Xs>::type;
+ using IsEmpty = BOOST_HANA_DISPATCH_IF(is_empty_impl<It>,
+ hana::Iterable<It>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Iterable<It>::value,
+ "hana::is_empty(xs) requires 'xs' to be an Iterable");
+ #endif
+
+ return IsEmpty::apply(xs);
+ }
+ //! @endcond
+
+ template <typename It, bool condition>
+ struct is_empty_impl<It, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_IS_EMPTY_HPP
diff --git a/boost/hana/is_subset.hpp b/boost/hana/is_subset.hpp
new file mode 100644
index 0000000000..546bc9baa5
--- /dev/null
+++ b/boost/hana/is_subset.hpp
@@ -0,0 +1,84 @@
+/*!
+@file
+Defines `boost::hana::is_subset`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_IS_SUBSET_HPP
+#define BOOST_HANA_IS_SUBSET_HPP
+
+#include <boost/hana/fwd/is_subset.hpp>
+
+#include <boost/hana/all_of.hpp>
+#include <boost/hana/concept/searchable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/contains.hpp>
+#include <boost/hana/core/common.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/has_common_embedding.hpp>
+#include <boost/hana/functional/partial.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Ys>
+ constexpr auto is_subset_t::operator()(Xs&& xs, Ys&& ys) const {
+ using S1 = typename hana::tag_of<Xs>::type;
+ using S2 = typename hana::tag_of<Ys>::type;
+ using IsSubset = BOOST_HANA_DISPATCH_IF(
+ decltype(is_subset_impl<S1, S2>{}),
+ hana::Searchable<S1>::value &&
+ hana::Searchable<S2>::value &&
+ !is_default<is_subset_impl<S1, S2>>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Searchable<S1>::value,
+ "hana::is_subset(xs, ys) requires 'xs' to be Searchable");
+
+ static_assert(hana::Searchable<S2>::value,
+ "hana::is_subset(xs, ys) requires 'ys' to be Searchable");
+
+ static_assert(!is_default<is_subset_impl<S1, S2>>::value,
+ "hana::is_subset(xs, ys) requires 'xs' and 'ys' to be embeddable "
+ "in a common Searchable");
+ #endif
+
+ return IsSubset::apply(static_cast<Xs&&>(xs), static_cast<Ys&&>(ys));
+ }
+ //! @endcond
+
+ template <typename S1, typename S2, bool condition>
+ struct is_subset_impl<S1, S2, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+
+ template <typename S, bool condition>
+ struct is_subset_impl<S, S, when<condition>> {
+ template <typename Xs, typename Ys>
+ static constexpr decltype(auto) apply(Xs&& xs, Ys&& ys) {
+ return hana::all_of(static_cast<Xs&&>(xs),
+ hana::partial(hana::contains, static_cast<Ys&&>(ys)));
+ }
+ };
+
+ // Cross-type overload
+ template <typename S1, typename S2>
+ struct is_subset_impl<S1, S2, when<
+ detail::has_nontrivial_common_embedding<Searchable, S1, S2>::value
+ >> {
+ using C = typename common<S1, S2>::type;
+ template <typename Xs, typename Ys>
+ static constexpr decltype(auto) apply(Xs&& xs, Ys&& ys) {
+ return hana::is_subset(hana::to<C>(static_cast<Xs&&>(xs)),
+ hana::to<C>(static_cast<Ys&&>(ys)));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_IS_SUBSET_HPP
diff --git a/boost/hana/keys.hpp b/boost/hana/keys.hpp
new file mode 100644
index 0000000000..d6d521b7e2
--- /dev/null
+++ b/boost/hana/keys.hpp
@@ -0,0 +1,48 @@
+/*!
+@file
+Defines `boost::hana::keys`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_KEYS_HPP
+#define BOOST_HANA_KEYS_HPP
+
+#include <boost/hana/fwd/keys.hpp>
+
+#include <boost/hana/accessors.hpp>
+#include <boost/hana/concept/struct.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/first.hpp>
+#include <boost/hana/transform.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Map>
+ constexpr auto keys_t::operator()(Map&& map) const {
+ return keys_impl<typename hana::tag_of<Map>::type>::apply(
+ static_cast<Map&&>(map)
+ );
+ }
+ //! @endcond
+
+ template <typename T, bool condition>
+ struct keys_impl<T, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+
+ template <typename S>
+ struct keys_impl<S, when<hana::Struct<S>::value>> {
+ template <typename Object>
+ static constexpr auto apply(Object const&) {
+ return hana::transform(hana::accessors<S>(), hana::first);
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_KEYS_HPP
diff --git a/boost/hana/lazy.hpp b/boost/hana/lazy.hpp
new file mode 100644
index 0000000000..073fbca5af
--- /dev/null
+++ b/boost/hana/lazy.hpp
@@ -0,0 +1,229 @@
+/*!
+@file
+Defines `boost::hana::lazy`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_LAZY_HPP
+#define BOOST_HANA_LAZY_HPP
+
+#include <boost/hana/fwd/lazy.hpp>
+
+#include <boost/hana/basic_tuple.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/detail/decay.hpp>
+#include <boost/hana/detail/operators/adl.hpp>
+#include <boost/hana/detail/operators/monad.hpp>
+#include <boost/hana/functional/apply.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/functional/on.hpp>
+#include <boost/hana/fwd/ap.hpp>
+#include <boost/hana/fwd/duplicate.hpp>
+#include <boost/hana/fwd/eval.hpp>
+#include <boost/hana/fwd/extend.hpp>
+#include <boost/hana/fwd/extract.hpp>
+#include <boost/hana/fwd/flatten.hpp>
+#include <boost/hana/fwd/lift.hpp>
+#include <boost/hana/fwd/transform.hpp>
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //////////////////////////////////////////////////////////////////////////
+ // lazy
+ //////////////////////////////////////////////////////////////////////////
+ template <typename Indices, typename F, typename ...Args>
+ struct lazy_apply_t;
+
+ namespace detail { struct lazy_secret { }; }
+
+ template <std::size_t ...n, typename F, typename ...Args>
+ struct lazy_apply_t<std::index_sequence<n...>, F, Args...>
+ : detail::operators::adl<>
+ {
+ template <typename ...T>
+ constexpr lazy_apply_t(detail::lazy_secret, T&& ...t)
+ : storage_{static_cast<T&&>(t)...}
+ { }
+
+ basic_tuple<F, Args...> storage_;
+ using hana_tag = lazy_tag;
+ };
+
+ template <typename X>
+ struct lazy_value_t : detail::operators::adl<> {
+ template <typename Y>
+ constexpr lazy_value_t(detail::lazy_secret, Y&& y)
+ : storage_{static_cast<Y&&>(y)}
+ { }
+
+ basic_tuple<X> storage_;
+ using hana_tag = lazy_tag;
+
+ // If this is called, we assume that `X` is in fact a function.
+ template <typename ...Args>
+ constexpr lazy_apply_t<
+ std::make_index_sequence<sizeof...(Args)>,
+ X, typename detail::decay<Args>::type...
+ > operator()(Args&& ...args) const& {
+ return {detail::lazy_secret{},
+ hana::get_impl<0>(storage_), static_cast<Args&&>(args)...};
+ }
+
+ template <typename ...Args>
+ constexpr lazy_apply_t<
+ std::make_index_sequence<sizeof...(Args)>,
+ X, typename detail::decay<Args>::type...
+ > operator()(Args&& ...args) && {
+ return {detail::lazy_secret{},
+ static_cast<X&&>(hana::get_impl<0>(storage_)),
+ static_cast<Args&&>(args)...
+ };
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // make<lazy_tag>
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct make_impl<lazy_tag> {
+ template <typename X>
+ static constexpr lazy_value_t<typename detail::decay<X>::type> apply(X&& x) {
+ return {detail::lazy_secret{}, static_cast<X&&>(x)};
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Operators
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <>
+ struct monad_operators<lazy_tag> { static constexpr bool value = true; };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // eval for lazy_tag
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct eval_impl<lazy_tag> {
+ // lazy_apply_t
+ template <std::size_t ...n, typename F, typename ...Args>
+ static constexpr decltype(auto)
+ apply(lazy_apply_t<std::index_sequence<n...>, F, Args...> const& expr) {
+ return hana::get_impl<0>(expr.storage_)(
+ hana::get_impl<n+1>(expr.storage_)...
+ );
+ }
+
+ template <std::size_t ...n, typename F, typename ...Args>
+ static constexpr decltype(auto)
+ apply(lazy_apply_t<std::index_sequence<n...>, F, Args...>& expr) {
+ return hana::get_impl<0>(expr.storage_)(
+ hana::get_impl<n+1>(expr.storage_)...
+ );
+ }
+
+ template <std::size_t ...n, typename F, typename ...Args>
+ static constexpr decltype(auto)
+ apply(lazy_apply_t<std::index_sequence<n...>, F, Args...>&& expr) {
+ return static_cast<F&&>(hana::get_impl<0>(expr.storage_))(
+ static_cast<Args&&>(hana::get_impl<n+1>(expr.storage_))...
+ );
+ }
+
+ // lazy_value_t
+ template <typename X>
+ static constexpr X const& apply(lazy_value_t<X> const& expr)
+ { return hana::get_impl<0>(expr.storage_); }
+
+ template <typename X>
+ static constexpr X& apply(lazy_value_t<X>& expr)
+ { return hana::get_impl<0>(expr.storage_); }
+
+ template <typename X>
+ static constexpr X apply(lazy_value_t<X>&& expr)
+ { return static_cast<X&&>(hana::get_impl<0>(expr.storage_)); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Functor
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct transform_impl<lazy_tag> {
+ template <typename Expr, typename F>
+ static constexpr auto apply(Expr&& expr, F&& f) {
+ return hana::make_lazy(hana::compose(static_cast<F&&>(f), hana::eval))(
+ static_cast<Expr&&>(expr)
+ );
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Applicative
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct lift_impl<lazy_tag> {
+ template <typename X>
+ static constexpr lazy_value_t<typename detail::decay<X>::type>
+ apply(X&& x) {
+ return {detail::lazy_secret{}, static_cast<X&&>(x)};
+ }
+ };
+
+ template <>
+ struct ap_impl<lazy_tag> {
+ template <typename F, typename X>
+ static constexpr decltype(auto) apply(F&& f, X&& x) {
+ return hana::make_lazy(hana::on(hana::apply, hana::eval))(
+ static_cast<F&&>(f), static_cast<X&&>(x)
+ );
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Monad
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct flatten_impl<lazy_tag> {
+ template <typename Expr>
+ static constexpr decltype(auto) apply(Expr&& expr) {
+ return hana::make_lazy(hana::compose(hana::eval, hana::eval))(
+ static_cast<Expr&&>(expr)
+ );
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Comonad
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct extract_impl<lazy_tag> {
+ template <typename Expr>
+ static constexpr decltype(auto) apply(Expr&& expr)
+ { return hana::eval(static_cast<Expr&&>(expr)); }
+ };
+
+ template <>
+ struct duplicate_impl<lazy_tag> {
+ template <typename Expr>
+ static constexpr decltype(auto) apply(Expr&& expr)
+ { return hana::make_lazy(static_cast<Expr&&>(expr)); }
+ };
+
+ template <>
+ struct extend_impl<lazy_tag> {
+ template <typename Expr, typename F>
+ static constexpr decltype(auto) apply(Expr&& expr, F&& f) {
+ return hana::make_lazy(static_cast<F&&>(f))(static_cast<Expr&&>(expr));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_LAZY_HPP
diff --git a/boost/hana/length.hpp b/boost/hana/length.hpp
new file mode 100644
index 0000000000..c7224df9bd
--- /dev/null
+++ b/boost/hana/length.hpp
@@ -0,0 +1,57 @@
+/*!
+@file
+Defines `boost::hana::length`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_LENGTH_HPP
+#define BOOST_HANA_LENGTH_HPP
+
+#include <boost/hana/fwd/length.hpp>
+
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/unpack.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs>
+ constexpr auto length_t::operator()(Xs const& xs) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Length = BOOST_HANA_DISPATCH_IF(length_impl<S>,
+ hana::Foldable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Foldable<S>::value,
+ "hana::length(xs) requires 'xs' to be Foldable");
+ #endif
+
+ return Length::apply(xs);
+ }
+ //! @endcond
+
+ namespace detail {
+ struct argn {
+ template <typename ...Xs>
+ constexpr auto operator()(Xs const& ...) const
+ { return hana::size_c<sizeof...(Xs)>; }
+ };
+ }
+
+ template <typename T, bool condition>
+ struct length_impl<T, when<condition>> : default_ {
+ template <typename Xs>
+ static constexpr auto apply(Xs const& xs) {
+ return hana::unpack(xs, detail::argn{});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_LENGTH_HPP
diff --git a/boost/hana/less.hpp b/boost/hana/less.hpp
new file mode 100644
index 0000000000..eff6d3709b
--- /dev/null
+++ b/boost/hana/less.hpp
@@ -0,0 +1,142 @@
+/*!
+@file
+Defines `boost::hana::less`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_LESS_HPP
+#define BOOST_HANA_LESS_HPP
+
+#include <boost/hana/fwd/less.hpp>
+
+#include <boost/hana/and.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/orderable.hpp>
+#include <boost/hana/concept/product.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/common.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/concepts.hpp>
+#include <boost/hana/detail/has_common_embedding.hpp>
+#include <boost/hana/detail/nested_than.hpp> // required by fwd decl
+#include <boost/hana/equal.hpp>
+#include <boost/hana/first.hpp>
+#include <boost/hana/if.hpp>
+#include <boost/hana/less_equal.hpp>
+#include <boost/hana/lexicographical_compare.hpp>
+#include <boost/hana/or.hpp>
+#include <boost/hana/second.hpp>
+#include <boost/hana/value.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename X, typename Y>
+ constexpr auto less_t::operator()(X&& x, Y&& y) const {
+ using T = typename hana::tag_of<X>::type;
+ using U = typename hana::tag_of<Y>::type;
+ using Less = BOOST_HANA_DISPATCH_IF(decltype(less_impl<T, U>{}),
+ hana::Orderable<T>::value &&
+ hana::Orderable<U>::value &&
+ !is_default<less_impl<T, U>>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Orderable<T>::value,
+ "hana::less(x, y) requires 'x' to be Orderable");
+
+ static_assert(hana::Orderable<U>::value,
+ "hana::less(x, y) requires 'y' to be Orderable");
+
+ static_assert(!is_default<less_impl<T, U>>::value,
+ "hana::less(x, y) requires 'x' and 'y' to be embeddable "
+ "in a common Orderable");
+ #endif
+
+ return Less::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
+ }
+ //! @endcond
+
+ template <typename T, typename U, bool condition>
+ struct less_impl<T, U, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+
+ // Cross-type overload
+ template <typename T, typename U>
+ struct less_impl<T, U, when<
+ detail::has_nontrivial_common_embedding<Orderable, T, U>::value &&
+ !detail::LessThanComparable<T, U>::value
+ >> {
+ using C = typename hana::common<T, U>::type;
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y) {
+ return hana::less(hana::to<C>(static_cast<X&&>(x)),
+ hana::to<C>(static_cast<Y&&>(y)));
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for LessThanComparable data types
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T, typename U>
+ struct less_impl<T, U, when<detail::LessThanComparable<T, U>::value>> {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y)
+ { return static_cast<X&&>(x) < static_cast<Y&&>(y); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for Constants wrapping an Orderable
+ //////////////////////////////////////////////////////////////////////////
+ template <typename C>
+ struct less_impl<C, C, when<
+ hana::Constant<C>::value &&
+ Orderable<typename C::value_type>::value
+ >> {
+ template <typename X, typename Y>
+ static constexpr auto apply(X const&, Y const&) {
+ constexpr auto less = hana::less(hana::value<X>(), hana::value<Y>());
+ constexpr bool truth_value = hana::if_(less, true, false);
+ return hana::bool_c<truth_value>;
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for Products
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T, typename U>
+ struct less_impl<T, U, when<hana::Product<T>::value && hana::Product<U>::value>> {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X const& x, Y const& y) {
+ return hana::or_(
+ hana::less(hana::first(x), hana::first(y)),
+ hana::and_(
+ hana::less_equal(hana::first(x), hana::first(y)),
+ hana::less(hana::second(x), hana::second(y))
+ )
+ );
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for Sequences
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T, typename U>
+ struct less_impl<T, U, when<
+ hana::Sequence<T>::value && hana::Sequence<U>::value
+ >> {
+ template <typename Xs, typename Ys>
+ static constexpr auto apply(Xs const& xs, Ys const& ys)
+ { return hana::lexicographical_compare(xs, ys); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_LESS_HPP
diff --git a/boost/hana/less_equal.hpp b/boost/hana/less_equal.hpp
new file mode 100644
index 0000000000..3a04f9b3c5
--- /dev/null
+++ b/boost/hana/less_equal.hpp
@@ -0,0 +1,75 @@
+/*!
+@file
+Defines `boost::hana::less_equal`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_LESS_EQUAL_HPP
+#define BOOST_HANA_LESS_EQUAL_HPP
+
+#include <boost/hana/fwd/less_equal.hpp>
+
+#include <boost/hana/concept/orderable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/common.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/has_common_embedding.hpp>
+#include <boost/hana/detail/nested_than.hpp> // required by fwd decl
+#include <boost/hana/less.hpp>
+#include <boost/hana/not.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename X, typename Y>
+ constexpr auto less_equal_t::operator()(X&& x, Y&& y) const {
+ using T = typename hana::tag_of<X>::type;
+ using U = typename hana::tag_of<Y>::type;
+ using LessEqual = BOOST_HANA_DISPATCH_IF(
+ decltype(less_equal_impl<T, U>{}),
+ hana::Orderable<T>::value &&
+ hana::Orderable<U>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Orderable<T>::value,
+ "hana::less_equal(x, y) requires 'x' to be Orderable");
+
+ static_assert(hana::Orderable<U>::value,
+ "hana::less_equal(x, y) requires 'y' to be Orderable");
+ #endif
+
+ return LessEqual::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
+ }
+ //! @endcond
+
+ template <typename T, typename U, bool condition>
+ struct less_equal_impl<T, U, when<condition>> : default_ {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y) {
+ return hana::not_(hana::less(static_cast<Y&&>(y),
+ static_cast<X&&>(x)));
+ }
+ };
+
+ // Cross-type overload
+ template <typename T, typename U>
+ struct less_equal_impl<T, U, when<
+ detail::has_nontrivial_common_embedding<Orderable, T, U>::value
+ >> {
+ using C = typename hana::common<T, U>::type;
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y) {
+ return hana::less_equal(hana::to<C>(static_cast<X&&>(x)),
+ hana::to<C>(static_cast<Y&&>(y)));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_LESS_EQUAL_HPP
diff --git a/boost/hana/lexicographical_compare.hpp b/boost/hana/lexicographical_compare.hpp
new file mode 100644
index 0000000000..bb2ca15a43
--- /dev/null
+++ b/boost/hana/lexicographical_compare.hpp
@@ -0,0 +1,110 @@
+/*!
+@file
+Defines `boost::hana::lexicographical_compare`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_LEXICOGRAPHICAL_COMPARE_HPP
+#define BOOST_HANA_LEXICOGRAPHICAL_COMPARE_HPP
+
+#include <boost/hana/fwd/lexicographical_compare.hpp>
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/iterable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/drop_front.hpp>
+#include <boost/hana/front.hpp>
+#include <boost/hana/if.hpp>
+#include <boost/hana/is_empty.hpp>
+#include <boost/hana/less.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Ys>
+ constexpr auto lexicographical_compare_t::operator()(Xs const& xs, Ys const& ys) const {
+ return hana::lexicographical_compare(xs, ys, hana::less);
+ }
+
+ template <typename Xs, typename Ys, typename Pred>
+ constexpr auto lexicographical_compare_t::operator()(Xs const& xs, Ys const& ys, Pred const& pred) const {
+ using It1 = typename hana::tag_of<Xs>::type;
+ using It2 = typename hana::tag_of<Ys>::type;
+ using LexicographicalCompare = BOOST_HANA_DISPATCH_IF(
+ lexicographical_compare_impl<It1>,
+ hana::Iterable<It1>::value &&
+ hana::Iterable<It2>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Iterable<It1>::value,
+ "hana::lexicographical_compare(xs, ys, pred) requires 'xs' to be Iterable");
+
+ static_assert(hana::Iterable<It2>::value,
+ "hana::lexicographical_compare(xs, ys, pred) requires 'ys' to be Iterable");
+ #endif
+
+ return LexicographicalCompare::apply(xs, ys, pred);
+ }
+ //! @endcond
+
+ template <typename It, bool condition>
+ struct lexicographical_compare_impl<It, when<condition>> : default_ {
+ template <typename Xs, typename Ys, typename Pred>
+ static constexpr auto
+ helper2(Xs const&, Ys const&, Pred const&, hana::true_)
+ { return hana::false_c; }
+
+ template <typename Xs, typename Ys, typename Pred>
+ static constexpr auto
+ helper2(Xs const& xs, Ys const& ys, Pred const& pred, hana::false_)
+ { return apply(hana::drop_front(xs), hana::drop_front(ys), pred); }
+
+ template <typename Xs, typename Ys, typename Pred>
+ static constexpr auto
+ helper2(Xs const& xs, Ys const& ys, Pred const& pred, bool is_greater)
+ { return is_greater ? false : apply(hana::drop_front(xs), hana::drop_front(ys), pred); }
+
+
+ template <typename Xs, typename Ys, typename Pred>
+ static constexpr auto
+ helper1(Xs const&, Ys const&, Pred const&, hana::true_)
+ { return hana::true_c; }
+
+ template <typename Xs, typename Ys, typename Pred>
+ static constexpr auto
+ helper1(Xs const& xs, Ys const& ys, Pred const& pred, hana::false_)
+ { return helper2(xs, ys, pred, hana::if_(pred(hana::front(ys), hana::front(xs)), hana::true_c, hana::false_c)); }
+
+ template <typename Xs, typename Ys, typename Pred>
+ static constexpr auto
+ helper1(Xs const& xs, Ys const& ys, Pred const& pred, bool is_less)
+ { return is_less ? true : helper2(xs, ys, pred, hana::if_(pred(hana::front(ys), hana::front(xs)), hana::true_c, hana::false_c)); }
+
+
+ template <typename Xs, typename Ys, typename Pred>
+ static constexpr auto
+ helper(Xs const&, Ys const& ys, Pred const&, hana::true_)
+ { return hana::not_(hana::is_empty(ys)); }
+
+ template <typename Xs, typename Ys, typename Pred>
+ static constexpr auto
+ helper(Xs const& xs, Ys const& ys, Pred const& pred, hana::false_)
+ { return helper1(xs, ys, pred, hana::if_(pred(hana::front(xs), hana::front(ys)), hana::true_c, hana::false_c)); }
+
+
+ template <typename Xs, typename Ys, typename Pred>
+ static constexpr auto apply(Xs const& xs, Ys const& ys, Pred const& pred) {
+ return helper(xs, ys, pred, hana::bool_c<
+ decltype(hana::is_empty(xs))::value ||
+ decltype(hana::is_empty(ys))::value
+ >);
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_LEXICOGRAPHICAL_COMPARE_HPP
diff --git a/boost/hana/lift.hpp b/boost/hana/lift.hpp
new file mode 100644
index 0000000000..a91c43bacc
--- /dev/null
+++ b/boost/hana/lift.hpp
@@ -0,0 +1,54 @@
+/*!
+@file
+Defines `boost::hana::lift`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_LIFT_HPP
+#define BOOST_HANA_LIFT_HPP
+
+#include <boost/hana/fwd/lift.hpp>
+
+#include <boost/hana/concept/applicative.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename A>
+ struct lift_t {
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Applicative<A>::value,
+ "hana::lift<A> requires 'A' to be an Applicative");
+ #endif
+
+ template <typename X>
+ constexpr auto operator()(X&& x) const {
+ using Lift = BOOST_HANA_DISPATCH_IF(lift_impl<A>,
+ hana::Applicative<A>::value
+ );
+
+ return Lift::apply(static_cast<X&&>(x));
+ }
+ };
+
+ template <typename A, bool condition>
+ struct lift_impl<A, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...args) = delete;
+ };
+
+ template <typename S>
+ struct lift_impl<S, when<Sequence<S>::value>> {
+ template <typename X>
+ static constexpr decltype(auto) apply(X&& x)
+ { return hana::make<S>(static_cast<X&&>(x)); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_LIFT_HPP
diff --git a/boost/hana/map.hpp b/boost/hana/map.hpp
new file mode 100644
index 0000000000..341f1d0517
--- /dev/null
+++ b/boost/hana/map.hpp
@@ -0,0 +1,389 @@
+/*!
+@file
+Defines `boost::hana::map`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_MAP_HPP
+#define BOOST_HANA_MAP_HPP
+
+#include <boost/hana/fwd/map.hpp>
+
+#include <boost/hana/all_of.hpp>
+#include <boost/hana/basic_tuple.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/product.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/contains.hpp>
+#include <boost/hana/core/is_a.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/detail/decay.hpp>
+#include <boost/hana/detail/fast_and.hpp>
+#include <boost/hana/detail/has_duplicates.hpp>
+#include <boost/hana/detail/hash_table.hpp>
+#include <boost/hana/detail/operators/adl.hpp>
+#include <boost/hana/detail/operators/comparable.hpp>
+#include <boost/hana/detail/operators/searchable.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/find.hpp>
+#include <boost/hana/first.hpp>
+#include <boost/hana/fold_left.hpp>
+#include <boost/hana/functional/demux.hpp>
+#include <boost/hana/functional/on.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/fwd/any_of.hpp>
+#include <boost/hana/fwd/at_key.hpp>
+#include <boost/hana/fwd/erase_key.hpp>
+#include <boost/hana/fwd/is_subset.hpp>
+#include <boost/hana/fwd/keys.hpp>
+#include <boost/hana/insert.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/keys.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/optional.hpp>
+#include <boost/hana/remove_if.hpp>
+#include <boost/hana/second.hpp>
+#include <boost/hana/unpack.hpp>
+#include <boost/hana/value.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //////////////////////////////////////////////////////////////////////////
+ // operators
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <>
+ struct comparable_operators<map_tag> {
+ static constexpr bool value = true;
+ };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // map
+ //////////////////////////////////////////////////////////////////////////
+ //! @cond
+ template <typename HashTable, typename Storage>
+ struct map
+ : detail::searchable_operators<map<HashTable, Storage>>
+ , detail::operators::adl<map<HashTable, Storage>>
+ {
+ using hash_table_type = HashTable;
+ using storage_type = Storage;
+
+ Storage storage;
+
+ using hana_tag = map_tag;
+
+ explicit constexpr map(Storage const& xs)
+ : storage(xs)
+ { }
+
+ explicit constexpr map(Storage&& xs)
+ : storage(static_cast<Storage&&>(xs))
+ { }
+
+ constexpr map() = default;
+ constexpr map(map const& other) = default;
+ constexpr map(map&& other) = default;
+ };
+ //! @endcond
+
+ namespace detail {
+ template <typename Storage>
+ struct KeyAtIndex {
+ template <std::size_t i>
+ using apply = decltype(hana::first(hana::get_impl<i>(std::declval<Storage>())));
+ };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // make<map_tag>
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct make_impl<map_tag> {
+ template <typename ...Pairs>
+ static constexpr auto apply(Pairs&& ...pairs) {
+#if defined(BOOST_HANA_CONFIG_ENABLE_DEBUG_MODE)
+ static_assert(detail::fast_and<hana::Product<Pairs>::value...>::value,
+ "hana::make_map(pairs...) requires all the 'pairs' to be Products");
+
+ static_assert(detail::fast_and<
+ Comparable<decltype(hana::first(pairs))>::value...
+ >::value,
+ "hana::make_map(pairs...) requires all the keys to be Comparable");
+
+ static_assert(detail::fast_and<
+ Constant<
+ decltype(hana::equal(hana::first(pairs), hana::first(pairs)))
+ >::value...
+ >::value,
+ "hana::make_map(pairs...) requires all the keys to be "
+ "Comparable at compile-time");
+
+ //! @todo
+ //! This can be implemented more efficiently by doing the check
+ //! inside each bucket instead.
+ static_assert(!detail::has_duplicates<decltype(hana::first(pairs))...>::value,
+ "hana::make_map({keys, values}...) requires all the keys to be unique");
+
+ static_assert(!detail::has_duplicates<decltype(hana::hash(hana::first(pairs)))...>::value,
+ "hana::make_map({keys, values}...) requires all the keys to have different hashes");
+#endif
+
+ using Storage = hana::basic_tuple<typename detail::decay<Pairs>::type...>;
+ using HashTable = typename detail::make_hash_table<
+ detail::KeyAtIndex<Storage>::template apply, sizeof...(Pairs)
+ >::type;
+
+ return map<HashTable, Storage>(
+ hana::make_basic_tuple(static_cast<Pairs&&>(pairs)...)
+ );
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // keys
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct keys_impl<map_tag> {
+ template <typename Map>
+ static constexpr decltype(auto) apply(Map&& map) {
+ return hana::transform(static_cast<Map&&>(map).storage, hana::first);
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // values
+ //////////////////////////////////////////////////////////////////////////
+ //! @cond
+ template <typename Map>
+ constexpr decltype(auto) values_t::operator()(Map&& map) const {
+ return hana::transform(static_cast<Map&&>(map).storage, hana::second);
+ }
+ //! @endcond
+
+ //////////////////////////////////////////////////////////////////////////
+ // insert
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct insert_impl<map_tag> {
+ template <typename Map, typename Pair>
+ static constexpr auto helper(Map&& map, Pair&& pair, ...) {
+ using RawMap = typename std::remove_reference<Map>::type;
+ using HashTable = typename RawMap::hash_table_type;
+ using NewHashTable = typename detail::bucket_insert<
+ HashTable,
+ decltype(hana::first(pair)),
+ decltype(hana::length(map.storage))::value
+ >::type;
+
+ using NewStorage = decltype(
+ hana::append(static_cast<Map&&>(map).storage, static_cast<Pair&&>(pair))
+ );
+ return hana::map<NewHashTable, NewStorage>(
+ hana::append(static_cast<Map&&>(map).storage, static_cast<Pair&&>(pair))
+ );
+ }
+
+ template <typename Map, typename Pair, std::size_t i>
+ static constexpr auto
+ helper(Map&& map, Pair&&,
+ hana::optional<std::integral_constant<std::size_t, i>>)
+ {
+ return static_cast<Map&&>(map);
+ }
+
+ //! @todo
+ //! Here, we insert only if the key is not already in the map.
+ //! This should be handled by `bucket_insert`, and that would also
+ //! be more efficient.
+ template <typename Map, typename Pair>
+ static constexpr auto apply(Map&& map, Pair&& pair) {
+ using RawMap = typename std::remove_reference<Map>::type;
+ using Storage = typename RawMap::storage_type;
+ using HashTable = typename RawMap::hash_table_type;
+ using Key = decltype(hana::first(pair));
+ using MaybeIndex = typename detail::find_index<
+ HashTable, Key, detail::KeyAtIndex<Storage>::template apply
+ >::type;
+ return helper(static_cast<Map&&>(map), static_cast<Pair&&>(pair), MaybeIndex{});
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // erase_key
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct erase_key_impl<map_tag> {
+ //! @todo
+ //! We could implement some kind of `bucket_erase` metafunction
+ //! that would be much more efficient than this.
+ template <typename Map, typename Key>
+ static constexpr auto
+ erase_key_helper(Map&& map, Key const&, hana::false_) {
+ return static_cast<Map&&>(map);
+ }
+
+ template <typename Map, typename Key>
+ static constexpr auto
+ erase_key_helper(Map&& map, Key const& key, hana::true_) {
+ return hana::unpack(
+ hana::remove_if(static_cast<Map&&>(map).storage,
+ hana::on(hana::equal.to(key), hana::first)),
+ hana::make_map
+ );
+ }
+
+ template <typename Map, typename Key>
+ static constexpr auto apply(Map&& map, Key const& key) {
+ constexpr bool contains = hana::value<decltype(hana::contains(map, key))>();
+ return erase_key_helper(static_cast<Map&&>(map), key,
+ hana::bool_c<contains>);
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Comparable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct equal_impl<map_tag, map_tag> {
+ template <typename M1, typename M2>
+ static constexpr auto equal_helper(M1 const&, M2 const&, hana::false_) {
+ return hana::false_c;
+ }
+
+ template <typename M1, typename M2>
+ static constexpr auto equal_helper(M1 const& m1, M2 const& m2, hana::true_) {
+ return hana::all_of(hana::keys(m1), hana::demux(equal)(
+ hana::partial(hana::find, m1),
+ hana::partial(hana::find, m2)
+ ));
+ }
+
+ template <typename M1, typename M2>
+ static constexpr auto apply(M1 const& m1, M2 const& m2) {
+ return equal_impl::equal_helper(m1, m2, hana::bool_c<
+ decltype(hana::length(m1.storage))::value ==
+ decltype(hana::length(m2.storage))::value
+ >);
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Searchable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct find_impl<map_tag> {
+ template <typename Map>
+ static constexpr auto find_helper(Map&&, ...) {
+ return hana::nothing;
+ }
+
+ template <typename Map, std::size_t i>
+ static constexpr auto
+ find_helper(Map&& map, hana::optional<std::integral_constant<std::size_t, i>>) {
+ return hana::just(hana::second(hana::at_c<i>(static_cast<Map&&>(map).storage)));
+ }
+
+ template <typename Map, typename Key>
+ static constexpr auto apply(Map&& map, Key const&) {
+ using RawMap = typename std::remove_reference<Map>::type;
+ using Storage = typename RawMap::storage_type;
+ using HashTable = typename RawMap::hash_table_type;
+ using MaybeIndex = typename detail::find_index<
+ HashTable, Key, detail::KeyAtIndex<Storage>::template apply
+ >::type;
+ return find_helper(static_cast<Map&&>(map), MaybeIndex{});
+ }
+ };
+
+ template <>
+ struct find_if_impl<map_tag> {
+ template <typename M, typename Pred>
+ static constexpr auto apply(M&& map, Pred&& pred) {
+ return hana::transform(
+ hana::find_if(static_cast<M&&>(map).storage,
+ hana::compose(static_cast<Pred&&>(pred), hana::first)),
+ hana::second
+ );
+ }
+ };
+
+ template <>
+ struct any_of_impl<map_tag> {
+ template <typename M, typename Pred>
+ static constexpr auto apply(M const& map, Pred const& pred)
+ { return hana::any_of(hana::keys(map), pred); }
+ };
+
+ template <>
+ struct is_subset_impl<map_tag, map_tag> {
+ template <typename Ys>
+ struct all_contained {
+ Ys const& ys;
+ template <typename ...X>
+ constexpr auto operator()(X const& ...x) const {
+ return hana::bool_c<detail::fast_and<
+ hana::value<decltype(hana::contains(ys, x))>()...
+ >::value>;
+ }
+ };
+
+ template <typename Xs, typename Ys>
+ static constexpr auto apply(Xs const& xs, Ys const& ys) {
+ auto ys_keys = hana::keys(ys);
+ return hana::unpack(hana::keys(xs), all_contained<decltype(ys_keys)>{ys_keys});
+ }
+ };
+
+ template <>
+ struct at_key_impl<map_tag> {
+ template <typename Map, typename Key>
+ static constexpr decltype(auto) apply(Map&& map, Key const&) {
+ using RawMap = typename std::remove_reference<Map>::type;
+ using HashTable = typename RawMap::hash_table_type;
+ using Storage = typename RawMap::storage_type;
+ using MaybeIndex = typename detail::find_index<
+ HashTable, Key, detail::KeyAtIndex<Storage>::template apply
+ >::type;
+ constexpr std::size_t index = decltype(*MaybeIndex{}){}();
+ return hana::second(hana::at_c<index>(static_cast<Map&&>(map).storage));
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Foldable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct unpack_impl<map_tag> {
+ template <typename M, typename F>
+ static constexpr decltype(auto) apply(M&& map, F&& f) {
+ return hana::unpack(static_cast<M&&>(map).storage,
+ static_cast<F&&>(f));
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Construction from a Foldable
+ //////////////////////////////////////////////////////////////////////////
+ template <typename F>
+ struct to_impl<map_tag, F, when<hana::Foldable<F>::value>> {
+ template <typename Xs>
+ static constexpr decltype(auto) apply(Xs&& xs) {
+ return hana::fold_left(
+ static_cast<Xs&&>(xs), hana::make_map(), hana::insert
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_MAP_HPP
diff --git a/boost/hana/max.hpp b/boost/hana/max.hpp
new file mode 100644
index 0000000000..b470c92e71
--- /dev/null
+++ b/boost/hana/max.hpp
@@ -0,0 +1,58 @@
+/*!
+@file
+Defines `boost::hana::max`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_MAX_HPP
+#define BOOST_HANA_MAX_HPP
+
+#include <boost/hana/fwd/max.hpp>
+
+#include <boost/hana/concept/orderable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/if.hpp>
+#include <boost/hana/less.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename X, typename Y>
+ constexpr decltype(auto) max_t::operator()(X&& x, Y&& y) const {
+ using T = typename hana::tag_of<X>::type;
+ using U = typename hana::tag_of<Y>::type;
+ using Max = BOOST_HANA_DISPATCH_IF(decltype(max_impl<T, U>{}),
+ hana::Orderable<T>::value &&
+ hana::Orderable<U>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Orderable<T>::value,
+ "hana::max(x, y) requires 'x' to be Orderable");
+
+ static_assert(hana::Orderable<U>::value,
+ "hana::max(x, y) requires 'y' to be Orderable");
+ #endif
+
+ return Max::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
+ }
+ //! @endcond
+
+ template <typename T, typename U, bool condition>
+ struct max_impl<T, U, when<condition>> : default_ {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y) {
+ decltype(auto) cond = hana::less(x, y);
+ return hana::if_(static_cast<decltype(cond)&&>(cond),
+ static_cast<Y&&>(y),
+ static_cast<X&&>(x)
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_MAX_HPP
diff --git a/boost/hana/maximum.hpp b/boost/hana/maximum.hpp
new file mode 100644
index 0000000000..36eaf1008d
--- /dev/null
+++ b/boost/hana/maximum.hpp
@@ -0,0 +1,97 @@
+/*!
+@file
+Defines `boost::hana::maximum`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_MAXIMUM_HPP
+#define BOOST_HANA_MAXIMUM_HPP
+
+#include <boost/hana/fwd/maximum.hpp>
+
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/nested_by.hpp> // required by fwd decl
+#include <boost/hana/fold_left.hpp>
+#include <boost/hana/if.hpp>
+#include <boost/hana/less.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs>
+ constexpr decltype(auto) maximum_t::operator()(Xs&& xs) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Maximum = BOOST_HANA_DISPATCH_IF(maximum_impl<S>,
+ hana::Foldable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Foldable<S>::value,
+ "hana::maximum(xs) requires 'xs' to be Foldable");
+ #endif
+
+ return Maximum::apply(static_cast<Xs&&>(xs));
+ }
+
+ template <typename Xs, typename Predicate>
+ constexpr decltype(auto) maximum_t::operator()(Xs&& xs, Predicate&& pred) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Maximum = BOOST_HANA_DISPATCH_IF(maximum_pred_impl<S>,
+ hana::Foldable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Foldable<S>::value,
+ "hana::maximum(xs, predicate) requires 'xs' to be Foldable");
+ #endif
+
+ return Maximum::apply(static_cast<Xs&&>(xs),
+ static_cast<Predicate&&>(pred));
+ }
+ //! @endcond
+
+ //////////////////////////////////////////////////////////////////////////
+ // maximum (with a custom predicate)
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <typename Pred>
+ struct max_by {
+ Pred pred;
+
+ template <typename X, typename Y>
+ constexpr decltype(auto) operator()(X&& x, Y&& y) const {
+ auto result = (*pred)(x, y);
+ return hana::if_(result, static_cast<Y&&>(y),
+ static_cast<X&&>(x));
+ }
+ };
+ }
+
+ template <typename T, bool condition>
+ struct maximum_pred_impl<T, when<condition>> : default_ {
+ template <typename Xs, typename Pred>
+ static constexpr decltype(auto) apply(Xs&& xs, Pred&& pred) {
+ // We use a pointer instead of a reference to avoid a Clang ICE.
+ return hana::fold_left(static_cast<Xs&&>(xs),
+ detail::max_by<decltype(&pred)>{&pred}
+ );
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // maximum (without a custom predicate)
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T, bool condition>
+ struct maximum_impl<T, when<condition>> : default_ {
+ template <typename Xs>
+ static constexpr decltype(auto) apply(Xs&& xs)
+ { return hana::maximum(static_cast<Xs&&>(xs), hana::less); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_MAXIMUM_HPP
diff --git a/boost/hana/members.hpp b/boost/hana/members.hpp
new file mode 100644
index 0000000000..ffa933bfe8
--- /dev/null
+++ b/boost/hana/members.hpp
@@ -0,0 +1,65 @@
+/*!
+@file
+Defines `boost::hana::members`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_MEMBERS_HPP
+#define BOOST_HANA_MEMBERS_HPP
+
+#include <boost/hana/fwd/members.hpp>
+
+#include <boost/hana/accessors.hpp>
+#include <boost/hana/concept/struct.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/second.hpp>
+#include <boost/hana/transform.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Object>
+ constexpr auto members_t::operator()(Object&& object) const {
+ using S = typename hana::tag_of<Object>::type;
+ using Members = BOOST_HANA_DISPATCH_IF(members_impl<S>,
+ hana::Struct<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Struct<S>::value,
+ "hana::members(object) requires 'object' to be a Struct");
+ #endif
+
+ return Members::apply(static_cast<Object&&>(object));
+ }
+ //! @endcond
+
+ namespace struct_detail {
+ template <typename Holder, typename Forward>
+ struct members_helper {
+ Holder object;
+ template <typename Accessor>
+ constexpr decltype(auto) operator()(Accessor&& accessor) const {
+ return hana::second(static_cast<Accessor&&>(accessor))(
+ static_cast<Forward>(object)
+ );
+ }
+ };
+ }
+
+ template <typename S, bool condition>
+ struct members_impl<S, when<condition>> : default_ {
+ template <typename Object>
+ static constexpr auto apply(Object&& object) {
+ return hana::transform(hana::accessors<S>(),
+ struct_detail::members_helper<Object&, Object&&>{object}
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_MEMBERS_HPP
diff --git a/boost/hana/min.hpp b/boost/hana/min.hpp
new file mode 100644
index 0000000000..08f4cd9738
--- /dev/null
+++ b/boost/hana/min.hpp
@@ -0,0 +1,58 @@
+/*!
+@file
+Defines `boost::hana::min`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_MIN_HPP
+#define BOOST_HANA_MIN_HPP
+
+#include <boost/hana/fwd/min.hpp>
+
+#include <boost/hana/concept/orderable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/if.hpp>
+#include <boost/hana/less.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename X, typename Y>
+ constexpr decltype(auto) min_t::operator()(X&& x, Y&& y) const {
+ using T = typename hana::tag_of<X>::type;
+ using U = typename hana::tag_of<Y>::type;
+ using Min = BOOST_HANA_DISPATCH_IF(decltype(min_impl<T, U>{}),
+ hana::Orderable<T>::value &&
+ hana::Orderable<U>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Orderable<T>::value,
+ "hana::min(x, y) requires 'x' to be Orderable");
+
+ static_assert(hana::Orderable<U>::value,
+ "hana::min(x, y) requires 'y' to be Orderable");
+ #endif
+
+ return Min::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
+ }
+ //! @endcond
+
+ template <typename T, typename U, bool condition>
+ struct min_impl<T, U, when<condition>> : default_ {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y) {
+ decltype(auto) cond = hana::less(x, y);
+ return hana::if_(static_cast<decltype(cond)&&>(cond),
+ static_cast<X&&>(x),
+ static_cast<Y&&>(y)
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_MIN_HPP
diff --git a/boost/hana/minimum.hpp b/boost/hana/minimum.hpp
new file mode 100644
index 0000000000..96b2444b6b
--- /dev/null
+++ b/boost/hana/minimum.hpp
@@ -0,0 +1,97 @@
+/*!
+@file
+Defines `boost::hana::minimum`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_MINIMUM_HPP
+#define BOOST_HANA_MINIMUM_HPP
+
+#include <boost/hana/fwd/minimum.hpp>
+
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/nested_by.hpp> // required by fwd decl
+#include <boost/hana/fold_left.hpp>
+#include <boost/hana/if.hpp>
+#include <boost/hana/less.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs>
+ constexpr decltype(auto) minimum_t::operator()(Xs&& xs) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Minimum = BOOST_HANA_DISPATCH_IF(minimum_impl<S>,
+ hana::Foldable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Foldable<S>::value,
+ "hana::minimum(xs) requires 'xs' to be Foldable");
+ #endif
+
+ return Minimum::apply(static_cast<Xs&&>(xs));
+ }
+
+ template <typename Xs, typename Predicate>
+ constexpr decltype(auto) minimum_t::operator()(Xs&& xs, Predicate&& pred) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Minimum = BOOST_HANA_DISPATCH_IF(minimum_pred_impl<S>,
+ hana::Foldable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Foldable<S>::value,
+ "hana::minimum(xs, predicate) requires 'xs' to be Foldable");
+ #endif
+
+ return Minimum::apply(static_cast<Xs&&>(xs),
+ static_cast<Predicate&&>(pred));
+ }
+ //! @endcond
+
+ //////////////////////////////////////////////////////////////////////////
+ // minimum (with a custom predicate)
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <typename Pred>
+ struct min_by {
+ Pred pred;
+
+ template <typename X, typename Y>
+ constexpr decltype(auto) operator()(X&& x, Y&& y) const {
+ auto result = (*pred)(x, y);
+ return hana::if_(result, static_cast<X&&>(x),
+ static_cast<Y&&>(y));
+ }
+ };
+ }
+
+ template <typename T, bool condition>
+ struct minimum_pred_impl<T, when<condition>> : default_ {
+ template <typename Xs, typename Pred>
+ static constexpr decltype(auto) apply(Xs&& xs, Pred const& pred) {
+ // We use a pointer instead of a reference to avoid a Clang ICE.
+ return hana::fold_left(static_cast<Xs&&>(xs),
+ detail::min_by<decltype(&pred)>{&pred}
+ );
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // minimum (without a custom predicate)
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T, bool condition>
+ struct minimum_impl<T, when<condition>> : default_ {
+ template <typename Xs>
+ static constexpr decltype(auto) apply(Xs&& xs)
+ { return hana::minimum(static_cast<Xs&&>(xs), hana::less); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_MINIMUM_HPP
diff --git a/boost/hana/minus.hpp b/boost/hana/minus.hpp
new file mode 100644
index 0000000000..067c3665c8
--- /dev/null
+++ b/boost/hana/minus.hpp
@@ -0,0 +1,114 @@
+/*!
+@file
+Defines `boost::hana::minus`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_MINUS_HPP
+#define BOOST_HANA_MINUS_HPP
+
+#include <boost/hana/fwd/minus.hpp>
+
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/group.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/common.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/canonical_constant.hpp>
+#include <boost/hana/detail/has_common_embedding.hpp>
+#include <boost/hana/fwd/negate.hpp>
+#include <boost/hana/plus.hpp>
+#include <boost/hana/value.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename X, typename Y>
+ constexpr decltype(auto) minus_t::operator()(X&& x, Y&& y) const {
+ using T = typename hana::tag_of<X>::type;
+ using U = typename hana::tag_of<Y>::type;
+ using Minus = BOOST_HANA_DISPATCH_IF(decltype(minus_impl<T, U>{}),
+ hana::Group<T>::value &&
+ hana::Group<U>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Group<T>::value,
+ "hana::minus(x, y) requires 'x' to be in a Group");
+
+ static_assert(hana::Group<U>::value,
+ "hana::minus(x, y) requires 'y' to be in a Group");
+ #endif
+
+ return Minus::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
+ }
+ //! @endcond
+
+ template <typename T, typename U, bool condition>
+ struct minus_impl<T, U, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+
+ template <typename T, bool condition>
+ struct minus_impl<T, T, when<condition>> : default_ {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y) {
+ return hana::plus(static_cast<X&&>(x),
+ hana::negate(static_cast<Y&&>(y)));
+ }
+ };
+
+ // Cross-type overload
+ template <typename T, typename U>
+ struct minus_impl<T, U, when<
+ detail::has_nontrivial_common_embedding<Group, T, U>::value
+ >> {
+ using C = typename common<T, U>::type;
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y) {
+ return hana::minus(hana::to<C>(static_cast<X&&>(x)),
+ hana::to<C>(static_cast<Y&&>(y)));
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for arithmetic data types
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T>
+ struct minus_impl<T, T, when<std::is_arithmetic<T>::value &&
+ !std::is_same<bool, T>::value>> {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y)
+ { return static_cast<X&&>(x) - static_cast<Y&&>(y); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for Constants over a Group
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <typename C, typename X, typename Y>
+ struct constant_from_minus {
+ static constexpr auto value = hana::minus(hana::value<X>(), hana::value<Y>());
+ using hana_tag = detail::CanonicalConstant<typename C::value_type>;
+ };
+ }
+
+ template <typename C>
+ struct minus_impl<C, C, when<
+ hana::Constant<C>::value &&
+ Group<typename C::value_type>::value
+ >> {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X const&, Y const&)
+ { return hana::to<C>(detail::constant_from_minus<C, X, Y>{}); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_MINUS_HPP
diff --git a/boost/hana/mod.hpp b/boost/hana/mod.hpp
new file mode 100644
index 0000000000..052df99ac9
--- /dev/null
+++ b/boost/hana/mod.hpp
@@ -0,0 +1,107 @@
+/*!
+@file
+Defines `boost::hana::mod`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_MOD_HPP
+#define BOOST_HANA_MOD_HPP
+
+#include <boost/hana/fwd/mod.hpp>
+
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/euclidean_ring.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/canonical_constant.hpp>
+#include <boost/hana/detail/has_common_embedding.hpp>
+#include <boost/hana/value.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename X, typename Y>
+ constexpr decltype(auto) mod_t::operator()(X&& x, Y&& y) const {
+ using T = typename hana::tag_of<X>::type;
+ using U = typename hana::tag_of<Y>::type;
+ using Mod = BOOST_HANA_DISPATCH_IF(decltype(mod_impl<T, U>{}),
+ hana::EuclideanRing<T>::value &&
+ hana::EuclideanRing<U>::value &&
+ !is_default<mod_impl<T, U>>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::EuclideanRing<T>::value,
+ "hana::mod(x, y) requires 'x' to be an EuclideanRing");
+
+ static_assert(hana::EuclideanRing<U>::value,
+ "hana::mod(x, y) requires 'y' to be an EuclideanRing");
+
+ static_assert(!is_default<mod_impl<T, U>>::value,
+ "hana::mod(x, y) requires 'x' and 'y' to be embeddable "
+ "in a common EuclideanRing");
+ #endif
+
+ return Mod::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
+ }
+ //! @endcond
+
+ template <typename T, typename U, bool condition>
+ struct mod_impl<T, U, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+
+ // Cross-type overload
+ template <typename T, typename U>
+ struct mod_impl<T, U, when<
+ detail::has_nontrivial_common_embedding<EuclideanRing, T, U>::value
+ >> {
+ using C = typename common<T, U>::type;
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y) {
+ return hana::mod(hana::to<C>(static_cast<X&&>(x)),
+ hana::to<C>(static_cast<Y&&>(y)));
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for integral data types
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T>
+ struct mod_impl<T, T, when<std::is_integral<T>::value &&
+ !std::is_same<T, bool>::value>> {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y)
+ { return static_cast<X&&>(x) % static_cast<Y&&>(y); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for Constants over an EuclideanRing
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <typename C, typename X, typename Y>
+ struct constant_from_mod {
+ static constexpr auto value = hana::mod(hana::value<X>(), hana::value<Y>());
+ using hana_tag = detail::CanonicalConstant<typename C::value_type>;
+ };
+ }
+
+ template <typename C>
+ struct mod_impl<C, C, when<
+ hana::Constant<C>::value &&
+ EuclideanRing<typename C::value_type>::value
+ >> {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X const&, Y const&)
+ { return hana::to<C>(detail::constant_from_mod<C, X, Y>{}); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_MOD_HPP
diff --git a/boost/hana/monadic_compose.hpp b/boost/hana/monadic_compose.hpp
new file mode 100644
index 0000000000..5bd8c5b8e4
--- /dev/null
+++ b/boost/hana/monadic_compose.hpp
@@ -0,0 +1,51 @@
+/*!
+@file
+Defines `boost::hana::monadic_compose`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_MONADIC_COMPOSE_HPP
+#define BOOST_HANA_MONADIC_COMPOSE_HPP
+
+#include <boost/hana/fwd/monadic_compose.hpp>
+
+#include <boost/hana/chain.hpp>
+#include <boost/hana/concept/monad.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/functional/partial.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace detail {
+ struct monadic_compose_helper {
+ template <typename F, typename G, typename X>
+ constexpr decltype(auto) operator()(F&& f, G&& g, X&& x) const {
+ using M = typename hana::tag_of<decltype(g(x))>::type;
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Monad<M>::value,
+ "hana::monadic_compose(f, g) requires 'g' to return a monadic value");
+ #endif
+
+ return hana::chain(static_cast<G&&>(g)(static_cast<X&&>(x)),
+ static_cast<F&&>(f));
+ }
+ };
+ }
+
+ //! @cond
+ template <typename F, typename G>
+ constexpr auto monadic_compose_t::operator()(F&& f, G&& g) const {
+ return hana::partial(detail::monadic_compose_helper{},
+ static_cast<F&&>(f),
+ static_cast<G&&>(g)
+ );
+ }
+ //! @endcond
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_MONADIC_COMPOSE_HPP
diff --git a/boost/hana/monadic_fold_left.hpp b/boost/hana/monadic_fold_left.hpp
new file mode 100644
index 0000000000..999ddfff55
--- /dev/null
+++ b/boost/hana/monadic_fold_left.hpp
@@ -0,0 +1,131 @@
+/*!
+@file
+Defines `boost::hana::monadic_fold_left`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_MONADIC_FOLD_LEFT_HPP
+#define BOOST_HANA_MONADIC_FOLD_LEFT_HPP
+
+#include <boost/hana/fwd/monadic_fold_left.hpp>
+
+#include <boost/hana/chain.hpp>
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/concept/monad.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/fold_right.hpp>
+#include <boost/hana/functional/curry.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/lift.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename M>
+ struct monadic_fold_left_t {
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Monad<M>::value,
+ "hana::monadic_fold_left<M> requires 'M' to be a Monad");
+ #endif
+
+ template <typename Xs, typename State, typename F>
+ constexpr decltype(auto) operator()(Xs&& xs, State&& state, F&& f) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using MonadicFoldLeft = BOOST_HANA_DISPATCH_IF(monadic_fold_left_impl<S>,
+ hana::Foldable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Foldable<S>::value,
+ "hana::monadic_fold_left<M>(xs, state, f) requires 'xs' to be Foldable");
+ #endif
+
+ return MonadicFoldLeft::template apply<M>(static_cast<Xs&&>(xs),
+ static_cast<State&&>(state),
+ static_cast<F&&>(f));
+ }
+
+ template <typename Xs, typename F>
+ constexpr decltype(auto) operator()(Xs&& xs, F&& f) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using MonadicFoldLeft = BOOST_HANA_DISPATCH_IF(monadic_fold_left_impl<S>,
+ hana::Foldable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Foldable<S>::value,
+ "hana::monadic_fold_left<M>(xs, f) requires 'xs' to be Foldable");
+ #endif
+
+ return MonadicFoldLeft::template apply<M>(static_cast<Xs&&>(xs),
+ static_cast<F&&>(f));
+ }
+ };
+
+ namespace detail {
+ struct foldlM_helper {
+ template <typename F, typename X, typename K, typename Z>
+ constexpr decltype(auto) operator()(F&& f, X&& x, K&& k, Z&& z) const {
+ return hana::chain(
+ static_cast<F&&>(f)(
+ static_cast<Z&&>(z),
+ static_cast<X&&>(x)
+ ),
+ static_cast<K&&>(k)
+ );
+ }
+ };
+
+ template <typename End, typename M, typename F>
+ struct monadic_foldl1_helper {
+ F f;
+ template <typename X, typename Y>
+ constexpr decltype(auto) operator()(X&& x, Y&& y) const
+ { return f(static_cast<X&&>(x), static_cast<Y&&>(y)); }
+ template <typename Y>
+ constexpr decltype(auto) operator()(End, Y&& y) const
+ { return hana::lift<M>(static_cast<Y&&>(y)); }
+ };
+ }
+
+ template <typename T, bool condition>
+ struct monadic_fold_left_impl<T, when<condition>> : default_ {
+ // with state
+ template <typename M, typename Xs, typename S, typename F>
+ static constexpr decltype(auto) apply(Xs&& xs, S&& s, F&& f) {
+ return hana::fold_right(
+ static_cast<Xs&&>(xs),
+ hana::lift<M>,
+ hana::curry<3>(hana::partial(
+ detail::foldlM_helper{}, static_cast<F&&>(f)
+ ))
+ )(static_cast<S&&>(s));
+ }
+
+ // without state
+ template <typename M, typename Xs, typename F>
+ static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
+ struct end { };
+ using G = detail::monadic_foldl1_helper<end, M, typename std::decay<F>::type>;
+ decltype(auto) result = hana::monadic_fold_left<M>(
+ static_cast<Xs&&>(xs),
+ end{},
+ G{static_cast<F&&>(f)}
+ );
+
+ static_assert(!std::is_same<
+ std::remove_reference_t<decltype(result)>,
+ decltype(hana::lift<M>(end{}))
+ >{},
+ "hana::monadic_fold_left<M>(xs, f) requires 'xs' to be non-empty");
+ return result;
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_MONADIC_FOLD_LEFT_HPP
diff --git a/boost/hana/monadic_fold_right.hpp b/boost/hana/monadic_fold_right.hpp
new file mode 100644
index 0000000000..814343a336
--- /dev/null
+++ b/boost/hana/monadic_fold_right.hpp
@@ -0,0 +1,130 @@
+/*!
+@file
+Defines `boost::hana::monadic_fold_right`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_MONADIC_FOLD_RIGHT_HPP
+#define BOOST_HANA_MONADIC_FOLD_RIGHT_HPP
+
+#include <boost/hana/fwd/monadic_fold_right.hpp>
+
+#include <boost/hana/chain.hpp>
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/concept/monad.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/fold_left.hpp>
+#include <boost/hana/functional/curry.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/lift.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename M>
+ struct monadic_fold_right_t {
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Monad<M>::value,
+ "hana::monadic_fold_right<M> requires 'M' to be a Monad");
+ #endif
+
+ template <typename Xs, typename State, typename F>
+ constexpr decltype(auto) operator()(Xs&& xs, State&& state, F&& f) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using MonadicFoldRight = BOOST_HANA_DISPATCH_IF(monadic_fold_right_impl<S>,
+ hana::Foldable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Foldable<S>::value,
+ "hana::monadic_fold_right<M>(xs, state, f) requires 'xs' to be Foldable");
+ #endif
+
+ return MonadicFoldRight::template apply<M>(static_cast<Xs&&>(xs),
+ static_cast<State&&>(state),
+ static_cast<F&&>(f));
+ }
+
+ template <typename Xs, typename F>
+ constexpr decltype(auto) operator()(Xs&& xs, F&& f) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using MonadicFoldRight = BOOST_HANA_DISPATCH_IF(monadic_fold_right_impl<S>,
+ hana::Foldable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Foldable<S>::value,
+ "hana::monadic_fold_right<M>(xs, f) requires 'xs' to be Foldable");
+ #endif
+ return MonadicFoldRight::template apply<M>(static_cast<Xs&&>(xs),
+ static_cast<F&&>(f));
+ }
+ };
+
+ namespace detail {
+ struct foldrM_helper {
+ template <typename F, typename K, typename X, typename Z>
+ constexpr decltype(auto) operator()(F&& f, K&& k, X&& x, Z&& z) const {
+ return hana::chain(
+ static_cast<F&&>(f)(
+ static_cast<X&&>(x),
+ static_cast<Z&&>(z)
+ ),
+ static_cast<K&&>(k)
+ );
+ }
+ };
+
+ template <typename End, typename M, typename F>
+ struct monadic_foldr1_helper {
+ F f;
+ template <typename X, typename Y>
+ constexpr decltype(auto) operator()(X&& x, Y&& y) const
+ { return f(static_cast<X&&>(x), static_cast<Y&&>(y)); }
+ template <typename X>
+ constexpr decltype(auto) operator()(X&& x, End) const
+ { return hana::lift<M>(static_cast<X&&>(x)); }
+ };
+ }
+
+ template <typename T, bool condition>
+ struct monadic_fold_right_impl<T, when<condition>> : default_ {
+ // with state
+ template <typename M, typename Xs, typename S, typename F>
+ static constexpr decltype(auto) apply(Xs&& xs, S&& s, F&& f) {
+ return hana::fold_left(
+ static_cast<Xs&&>(xs),
+ hana::lift<M>,
+ hana::curry<3>(hana::partial(
+ detail::foldrM_helper{}, static_cast<F&&>(f)
+ ))
+ )(static_cast<S&&>(s));
+ }
+
+ // without state
+ template <typename M, typename Xs, typename F>
+ static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
+ struct end { };
+ using G = detail::monadic_foldr1_helper<end, M, typename std::decay<F>::type>;
+ decltype(auto) result = hana::monadic_fold_right<M>(
+ static_cast<Xs&&>(xs),
+ end{},
+ G{static_cast<F&&>(f)}
+ );
+
+ static_assert(!std::is_same<
+ std::remove_reference_t<decltype(result)>,
+ decltype(hana::lift<M>(end{}))
+ >{},
+ "hana::monadic_fold_right<M>(xs, f) requires 'xs' to be non-empty");
+ return result;
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_MONADIC_FOLD_RIGHT_HPP
diff --git a/boost/hana/mult.hpp b/boost/hana/mult.hpp
new file mode 100644
index 0000000000..248607bc1d
--- /dev/null
+++ b/boost/hana/mult.hpp
@@ -0,0 +1,107 @@
+/*!
+@file
+Defines `boost::hana::mult`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_MULT_HPP
+#define BOOST_HANA_MULT_HPP
+
+#include <boost/hana/fwd/mult.hpp>
+
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/ring.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/canonical_constant.hpp>
+#include <boost/hana/detail/has_common_embedding.hpp>
+#include <boost/hana/value.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename X, typename Y>
+ constexpr decltype(auto) mult_t::operator()(X&& x, Y&& y) const {
+ using T = typename hana::tag_of<X>::type;
+ using U = typename hana::tag_of<Y>::type;
+ using Mult = BOOST_HANA_DISPATCH_IF(decltype(mult_impl<T, U>{}),
+ hana::Ring<T>::value &&
+ hana::Ring<U>::value &&
+ !is_default<mult_impl<T, U>>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Ring<T>::value,
+ "hana::mult(x, y) requires 'x' to be in a Ring");
+
+ static_assert(hana::Ring<U>::value,
+ "hana::mult(x, y) requires 'y' to be in a Ring");
+
+ static_assert(!is_default<mult_impl<T, U>>::value,
+ "hana::mult(x, y) requires 'x' and 'y' to be embeddable "
+ "in a common Ring");
+ #endif
+
+ return Mult::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
+ }
+ //! @endcond
+
+ template <typename T, typename U, bool condition>
+ struct mult_impl<T, U, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+
+ // Cross-type overload
+ template <typename T, typename U>
+ struct mult_impl<T, U, when<
+ detail::has_nontrivial_common_embedding<Ring, T, U>::value
+ >> {
+ using C = typename common<T, U>::type;
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y) {
+ return hana::mult(hana::to<C>(static_cast<X&&>(x)),
+ hana::to<C>(static_cast<Y&&>(y)));
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for non-boolean arithmetic data types
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T>
+ struct mult_impl<T, T, when<std::is_arithmetic<T>::value &&
+ !std::is_same<bool, T>::value>> {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y)
+ { return static_cast<X&&>(x) * static_cast<Y&&>(y); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for Constants over a Ring
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <typename C, typename X, typename Y>
+ struct constant_from_mult {
+ static constexpr auto value = hana::mult(hana::value<X>(), hana::value<Y>());
+ using hana_tag = detail::CanonicalConstant<typename C::value_type>;
+ };
+ }
+
+ template <typename C>
+ struct mult_impl<C, C, when<
+ hana::Constant<C>::value &&
+ Ring<typename C::value_type>::value
+ >> {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X const&, Y const&)
+ { return hana::to<C>(detail::constant_from_mult<C, X, Y>{}); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_MULT_HPP
diff --git a/boost/hana/negate.hpp b/boost/hana/negate.hpp
new file mode 100644
index 0000000000..f0986f6fac
--- /dev/null
+++ b/boost/hana/negate.hpp
@@ -0,0 +1,61 @@
+/*!
+@file
+Defines `boost::hana::negate`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_NEGATE_HPP
+#define BOOST_HANA_NEGATE_HPP
+
+#include <boost/hana/fwd/negate.hpp>
+
+#include <boost/hana/concept/group.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/fwd/minus.hpp>
+#include <boost/hana/zero.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename X>
+ constexpr decltype(auto) negate_t::operator()(X&& x) const {
+ using G = typename hana::tag_of<X>::type;
+ using Negate = BOOST_HANA_DISPATCH_IF(negate_impl<G>,
+ hana::Group<G>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Group<G>::value,
+ "hana::negate(x) requires 'x' to be in a Group");
+ #endif
+
+ return Negate::apply(static_cast<X&&>(x));
+ }
+ //! @endcond
+
+ template <typename T, bool condition>
+ struct negate_impl<T, when<condition>> : default_ {
+ template <typename X>
+ static constexpr decltype(auto) apply(X&& x)
+ { return hana::minus(hana::zero<T>(), static_cast<X&&>(x)); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for arithmetic data types
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T>
+ struct negate_impl<T, when<std::is_arithmetic<T>::value &&
+ !std::is_same<bool, T>::value>> {
+ template <typename X>
+ static constexpr decltype(auto) apply(X&& x)
+ { return -static_cast<X&&>(x); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_NEGATE_HPP
diff --git a/boost/hana/none.hpp b/boost/hana/none.hpp
new file mode 100644
index 0000000000..2079fc2efb
--- /dev/null
+++ b/boost/hana/none.hpp
@@ -0,0 +1,48 @@
+/*!
+@file
+Defines `boost::hana::none`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_NONE_HPP
+#define BOOST_HANA_NONE_HPP
+
+#include <boost/hana/fwd/none.hpp>
+
+#include <boost/hana/concept/searchable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/functional/id.hpp>
+#include <boost/hana/none_of.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs>
+ constexpr auto none_t::operator()(Xs&& xs) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using None = BOOST_HANA_DISPATCH_IF(none_impl<S>,
+ hana::Searchable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Searchable<S>::value,
+ "hana::none(xs) requires 'xs' to be a Searchable");
+ #endif
+
+ return None::apply(static_cast<Xs&&>(xs));
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct none_impl<S, when<condition>> : default_ {
+ template <typename Xs>
+ static constexpr auto apply(Xs&& xs)
+ { return hana::none_of(static_cast<Xs&&>(xs), hana::id); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_NONE_HPP
diff --git a/boost/hana/none_of.hpp b/boost/hana/none_of.hpp
new file mode 100644
index 0000000000..2c1fbec1d0
--- /dev/null
+++ b/boost/hana/none_of.hpp
@@ -0,0 +1,50 @@
+/*!
+@file
+Defines `boost::hana::none_of`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_NONE_OF_HPP
+#define BOOST_HANA_NONE_OF_HPP
+
+#include <boost/hana/fwd/none_of.hpp>
+
+#include <boost/hana/any_of.hpp>
+#include <boost/hana/concept/searchable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/not.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Pred>
+ constexpr auto none_of_t::operator()(Xs&& xs, Pred&& pred) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using NoneOf = BOOST_HANA_DISPATCH_IF(none_of_impl<S>,
+ hana::Searchable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Searchable<S>::value,
+ "hana::none_of(xs, pred) requires 'xs' to be a Searchable");
+ #endif
+
+ return NoneOf::apply(static_cast<Xs&&>(xs), static_cast<Pred&&>(pred));
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct none_of_impl<S, when<condition>> : default_ {
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs&& xs, Pred&& pred) {
+ return hana::not_(hana::any_of(static_cast<Xs&&>(xs),
+ static_cast<Pred&&>(pred)));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_NONE_OF_HPP
diff --git a/boost/hana/not.hpp b/boost/hana/not.hpp
new file mode 100644
index 0000000000..87ff508b29
--- /dev/null
+++ b/boost/hana/not.hpp
@@ -0,0 +1,75 @@
+/*!
+@file
+Defines `boost::hana::not_`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_NOT_HPP
+#define BOOST_HANA_NOT_HPP
+
+#include <boost/hana/fwd/not.hpp>
+
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/logical.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/canonical_constant.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename X>
+ constexpr decltype(auto) not_t::operator()(X&& x) const {
+ using Bool = typename hana::tag_of<X>::type;
+ using Not = BOOST_HANA_DISPATCH_IF(hana::not_impl<Bool>,
+ hana::Logical<Bool>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Logical<Bool>::value,
+ "hana::not_(cond) requires 'cond' to be a Logical");
+ #endif
+
+ return Not::apply(static_cast<X&&>(x));
+ }
+ //! @endcond
+
+ template <typename L, bool condition>
+ struct not_impl<L, when<condition>> : hana::default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+
+ template <typename L>
+ struct not_impl<L, hana::when<std::is_arithmetic<L>::value>> {
+ template <typename Cond>
+ static constexpr Cond apply(Cond const& cond)
+ { return static_cast<Cond>(cond ? false : true); }
+ };
+
+ namespace detail {
+ template <typename C, typename X>
+ struct constant_from_not {
+ static constexpr auto value = hana::not_(hana::value<X>());
+ using hana_tag = detail::CanonicalConstant<typename C::value_type>;
+ };
+ }
+
+ template <typename C>
+ struct not_impl<C, hana::when<
+ hana::Constant<C>::value &&
+ hana::Logical<typename C::value_type>::value
+ >> {
+ template <typename Cond>
+ static constexpr auto apply(Cond const&)
+ { return hana::to<C>(detail::constant_from_not<C, Cond>{}); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_NOT_HPP
diff --git a/boost/hana/not_equal.hpp b/boost/hana/not_equal.hpp
new file mode 100644
index 0000000000..891bab7499
--- /dev/null
+++ b/boost/hana/not_equal.hpp
@@ -0,0 +1,59 @@
+/*!
+@file
+Defines `boost::hana::not_equal`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_NOT_EQUAL_HPP
+#define BOOST_HANA_NOT_EQUAL_HPP
+
+#include <boost/hana/fwd/not_equal.hpp>
+
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/has_common_embedding.hpp>
+#include <boost/hana/detail/nested_to.hpp> // required by fwd decl
+#include <boost/hana/equal.hpp>
+#include <boost/hana/not.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename X, typename Y>
+ constexpr auto not_equal_t::operator()(X&& x, Y&& y) const {
+ using T = typename hana::tag_of<X>::type;
+ using U = typename hana::tag_of<Y>::type;
+ using NotEqual = not_equal_impl<T, U>;
+ return NotEqual::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
+ }
+ //! @endcond
+
+ template <typename T, typename U, bool condition>
+ struct not_equal_impl<T, U, when<condition>> : default_ {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y) {
+ return hana::not_(hana::equal(static_cast<X&&>(x),
+ static_cast<Y&&>(y)));
+ }
+ };
+
+ // Cross-type overload
+ template <typename T, typename U>
+ struct not_equal_impl<T, U, when<
+ detail::has_nontrivial_common_embedding<Comparable, T, U>::value
+ >> {
+ using C = typename hana::common<T, U>::type;
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y) {
+ return hana::not_equal(hana::to<C>(static_cast<X&&>(x)),
+ hana::to<C>(static_cast<Y&&>(y)));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_NOT_EQUAL_HPP
diff --git a/boost/hana/one.hpp b/boost/hana/one.hpp
new file mode 100644
index 0000000000..47b902da60
--- /dev/null
+++ b/boost/hana/one.hpp
@@ -0,0 +1,79 @@
+/*!
+@file
+Defines `boost::hana::one`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_ONE_HPP
+#define BOOST_HANA_ONE_HPP
+
+#include <boost/hana/fwd/one.hpp>
+
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/ring.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/canonical_constant.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename R>
+ struct one_t {
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Ring<R>::value,
+ "hana::one<R>() requires 'R' to be a Ring");
+ #endif
+
+ constexpr decltype(auto) operator()() const {
+ using One = BOOST_HANA_DISPATCH_IF(one_impl<R>,
+ hana::Ring<R>::value
+ );
+
+ return One::apply();
+ }
+ };
+
+ template <typename R, bool condition>
+ struct one_impl<R, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for non-boolean arithmetic data types
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T>
+ struct one_impl<T, when<std::is_arithmetic<T>::value &&
+ !std::is_same<bool, T>::value>> {
+ static constexpr T apply()
+ { return static_cast<T>(1); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for Constants over a Ring
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <typename C>
+ struct constant_from_one {
+ static constexpr auto value = hana::one<typename C::value_type>();
+ using hana_tag = detail::CanonicalConstant<typename C::value_type>;
+ };
+ }
+
+ template <typename C>
+ struct one_impl<C, when<
+ hana::Constant<C>::value &&
+ Ring<typename C::value_type>::value
+ >> {
+ static constexpr decltype(auto) apply()
+ { return hana::to<C>(detail::constant_from_one<C>{}); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_ONE_HPP
diff --git a/boost/hana/optional.hpp b/boost/hana/optional.hpp
new file mode 100644
index 0000000000..772f90fbe0
--- /dev/null
+++ b/boost/hana/optional.hpp
@@ -0,0 +1,416 @@
+/*!
+@file
+Defines `boost::hana::optional`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_OPTIONAL_HPP
+#define BOOST_HANA_OPTIONAL_HPP
+
+#include <boost/hana/fwd/optional.hpp>
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/detail/operators/adl.hpp>
+#include <boost/hana/detail/operators/comparable.hpp>
+#include <boost/hana/detail/operators/monad.hpp>
+#include <boost/hana/detail/operators/orderable.hpp>
+#include <boost/hana/detail/wrong.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/fwd/any_of.hpp>
+#include <boost/hana/fwd/ap.hpp>
+#include <boost/hana/fwd/concat.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+#include <boost/hana/fwd/empty.hpp>
+#include <boost/hana/fwd/equal.hpp>
+#include <boost/hana/fwd/find_if.hpp>
+#include <boost/hana/fwd/flatten.hpp>
+#include <boost/hana/fwd/less.hpp>
+#include <boost/hana/fwd/lift.hpp>
+#include <boost/hana/fwd/transform.hpp>
+#include <boost/hana/fwd/type.hpp>
+#include <boost/hana/fwd/unpack.hpp>
+
+#include <cstddef> // std::nullptr_t
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //////////////////////////////////////////////////////////////////////////
+ // optional<>
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <typename T, typename = typename hana::tag_of<T>::type>
+ struct nested_type { };
+
+ template <typename T>
+ struct nested_type<T, type_tag> { using type = typename T::type; };
+ }
+
+ template <typename T>
+ struct optional<T> : detail::operators::adl<>, detail::nested_type<T> {
+ // 5.3.1, Constructors
+ constexpr optional() = default;
+ constexpr optional(optional const&) = default;
+ constexpr optional(optional&&) = default;
+
+ constexpr optional(T const& t)
+ : value_(t)
+ { }
+
+ constexpr optional(T&& t)
+ : value_(static_cast<T&&>(t))
+ { }
+
+ // 5.3.3, Assignment
+ constexpr optional& operator=(optional const&) = default;
+ constexpr optional& operator=(optional&&) = default;
+
+ // 5.3.5, Observers
+ constexpr T const* operator->() const { return &value_; }
+ constexpr T* operator->() { return &value_; }
+
+ constexpr T& value() & { return value_; }
+ constexpr T const& value() const& { return value_; }
+ constexpr T&& value() && { return static_cast<T&&>(value_); }
+ constexpr T const&& value() const&& { return static_cast<T const&&>(value_); }
+
+ constexpr T& operator*() & { return value_; }
+ constexpr T const& operator*() const& { return value_; }
+ constexpr T&& operator*() && { return static_cast<T&&>(value_); }
+ constexpr T const&& operator*() const&& { return static_cast<T const&&>(value_); }
+
+ template <typename U> constexpr T& value_or(U&&) & { return value_; }
+ template <typename U> constexpr T const& value_or(U&&) const& { return value_; }
+ template <typename U> constexpr T&& value_or(U&&) && { return static_cast<T&&>(value_); }
+ template <typename U> constexpr T const&& value_or(U&&) const&& { return static_cast<T const&&>(value_); }
+
+ // We leave this public because it simplifies the implementation, but
+ // this should be considered private by users.
+ T value_;
+ };
+
+ //! @cond
+ template <typename ...dummy>
+ constexpr auto optional<>::value() const {
+ static_assert(detail::wrong<dummy...>{},
+ "hana::optional::value() requires a non-empty optional");
+ }
+
+ template <typename ...dummy>
+ constexpr auto optional<>::operator*() const {
+ static_assert(detail::wrong<dummy...>{},
+ "hana::optional::operator* requires a non-empty optional");
+ }
+
+ template <typename U>
+ constexpr U&& optional<>::value_or(U&& u) const {
+ return static_cast<U&&>(u);
+ }
+
+ template <typename T>
+ constexpr auto make_just_t::operator()(T&& t) const {
+ return hana::optional<typename std::decay<T>::type>(static_cast<T&&>(t));
+ }
+ //! @endcond
+
+ template <typename ...T>
+ struct tag_of<optional<T...>> {
+ using type = optional_tag;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // make<optional_tag>
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct make_impl<optional_tag> {
+ template <typename X>
+ static constexpr auto apply(X&& x)
+ { return hana::just(static_cast<X&&>(x)); }
+
+ static constexpr auto apply()
+ { return hana::nothing; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Operators
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <>
+ struct comparable_operators<optional_tag> {
+ static constexpr bool value = true;
+ };
+ template <>
+ struct orderable_operators<optional_tag> {
+ static constexpr bool value = true;
+ };
+ template <>
+ struct monad_operators<optional_tag> {
+ static constexpr bool value = true;
+ };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // is_just and is_nothing
+ //////////////////////////////////////////////////////////////////////////
+ //! @cond
+ template <typename ...T>
+ constexpr auto is_just_t::operator()(optional<T...> const&) const
+ { return hana::bool_c<sizeof...(T) != 0>; }
+
+ template <typename ...T>
+ constexpr auto is_nothing_t::operator()(optional<T...> const&) const
+ { return hana::bool_c<sizeof...(T) == 0>; }
+ //! @endcond
+
+ //////////////////////////////////////////////////////////////////////////
+ // sfinae
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ struct sfinae_impl {
+ template <typename F, typename ...X, typename = decltype(
+ std::declval<F>()(std::declval<X>()...)
+ )>
+ constexpr decltype(auto) operator()(int, F&& f, X&& ...x) const {
+ using Return = decltype(static_cast<F&&>(f)(static_cast<X&&>(x)...));
+ static_assert(!std::is_same<Return, void>::value,
+ "hana::sfinae(f)(args...) requires f(args...) to be non-void");
+
+ return hana::just(static_cast<F&&>(f)(static_cast<X&&>(x)...));
+ }
+
+ template <typename F, typename ...X>
+ constexpr auto operator()(long, F&&, X&& ...) const
+ { return hana::nothing; }
+ };
+ }
+
+ //! @cond
+ template <typename F>
+ constexpr decltype(auto) sfinae_t::operator()(F&& f) const {
+ return hana::partial(detail::sfinae_impl{}, int{},
+ static_cast<F&&>(f));
+ }
+ //! @endcond
+
+ //////////////////////////////////////////////////////////////////////////
+ // Comparable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct equal_impl<optional_tag, optional_tag> {
+ template <typename T, typename U>
+ static constexpr auto apply(hana::optional<T> const& t, hana::optional<U> const& u)
+ { return hana::equal(t.value_, u.value_); }
+
+ static constexpr hana::true_ apply(hana::optional<> const&, hana::optional<> const&)
+ { return {}; }
+
+ template <typename T, typename U>
+ static constexpr hana::false_ apply(T const&, U const&)
+ { return {}; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Orderable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct less_impl<optional_tag, optional_tag> {
+ template <typename T>
+ static constexpr hana::true_ apply(hana::optional<> const&, hana::optional<T> const&)
+ { return {}; }
+
+ static constexpr hana::false_ apply(hana::optional<> const&, hana::optional<> const&)
+ { return {}; }
+
+ template <typename T>
+ static constexpr hana::false_ apply(hana::optional<T> const&, hana::optional<> const&)
+ { return {}; }
+
+ template <typename T, typename U>
+ static constexpr auto apply(hana::optional<T> const& x, hana::optional<U> const& y)
+ { return hana::less(x.value_, y.value_); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Functor
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct transform_impl<optional_tag> {
+ template <typename F>
+ static constexpr auto apply(optional<> const&, F&&)
+ { return hana::nothing; }
+
+ template <typename T, typename F>
+ static constexpr auto apply(optional<T> const& opt, F&& f)
+ { return hana::just(static_cast<F&&>(f)(opt.value_)); }
+
+ template <typename T, typename F>
+ static constexpr auto apply(optional<T>& opt, F&& f)
+ { return hana::just(static_cast<F&&>(f)(opt.value_)); }
+
+ template <typename T, typename F>
+ static constexpr auto apply(optional<T>&& opt, F&& f)
+ { return hana::just(static_cast<F&&>(f)(static_cast<T&&>(opt.value_))); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Applicative
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct lift_impl<optional_tag> {
+ template <typename X>
+ static constexpr auto apply(X&& x)
+ { return hana::just(static_cast<X&&>(x)); }
+ };
+
+ template <>
+ struct ap_impl<optional_tag> {
+ template <typename F, typename X>
+ static constexpr auto ap_helper(F&&, X&&, ...)
+ { return hana::nothing; }
+
+ template <typename F, typename X>
+ static constexpr auto ap_helper(F&& f, X&& x, hana::true_, hana::true_)
+ { return hana::just(static_cast<F&&>(f).value_(static_cast<X&&>(x).value_)); }
+
+ template <typename F, typename X>
+ static constexpr auto apply(F&& f, X&& x) {
+ return ap_impl::ap_helper(static_cast<F&&>(f), static_cast<X&&>(x),
+ hana::is_just(f), hana::is_just(x));
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Monad
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct flatten_impl<optional_tag> {
+ static constexpr auto apply(optional<> const&)
+ { return hana::nothing; }
+
+ static constexpr auto apply(optional<optional<>> const&)
+ { return hana::nothing; }
+
+ template <typename T>
+ static constexpr auto apply(optional<optional<T>> const& opt)
+ { return hana::just(opt.value_.value_); }
+
+ template <typename T>
+ static constexpr auto apply(optional<optional<T>>&& opt)
+ { return hana::just(static_cast<T&&>(opt.value_.value_)); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // MonadPlus
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct concat_impl<optional_tag> {
+ template <typename Y>
+ static constexpr auto apply(hana::optional<>&, Y&& y)
+ { return static_cast<Y&&>(y); }
+
+ template <typename Y>
+ static constexpr auto apply(hana::optional<>&&, Y&& y)
+ { return static_cast<Y&&>(y); }
+
+ template <typename Y>
+ static constexpr auto apply(hana::optional<> const&, Y&& y)
+ { return static_cast<Y&&>(y); }
+
+ template <typename X, typename Y>
+ static constexpr auto apply(X&& x, Y&&)
+ { return static_cast<X&&>(x); }
+ };
+
+ template <>
+ struct empty_impl<optional_tag> {
+ static constexpr auto apply()
+ { return hana::nothing; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Foldable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct unpack_impl<optional_tag> {
+ template <typename T, typename F>
+ static constexpr decltype(auto) apply(optional<T>&& opt, F&& f)
+ { return static_cast<F&&>(f)(static_cast<T&&>(opt.value_)); }
+
+ template <typename T, typename F>
+ static constexpr decltype(auto) apply(optional<T> const& opt, F&& f)
+ { return static_cast<F&&>(f)(opt.value_); }
+
+ template <typename T, typename F>
+ static constexpr decltype(auto) apply(optional<T>& opt, F&& f)
+ { return static_cast<F&&>(f)(opt.value_); }
+
+ template <typename F>
+ static constexpr decltype(auto) apply(optional<> const&, F&& f)
+ { return static_cast<F&&>(f)(); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Searchable
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <bool>
+ struct optional_find_if {
+ template <typename T>
+ static constexpr auto apply(T const&)
+ { return hana::nothing; }
+ };
+
+ template <>
+ struct optional_find_if<true> {
+ template <typename T>
+ static constexpr auto apply(T&& t)
+ { return hana::just(static_cast<T&&>(t)); }
+ };
+ }
+
+ template <>
+ struct find_if_impl<optional_tag> {
+ template <typename T, typename Pred>
+ static constexpr auto apply(hana::optional<T> const& opt, Pred&& pred) {
+ constexpr bool found = decltype(static_cast<Pred&&>(pred)(opt.value_))::value;
+ return detail::optional_find_if<found>::apply(opt.value_);
+ }
+
+ template <typename T, typename Pred>
+ static constexpr auto apply(hana::optional<T>& opt, Pred&& pred) {
+ constexpr bool found = decltype(static_cast<Pred&&>(pred)(opt.value_))::value;
+ return detail::optional_find_if<found>::apply(opt.value_);
+ }
+
+ template <typename T, typename Pred>
+ static constexpr auto apply(hana::optional<T>&& opt, Pred&& pred) {
+ constexpr bool found = decltype(
+ static_cast<Pred&&>(pred)(static_cast<T&&>(opt.value_))
+ )::value;
+ return detail::optional_find_if<found>::apply(static_cast<T&&>(opt.value_));
+ }
+
+ template <typename Pred>
+ static constexpr auto apply(hana::optional<> const&, Pred&&)
+ { return hana::nothing; }
+ };
+
+ template <>
+ struct any_of_impl<optional_tag> {
+ template <typename T, typename Pred>
+ static constexpr auto apply(hana::optional<T> const& opt, Pred&& pred)
+ { return static_cast<Pred&&>(pred)(opt.value_); }
+
+ template <typename Pred>
+ static constexpr hana::false_ apply(hana::optional<> const&, Pred&&)
+ { return {}; }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_OPTIONAL_HPP
diff --git a/boost/hana/or.hpp b/boost/hana/or.hpp
new file mode 100644
index 0000000000..a97510a474
--- /dev/null
+++ b/boost/hana/or.hpp
@@ -0,0 +1,61 @@
+/*!
+@file
+Defines `boost::hana::or_`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_OR_HPP
+#define BOOST_HANA_OR_HPP
+
+#include <boost/hana/fwd/or.hpp>
+
+#include <boost/hana/concept/logical.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/variadic/foldl1.hpp>
+#include <boost/hana/if.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename X, typename Y>
+ constexpr decltype(auto) or_t::operator()(X&& x, Y&& y) const {
+ using Bool = typename hana::tag_of<X>::type;
+ using Or = BOOST_HANA_DISPATCH_IF(or_impl<Bool>,
+ hana::Logical<Bool>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Logical<Bool>::value,
+ "hana::or_(x, y) requires 'x' to be a Logical");
+ #endif
+
+ return Or::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
+ }
+
+ template <typename X, typename ...Y>
+ constexpr decltype(auto) or_t::operator()(X&& x, Y&& ...y) const {
+ return detail::variadic::foldl1(
+ *this,
+ static_cast<X&&>(x),
+ static_cast<Y&&>(y)...
+ );
+ }
+ //! @endcond
+
+ template <typename L, bool condition>
+ struct or_impl<L, when<condition>> : hana::default_ {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y) {
+ //! @todo How to forward `x` here? Since the arguments to `if_`
+ //! can be evaluated in any order, we have to be careful not to
+ //! use `x` in a moved-from state.
+ return hana::if_(x, x, static_cast<Y&&>(y));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_OR_HPP
diff --git a/boost/hana/ordering.hpp b/boost/hana/ordering.hpp
new file mode 100644
index 0000000000..dfd94239f6
--- /dev/null
+++ b/boost/hana/ordering.hpp
@@ -0,0 +1,45 @@
+/*!
+@file
+Defines `boost::hana::ordering`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_ORDERING_HPP
+#define BOOST_HANA_ORDERING_HPP
+
+#include <boost/hana/fwd/ordering.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/less.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace detail {
+ template <typename F>
+ struct less_by {
+ F f;
+
+ template <typename X, typename Y>
+ constexpr decltype(auto) operator()(X&& x, Y&& y) const&
+ { return hana::less(f(static_cast<X&&>(x)), f(static_cast<Y&&>(y))); }
+
+ template <typename X, typename Y>
+ constexpr decltype(auto) operator()(X&& x, Y&& y) &
+ { return hana::less(f(static_cast<X&&>(x)), f(static_cast<Y&&>(y))); }
+ };
+ }
+
+ //! @cond
+ template <typename F>
+ constexpr auto ordering_t::operator()(F&& f) const {
+ return detail::less_by<typename std::decay<F>::type>{static_cast<F&&>(f)};
+ }
+ //! @endcond
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_ORDERING_HPP
diff --git a/boost/hana/pair.hpp b/boost/hana/pair.hpp
new file mode 100644
index 0000000000..5a4bf87e23
--- /dev/null
+++ b/boost/hana/pair.hpp
@@ -0,0 +1,147 @@
+/*!
+@file
+Defines `boost::hana::pair`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_PAIR_HPP
+#define BOOST_HANA_PAIR_HPP
+
+#include <boost/hana/fwd/pair.hpp>
+
+#include <boost/hana/basic_tuple.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/decay.hpp>
+#include <boost/hana/detail/intrinsics.hpp>
+#include <boost/hana/detail/operators/adl.hpp>
+#include <boost/hana/detail/operators/comparable.hpp>
+#include <boost/hana/detail/operators/orderable.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+#include <boost/hana/fwd/first.hpp>
+#include <boost/hana/fwd/second.hpp>
+
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //////////////////////////////////////////////////////////////////////////
+ // pair
+ //////////////////////////////////////////////////////////////////////////
+ //! @cond
+ template <typename First, typename Second>
+ struct pair : detail::operators::adl<pair<First, Second>> {
+ template <typename ...dummy, typename = typename std::enable_if<
+ BOOST_HANA_TT_IS_CONSTRUCTIBLE(First, dummy...) &&
+ BOOST_HANA_TT_IS_CONSTRUCTIBLE(Second, dummy...)
+ >::type>
+ constexpr pair()
+ : storage_()
+ { }
+
+ template <typename ...dummy, typename = typename std::enable_if<
+ BOOST_HANA_TT_IS_CONSTRUCTIBLE(First, First const&, dummy...) &&
+ BOOST_HANA_TT_IS_CONSTRUCTIBLE(Second, Second const&, dummy...)
+ >::type>
+ constexpr pair(First const& first, Second const& second)
+ : storage_{first, second}
+ { }
+
+ template <typename T, typename U, typename = typename std::enable_if<
+ BOOST_HANA_TT_IS_CONVERTIBLE(T&&, First) &&
+ BOOST_HANA_TT_IS_CONVERTIBLE(U&&, Second)
+ >::type>
+ constexpr pair(T&& t, U&& u)
+ : storage_{static_cast<T&&>(t), static_cast<U&&>(u)}
+ { }
+
+ template <typename T, typename U, typename = typename std::enable_if<
+ BOOST_HANA_TT_IS_CONVERTIBLE(T const&, First) &&
+ BOOST_HANA_TT_IS_CONVERTIBLE(U const&, Second)
+ >::type>
+ constexpr pair(pair<T, U> const& other)
+ : storage_{hana::get_impl<0>(other.storage_),
+ hana::get_impl<1>(other.storage_)}
+ { }
+
+ template <typename T, typename U, typename = typename std::enable_if<
+ BOOST_HANA_TT_IS_CONVERTIBLE(T&&, First) &&
+ BOOST_HANA_TT_IS_CONVERTIBLE(U&&, Second)
+ >::type>
+ constexpr pair(pair<T, U>&& other)
+ : storage_{static_cast<T&&>(hana::get_impl<0>(other.storage_)),
+ static_cast<U&&>(hana::get_impl<1>(other.storage_))}
+ { }
+
+ template <typename T, typename U, typename = typename std::enable_if<
+ BOOST_HANA_TT_IS_ASSIGNABLE(First&, T const&) &&
+ BOOST_HANA_TT_IS_ASSIGNABLE(Second&, U const&)
+ >::type>
+ constexpr pair& operator=(pair<T, U> const& other) {
+ hana::get_impl<0>(storage_) = hana::get_impl<0>(other.storage_);
+ hana::get_impl<1>(storage_) = hana::get_impl<1>(other.storage_);
+ return *this;
+ }
+
+ template <typename T, typename U, typename = typename std::enable_if<
+ BOOST_HANA_TT_IS_ASSIGNABLE(First&, T&&) &&
+ BOOST_HANA_TT_IS_ASSIGNABLE(Second&, U&&)
+ >::type>
+ constexpr pair& operator=(pair<T, U>&& other) {
+ hana::get_impl<0>(storage_) = static_cast<T&&>(hana::get_impl<0>(other.storage_));
+ hana::get_impl<1>(storage_) = static_cast<U&&>(hana::get_impl<1>(other.storage_));
+ return *this;
+ }
+
+ using hana_tag = pair_tag;
+ basic_tuple<First, Second> storage_;
+ };
+ //! @endcond
+
+ //////////////////////////////////////////////////////////////////////////
+ // Operators
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <>
+ struct comparable_operators<pair_tag> {
+ static constexpr bool value = true;
+ };
+ template <>
+ struct orderable_operators<pair_tag> {
+ static constexpr bool value = true;
+ };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Product
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct make_impl<pair_tag> {
+ template <typename F, typename S>
+ static constexpr pair<
+ typename detail::decay<F>::type,
+ typename detail::decay<S>::type
+ > apply(F&& f, S&& s) {
+ return {static_cast<F&&>(f), static_cast<S&&>(s)};
+ }
+ };
+
+ template <>
+ struct first_impl<pair_tag> {
+ template <typename P>
+ static constexpr decltype(auto) apply(P&& p)
+ { return hana::get_impl<0>(static_cast<P&&>(p).storage_); }
+ };
+
+ template <>
+ struct second_impl<pair_tag> {
+ template <typename P>
+ static constexpr decltype(auto) apply(P&& p)
+ { return hana::get_impl<1>(static_cast<P&&>(p).storage_); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_PAIR_HPP
diff --git a/boost/hana/partition.hpp b/boost/hana/partition.hpp
new file mode 100644
index 0000000000..00ce243081
--- /dev/null
+++ b/boost/hana/partition.hpp
@@ -0,0 +1,116 @@
+/*!
+@file
+Defines `boost::hana::partition`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_PARTITION_HPP
+#define BOOST_HANA_PARTITION_HPP
+
+#include <boost/hana/fwd/partition.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/detail/algorithm.hpp>
+#include <boost/hana/detail/array.hpp>
+#include <boost/hana/detail/decay.hpp>
+#include <boost/hana/detail/nested_by.hpp> // required by fwd decl
+#include <boost/hana/pair.hpp>
+#include <boost/hana/unpack.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Pred>
+ constexpr auto partition_t::operator()(Xs&& xs, Pred&& pred) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Partition = BOOST_HANA_DISPATCH_IF(partition_impl<S>,
+ hana::Sequence<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::partition(xs, pred) requires 'xs' to be a Sequence");
+ #endif
+
+ return Partition::apply(static_cast<Xs&&>(xs), static_cast<Pred&&>(pred));
+ }
+ //! @endcond
+
+ namespace detail {
+ template <bool ...B>
+ struct partition_indices {
+ static constexpr bool results[] = {B..., false}; // avoid empty array
+ static constexpr std::size_t left_size =
+ detail::count(results, results + sizeof...(B), true);
+ static constexpr std::size_t right_size = sizeof...(B) - left_size;
+
+ static constexpr auto compute_left() {
+ detail::array<std::size_t, left_size> indices{};
+ std::size_t* left = &indices[0];
+ for (std::size_t i = 0; i < sizeof...(B); ++i)
+ if (results[i])
+ *left++ = i;
+ return indices;
+ }
+
+ static constexpr auto compute_right() {
+ detail::array<std::size_t, right_size> indices{};
+ std::size_t* right = &indices[0];
+ for (std::size_t i = 0; i < sizeof...(B); ++i)
+ if (!results[i])
+ *right++ = i;
+ return indices;
+ }
+
+ static constexpr auto left = compute_left();
+ static constexpr auto right = compute_right();
+
+ template <typename S, typename Xs, std::size_t ...l, std::size_t ...r>
+ static constexpr auto apply(Xs&& xs, std::index_sequence<l...>,
+ std::index_sequence<r...>)
+ {
+ return hana::make<hana::pair_tag>(
+ hana::make<S>(hana::at_c<left[l]>(static_cast<Xs&&>(xs))...),
+ hana::make<S>(hana::at_c<right[r]>(static_cast<Xs&&>(xs))...)
+ );
+ }
+ };
+
+ template <typename Pred>
+ struct deduce_partition_indices {
+ template <typename ...Xs>
+ auto operator()(Xs&& ...xs) const -> detail::partition_indices<
+ static_cast<bool>(detail::decay<
+ decltype(std::declval<Pred>()(static_cast<Xs&&>(xs)))
+ >::type::value)...
+ > { return {}; }
+ };
+ }
+
+ template <typename S, bool condition>
+ struct partition_impl<S, when<condition>> : default_ {
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs&& xs, Pred&&) {
+ using Indices = decltype(hana::unpack(
+ static_cast<Xs&&>(xs), detail::deduce_partition_indices<Pred&&>{}
+ ));
+ return Indices::template apply<S>(
+ static_cast<Xs&&>(xs),
+ std::make_index_sequence<Indices::left_size>{},
+ std::make_index_sequence<Indices::right_size>{}
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_PARTITION_HPP
diff --git a/boost/hana/permutations.hpp b/boost/hana/permutations.hpp
new file mode 100644
index 0000000000..52052ff03d
--- /dev/null
+++ b/boost/hana/permutations.hpp
@@ -0,0 +1,78 @@
+/*!
+@file
+Defines `boost::hana::permutations`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_PERMUTATIONS_HPP
+#define BOOST_HANA_PERMUTATIONS_HPP
+
+#include <boost/hana/fwd/permutations.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/detail/array.hpp>
+#include <boost/hana/length.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs>
+ constexpr auto permutations_t::operator()(Xs&& xs) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Permutations = BOOST_HANA_DISPATCH_IF(permutations_impl<S>,
+ hana::Sequence<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::permutations(xs) requires 'xs' to be a Sequence");
+ #endif
+
+ return Permutations::apply(static_cast<Xs&&>(xs));
+ }
+ //! @endcond
+
+ namespace detail {
+ template <std::size_t N>
+ struct permutation_indices {
+ static constexpr auto value =
+ detail::array<std::size_t, N>{}.iota(0).permutations();
+ };
+ }
+
+ template <typename S, bool condition>
+ struct permutations_impl<S, when<condition>> : default_ {
+ template <std::size_t n, typename Xs, std::size_t ...i>
+ static constexpr auto
+ nth_permutation(Xs const& xs, std::index_sequence<i...>) {
+ constexpr auto indices = detail::permutation_indices<sizeof...(i)>::value;
+ (void)indices; // workaround GCC warning when sizeof...(i) == 0
+ return hana::make<S>(hana::at_c<indices[n][i]>(xs)...);
+ }
+
+ template <std::size_t N, typename Xs, std::size_t ...n>
+ static constexpr auto
+ permutations_helper(Xs const& xs, std::index_sequence<n...>) {
+ return hana::make<S>(nth_permutation<n>(xs, std::make_index_sequence<N>{})...);
+ }
+
+ template <typename Xs>
+ static constexpr auto apply(Xs const& xs) {
+ constexpr std::size_t N = decltype(hana::length(xs))::value;
+ constexpr std::size_t total_perms = detail::factorial(N);
+ return permutations_helper<N>(xs, std::make_index_sequence<total_perms>{});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_PERMUTATIONS_HPP
diff --git a/boost/hana/plus.hpp b/boost/hana/plus.hpp
new file mode 100644
index 0000000000..65a2cc99d5
--- /dev/null
+++ b/boost/hana/plus.hpp
@@ -0,0 +1,109 @@
+/*!
+@file
+Defines `boost::hana::plus`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_PLUS_HPP
+#define BOOST_HANA_PLUS_HPP
+
+#include <boost/hana/fwd/plus.hpp>
+
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/monoid.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/common.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/canonical_constant.hpp>
+#include <boost/hana/detail/has_common_embedding.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename X, typename Y>
+ constexpr decltype(auto) plus_t::operator()(X&& x, Y&& y) const {
+ using T = typename hana::tag_of<X>::type;
+ using U = typename hana::tag_of<Y>::type;
+ using Plus = BOOST_HANA_DISPATCH_IF(decltype(plus_impl<T, U>{}),
+ hana::Monoid<T>::value &&
+ hana::Monoid<U>::value &&
+ !is_default<plus_impl<T, U>>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Monoid<T>::value,
+ "hana::plus(x, y) requires 'x' to be a Monoid");
+
+ static_assert(hana::Monoid<U>::value,
+ "hana::plus(x, y) requires 'y' to be a Monoid");
+
+ static_assert(!is_default<plus_impl<T, U>>::value,
+ "hana::plus(x, y) requires 'x' and 'y' to be embeddable "
+ "in a common Monoid");
+ #endif
+
+ return Plus::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
+ }
+ //! @endcond
+
+ template <typename T, typename U, bool condition>
+ struct plus_impl<T, U, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+
+ // Cross-type overload
+ template <typename T, typename U>
+ struct plus_impl<T, U, when<
+ detail::has_nontrivial_common_embedding<Monoid, T, U>::value
+ >> {
+ using C = typename common<T, U>::type;
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y) {
+ return hana::plus(hana::to<C>(static_cast<X&&>(x)),
+ hana::to<C>(static_cast<Y&&>(y)));
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for non-boolean arithmetic data types
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T>
+ struct plus_impl<T, T, when<
+ std::is_arithmetic<T>::value &&
+ !std::is_same<T, bool>::value
+ >> {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X&& x, Y&& y)
+ { return static_cast<X&&>(x) + static_cast<Y&&>(y); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for Constants over a Monoid
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <typename C, typename X, typename Y>
+ struct constant_from_plus {
+ static constexpr auto value = hana::plus(hana::value<X>(), hana::value<Y>());
+ using hana_tag = detail::CanonicalConstant<typename C::value_type>;
+ };
+ }
+
+ template <typename C>
+ struct plus_impl<C, C, when<
+ hana::Constant<C>::value &&
+ Monoid<typename C::value_type>::value
+ >> {
+ template <typename X, typename Y>
+ static constexpr decltype(auto) apply(X const&, Y const&)
+ { return hana::to<C>(detail::constant_from_plus<C, X, Y>{}); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_PLUS_HPP
diff --git a/boost/hana/power.hpp b/boost/hana/power.hpp
new file mode 100644
index 0000000000..b6f6de10a9
--- /dev/null
+++ b/boost/hana/power.hpp
@@ -0,0 +1,65 @@
+/*!
+@file
+Defines `boost::hana::power`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_POWER_HPP
+#define BOOST_HANA_POWER_HPP
+
+#include <boost/hana/fwd/power.hpp>
+
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/concept/ring.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/functional/iterate.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/mult.hpp>
+#include <boost/hana/one.hpp>
+
+#include <cstddef>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename X, typename N>
+ constexpr decltype(auto) power_t::operator()(X&& x, N const& n) const {
+ using R = typename hana::tag_of<X>::type;
+ using Power = BOOST_HANA_DISPATCH_IF(power_impl<R>,
+ hana::Ring<R>::value &&
+ hana::IntegralConstant<N>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Ring<R>::value,
+ "hana::power(x, n) requires 'x' to be in a Ring");
+
+ static_assert(hana::IntegralConstant<N>::value,
+ "hana::power(x, n) requires 'n' to be an IntegralConstant");
+ #endif
+
+ static_assert(N::value >= 0,
+ "hana::power(x, n) requires 'n' to be non-negative");
+
+ return Power::apply(static_cast<X&&>(x), n);
+ }
+ //! @endcond
+
+ template <typename R, bool condition>
+ struct power_impl<R, when<condition>> : default_ {
+ template <typename X, typename N>
+ static constexpr decltype(auto) apply(X&& x, N const&) {
+ constexpr std::size_t n = N::value;
+ return hana::iterate<n>(
+ hana::partial(hana::mult, static_cast<X&&>(x)),
+ hana::one<R>()
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_POWER_HPP
diff --git a/boost/hana/prefix.hpp b/boost/hana/prefix.hpp
new file mode 100644
index 0000000000..64f3bfb984
--- /dev/null
+++ b/boost/hana/prefix.hpp
@@ -0,0 +1,52 @@
+/*!
+@file
+Defines `boost::hana::prefix`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_PREFIX_HPP
+#define BOOST_HANA_PREFIX_HPP
+
+#include <boost/hana/fwd/prefix.hpp>
+
+#include <boost/hana/append.hpp>
+#include <boost/hana/chain.hpp>
+#include <boost/hana/concept/monad_plus.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/lift.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Pref>
+ constexpr auto prefix_t::operator()(Xs&& xs, Pref&& pref) const {
+ using M = typename hana::tag_of<Xs>::type;
+ using Prefix = BOOST_HANA_DISPATCH_IF(prefix_impl<M>,
+ hana::MonadPlus<M>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::MonadPlus<M>::value,
+ "hana::prefix(xs, pref) requires 'xs' to be a MonadPlus");
+ #endif
+
+ return Prefix::apply(static_cast<Xs&&>(xs), static_cast<Pref&&>(pref));
+ }
+ //! @endcond
+
+ template <typename M, bool condition>
+ struct prefix_impl<M, when<condition>> : default_ {
+ template <typename Xs, typename Z>
+ static constexpr decltype(auto) apply(Xs&& xs, Z&& z) {
+ return hana::chain(static_cast<Xs&&>(xs),
+ hana::partial(hana::append, hana::lift<M>(static_cast<Z&&>(z))));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_PREFIX_HPP
diff --git a/boost/hana/prepend.hpp b/boost/hana/prepend.hpp
new file mode 100644
index 0000000000..c4f5f0e0e3
--- /dev/null
+++ b/boost/hana/prepend.hpp
@@ -0,0 +1,74 @@
+/*!
+@file
+Defines `boost::hana::prepend`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_PREPEND_HPP
+#define BOOST_HANA_PREPEND_HPP
+
+#include <boost/hana/fwd/prepend.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concat.hpp>
+#include <boost/hana/concept/monad_plus.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/lift.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename X>
+ constexpr auto prepend_t::operator()(Xs&& xs, X&& x) const {
+ using M = typename hana::tag_of<Xs>::type;
+ using Prepend = BOOST_HANA_DISPATCH_IF(prepend_impl<M>,
+ hana::MonadPlus<M>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::MonadPlus<M>::value,
+ "hana::prepend(xs, x) requires 'xs' to be a MonadPlus");
+ #endif
+
+ return Prepend::apply(static_cast<Xs&&>(xs), static_cast<X&&>(x));
+ }
+ //! @endcond
+
+ template <typename M, bool condition>
+ struct prepend_impl<M, when<condition>> : default_ {
+ template <typename Xs, typename X>
+ static constexpr auto apply(Xs&& xs, X&& x) {
+ return hana::concat(hana::lift<M>(static_cast<X&&>(x)),
+ static_cast<Xs&&>(xs));
+ }
+ };
+
+ template <typename S>
+ struct prepend_impl<S, when<Sequence<S>::value>> {
+ template <typename Xs, typename X, std::size_t ...i>
+ static constexpr auto prepend_helper(Xs&& xs, X&& x, std::index_sequence<i...>) {
+ return hana::make<S>(
+ static_cast<X&&>(x), hana::at_c<i>(static_cast<Xs&&>(xs))...
+ );
+ }
+
+ template <typename Xs, typename X>
+ static constexpr auto apply(Xs&& xs, X&& x) {
+ constexpr std::size_t N = decltype(hana::length(xs))::value;
+ return prepend_helper(static_cast<Xs&&>(xs), static_cast<X&&>(x),
+ std::make_index_sequence<N>{});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_PREPEND_HPP
diff --git a/boost/hana/product.hpp b/boost/hana/product.hpp
new file mode 100644
index 0000000000..e6e584205a
--- /dev/null
+++ b/boost/hana/product.hpp
@@ -0,0 +1,58 @@
+/*!
+@file
+Defines `boost::hana::product`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_PRODUCT_HPP
+#define BOOST_HANA_PRODUCT_HPP
+
+#include <boost/hana/fwd/product.hpp>
+
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/concept/ring.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/fold_left.hpp>
+#include <boost/hana/integral_constant.hpp> // required by fwd decl
+#include <boost/hana/mult.hpp>
+#include <boost/hana/one.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename R>
+ struct product_t {
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Ring<R>::value,
+ "hana::product<R> requires 'R' to be a Ring");
+ #endif
+
+ template <typename Xs>
+ constexpr decltype(auto) operator()(Xs&& xs) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Product = BOOST_HANA_DISPATCH_IF(product_impl<S>,
+ hana::Foldable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Foldable<S>::value,
+ "hana::product<R>(xs) requires 'xs' to be Foldable");
+ #endif
+
+ return Product::template apply<R>(static_cast<Xs&&>(xs));
+ }
+ };
+
+ template <typename T, bool condition>
+ struct product_impl<T, when<condition>> : default_ {
+ template <typename R, typename Xs>
+ static constexpr decltype(auto) apply(Xs&& xs) {
+ return hana::fold_left(static_cast<Xs&&>(xs), hana::one<R>(), hana::mult);
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_PRODUCT_HPP
diff --git a/boost/hana/range.hpp b/boost/hana/range.hpp
new file mode 100644
index 0000000000..ecddc7da8e
--- /dev/null
+++ b/boost/hana/range.hpp
@@ -0,0 +1,294 @@
+/*!
+@file
+Defines `boost::hana::range`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_RANGE_HPP
+#define BOOST_HANA_RANGE_HPP
+
+#include <boost/hana/fwd/range.hpp>
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/common.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/detail/operators/adl.hpp>
+#include <boost/hana/detail/operators/comparable.hpp>
+#include <boost/hana/detail/operators/iterable.hpp>
+#include <boost/hana/fwd/at.hpp>
+#include <boost/hana/fwd/back.hpp>
+#include <boost/hana/fwd/contains.hpp>
+#include <boost/hana/fwd/drop_front.hpp>
+#include <boost/hana/fwd/drop_front_exactly.hpp>
+#include <boost/hana/fwd/equal.hpp>
+#include <boost/hana/fwd/find.hpp>
+#include <boost/hana/fwd/front.hpp>
+#include <boost/hana/fwd/is_empty.hpp>
+#include <boost/hana/fwd/length.hpp>
+#include <boost/hana/fwd/maximum.hpp>
+#include <boost/hana/fwd/minimum.hpp>
+#include <boost/hana/fwd/product.hpp>
+#include <boost/hana/fwd/sum.hpp>
+#include <boost/hana/fwd/unpack.hpp>
+#include <boost/hana/integral_constant.hpp> // required by fwd decl and below
+#include <boost/hana/optional.hpp>
+#include <boost/hana/value.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //////////////////////////////////////////////////////////////////////////
+ // range<>
+ //////////////////////////////////////////////////////////////////////////
+ //! @cond
+ template <typename T, T From, T To>
+ struct range
+ : detail::operators::adl<range<T, From, To>>
+ , detail::iterable_operators<range<T, From, To>>
+ {
+ static_assert(From <= To,
+ "hana::make_range(from, to) requires 'from <= to'");
+
+ using value_type = T;
+ static constexpr value_type from = From;
+ static constexpr value_type to = To;
+ };
+ //! @endcond
+
+ template <typename T, T From, T To>
+ struct tag_of<range<T, From, To>> {
+ using type = range_tag;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // make<range_tag>
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct make_impl<range_tag> {
+ template <typename From, typename To>
+ static constexpr auto apply(From const&, To const&) {
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::IntegralConstant<From>::value,
+ "hana::make_range(from, to) requires 'from' to be an IntegralConstant");
+
+ static_assert(hana::IntegralConstant<To>::value,
+ "hana::make_range(from, to) requires 'to' to be an IntegralConstant");
+ #endif
+
+ using T = typename common<
+ typename hana::tag_of<From>::type::value_type,
+ typename hana::tag_of<To>::type::value_type
+ >::type;
+ constexpr T from = hana::to<T>(From::value);
+ constexpr T to = hana::to<T>(To::value);
+ return range<T, from, to>{};
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Operators
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <>
+ struct comparable_operators<range_tag> {
+ static constexpr bool value = true;
+ };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Comparable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct equal_impl<range_tag, range_tag> {
+ template <typename R1, typename R2>
+ static constexpr auto apply(R1 const&, R2 const&) {
+ return hana::bool_c<
+ (R1::from == R1::to && R2::from == R2::to) ||
+ (R1::from == R2::from && R1::to == R2::to)
+ >;
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Foldable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct unpack_impl<range_tag> {
+ template <typename T, T from, typename F, T ...v>
+ static constexpr decltype(auto)
+ unpack_helper(F&& f, std::integer_sequence<T, v...>) {
+ return static_cast<F&&>(f)(integral_constant<T, from + v>{}...);
+ }
+
+ template <typename T, T from, T to, typename F>
+ static constexpr decltype(auto) apply(range<T, from, to> const&, F&& f) {
+ return unpack_helper<T, from>(static_cast<F&&>(f),
+ std::make_integer_sequence<T, to - from>{});
+ }
+ };
+
+ template <>
+ struct length_impl<range_tag> {
+ template <typename T, T from, T to>
+ static constexpr auto apply(range<T, from, to> const&)
+ { return hana::size_c<static_cast<std::size_t>(to - from)>; }
+ };
+
+ template <>
+ struct minimum_impl<range_tag> {
+ template <typename T, T from, T to>
+ static constexpr auto apply(range<T, from, to> const&)
+ { return integral_c<T, from>; }
+ };
+
+ template <>
+ struct maximum_impl<range_tag> {
+ template <typename T, T from, T to>
+ static constexpr auto apply(range<T, from, to> const&)
+ { return integral_c<T, to-1>; }
+ };
+
+ template <>
+ struct sum_impl<range_tag> {
+ // Returns the sum of `[m, n]`, where `m <= n` always hold.
+ template <typename I>
+ static constexpr I sum_helper(I m, I n) {
+ if (m == n)
+ return m;
+
+ // 0 == m < n
+ else if (0 == m)
+ return n * (n+1) / 2;
+
+ // 0 < m < n
+ else if (0 < m)
+ return sum_helper(0, n) - sum_helper(0, m-1);
+
+ // m < 0 <= n
+ else if (0 <= n)
+ return sum_helper(0, n) - sum_helper(0, -m);
+
+ // m < n < 0
+ else
+ return -sum_helper(-n, -m);
+ }
+
+ template <typename, typename T, T from, T to>
+ static constexpr auto apply(range<T, from, to> const&) {
+ return integral_c<T, from == to ? 0 : sum_helper(from, to-1)>;
+ }
+ };
+
+ template <>
+ struct product_impl<range_tag> {
+ // Returns the product of `[m, n)`, where `m <= n` always hold.
+ template <typename I>
+ static constexpr I product_helper(I m, I n) {
+ if (m <= 0 && 0 < n)
+ return 0;
+ else {
+ I p = 1;
+ for (; m != n; ++m)
+ p *= m;
+ return p;
+ }
+ }
+
+ template <typename, typename T, T from, T to>
+ static constexpr auto apply(range<T, from, to> const&)
+ { return integral_c<T, product_helper(from, to)>; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Searchable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct find_impl<range_tag> {
+ template <typename T, T from, typename N>
+ static constexpr auto find_helper(hana::true_) {
+ constexpr T n = N::value;
+ return hana::just(hana::integral_c<T, n>);
+ }
+
+ template <typename T, T from, typename N>
+ static constexpr auto find_helper(hana::false_)
+ { return hana::nothing; }
+
+ template <typename T, T from, T to, typename N>
+ static constexpr auto apply(range<T, from, to> const&, N const&) {
+ constexpr auto n = N::value;
+ return find_helper<T, from, N>(hana::bool_c<(n >= from && n < to)>);
+ }
+ };
+
+ template <>
+ struct contains_impl<range_tag> {
+ template <typename T, T from, T to, typename N>
+ static constexpr auto apply(range<T, from, to> const&, N const&) {
+ constexpr auto n = N::value;
+ return bool_c<(n >= from && n < to)>;
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Iterable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct front_impl<range_tag> {
+ template <typename T, T from, T to>
+ static constexpr auto apply(range<T, from, to> const&)
+ { return integral_c<T, from>; }
+ };
+
+ template <>
+ struct is_empty_impl<range_tag> {
+ template <typename T, T from, T to>
+ static constexpr auto apply(range<T, from, to> const&)
+ { return bool_c<from == to>; }
+ };
+
+ template <>
+ struct at_impl<range_tag> {
+ template <typename T, T from, T to, typename N>
+ static constexpr auto apply(range<T, from, to> const&, N const&) {
+ constexpr auto n = N::value;
+ return integral_c<T, from + n>;
+ }
+ };
+
+ template <>
+ struct back_impl<range_tag> {
+ template <typename T, T from, T to>
+ static constexpr auto apply(range<T, from, to> const&)
+ { return integral_c<T, to - 1>; }
+ };
+
+ template <>
+ struct drop_front_impl<range_tag> {
+ template <typename T, T from, T to, typename N>
+ static constexpr auto apply(range<T, from, to> const&, N const&) {
+ constexpr auto n = N::value;
+ return range<T, (to < from + n ? to : from + n), to>{};
+ }
+ };
+
+ template <>
+ struct drop_front_exactly_impl<range_tag> {
+ template <typename T, T from, T to, typename N>
+ static constexpr auto apply(range<T, from, to> const&, N const&) {
+ constexpr auto n = N::value;
+ return range<T, from + n, to>{};
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_RANGE_HPP
diff --git a/boost/hana/remove.hpp b/boost/hana/remove.hpp
new file mode 100644
index 0000000000..8472eb3c48
--- /dev/null
+++ b/boost/hana/remove.hpp
@@ -0,0 +1,54 @@
+/*!
+@file
+Defines `boost::hana::remove`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_REMOVE_HPP
+#define BOOST_HANA_REMOVE_HPP
+
+#include <boost/hana/fwd/remove.hpp>
+
+#include <boost/hana/concept/monad_plus.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/filter.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/not.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Value>
+ constexpr auto remove_t::operator()(Xs&& xs, Value&& value) const {
+ using M = typename hana::tag_of<Xs>::type;
+ using Remove = BOOST_HANA_DISPATCH_IF(remove_impl<M>,
+ hana::MonadPlus<M>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::MonadPlus<M>::value,
+ "hana::remove(xs, value) requires 'xs' to be a MonadPlus");
+ #endif
+
+ return Remove::apply(static_cast<Xs&&>(xs),
+ static_cast<Value&&>(value));
+ }
+ //! @endcond
+
+ template <typename M, bool condition>
+ struct remove_impl<M, when<condition>> : default_ {
+ template <typename Xs, typename Value>
+ static constexpr auto apply(Xs&& xs, Value&& value) {
+ return hana::filter(static_cast<Xs&&>(xs),
+ hana::compose(hana::not_,
+ hana::equal.to(static_cast<Value&&>(value))));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_REMOVE_HPP
diff --git a/boost/hana/remove_at.hpp b/boost/hana/remove_at.hpp
new file mode 100644
index 0000000000..4ee061857d
--- /dev/null
+++ b/boost/hana/remove_at.hpp
@@ -0,0 +1,86 @@
+/*!
+@file
+Defines `boost::hana::remove_at` and `boost::hana::remove_at_c`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_REMOVE_AT_HPP
+#define BOOST_HANA_REMOVE_AT_HPP
+
+#include <boost/hana/fwd/remove_at.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/length.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename N>
+ constexpr auto remove_at_t::operator()(Xs&& xs, N const& n) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using RemoveAt = BOOST_HANA_DISPATCH_IF(remove_at_impl<S>,
+ hana::Sequence<S>::value &&
+ hana::IntegralConstant<N>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::remove_at(xs, n) requires 'xs' to be a Sequence");
+
+ static_assert(hana::IntegralConstant<N>::value,
+ "hana::remove_at(xs, n) requires 'n' to be an IntegralConstant");
+ #endif
+
+ static_assert(N::value >= 0,
+ "hana::remove_at(xs, n) requires 'n' to be non-negative");
+
+ return RemoveAt::apply(static_cast<Xs&&>(xs), n);
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct remove_at_impl<S, when<condition>> : default_ {
+ template <typename Xs, std::size_t ...before, std::size_t ...after>
+ static constexpr auto
+ remove_at_helper(Xs&& xs, std::index_sequence<before...>,
+ std::index_sequence<after...>)
+ {
+ return hana::make<S>(
+ hana::at_c<before>(static_cast<Xs&&>(xs))...,
+ hana::at_c<after + sizeof...(before) + 1>(static_cast<Xs&&>(xs))...
+ );
+ }
+
+ template <typename Xs, typename N>
+ static constexpr auto apply(Xs&& xs, N const&) {
+ constexpr std::size_t n = N::value;
+ constexpr std::size_t len = decltype(hana::length(xs))::value;
+ static_assert(n < len,
+ "hana::remove_at(xs, n) requires 'n' to be in the bounds of the sequence");
+ return remove_at_helper(static_cast<Xs&&>(xs),
+ std::make_index_sequence<n>{},
+ std::make_index_sequence<len - n - 1>{});
+ }
+ };
+
+ template <std::size_t n>
+ struct remove_at_c_t {
+ template <typename Xs>
+ constexpr decltype(auto) operator()(Xs&& xs) const
+ { return hana::remove_at(static_cast<Xs&&>(xs), hana::size_c<n>); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_REMOVE_AT_HPP
diff --git a/boost/hana/remove_if.hpp b/boost/hana/remove_if.hpp
new file mode 100644
index 0000000000..fb85c3d424
--- /dev/null
+++ b/boost/hana/remove_if.hpp
@@ -0,0 +1,52 @@
+/*!
+@file
+Defines `boost::hana::remove_if`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_REMOVE_IF_HPP
+#define BOOST_HANA_REMOVE_IF_HPP
+
+#include <boost/hana/fwd/remove_if.hpp>
+
+#include <boost/hana/concept/monad_plus.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/filter.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/not.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Pred>
+ constexpr auto remove_if_t::operator()(Xs&& xs, Pred&& pred) const {
+ using M = typename hana::tag_of<Xs>::type;
+ using RemoveIf = BOOST_HANA_DISPATCH_IF(remove_if_impl<M>,
+ hana::MonadPlus<M>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::MonadPlus<M>::value,
+ "hana::remove_if(xs, predicate) requires 'xs' to be a MonadPlus");
+ #endif
+
+ return RemoveIf::apply(static_cast<Xs&&>(xs),
+ static_cast<Pred&&>(pred));
+ }
+ //! @endcond
+
+ template <typename M, bool condition>
+ struct remove_if_impl<M, when<condition>> : default_ {
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs&& xs, Pred&& pred) {
+ return hana::filter(static_cast<Xs&&>(xs),
+ hana::compose(hana::not_, static_cast<Pred&&>(pred)));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_REMOVE_IF_HPP
diff --git a/boost/hana/remove_range.hpp b/boost/hana/remove_range.hpp
new file mode 100644
index 0000000000..d9fd3c1476
--- /dev/null
+++ b/boost/hana/remove_range.hpp
@@ -0,0 +1,100 @@
+/*!
+@file
+Defines `boost::hana::remove_range` and `boost::hana::remove_range_c`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_REMOVE_RANGE_HPP
+#define BOOST_HANA_REMOVE_RANGE_HPP
+
+#include <boost/hana/fwd/remove_range.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/length.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename From, typename To>
+ constexpr auto remove_range_t::operator()(Xs&& xs, From const& from, To const& to) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using RemoveRange = BOOST_HANA_DISPATCH_IF(remove_range_impl<S>,
+ hana::Sequence<S>::value &&
+ hana::IntegralConstant<From>::value &&
+ hana::IntegralConstant<To>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::remove_range(xs, from, to) requires 'xs' to be a Sequence");
+
+ static_assert(hana::IntegralConstant<From>::value,
+ "hana::remove_range(xs, from, to) requires 'from' to be an IntegralConstant");
+
+ static_assert(hana::IntegralConstant<To>::value,
+ "hana::remove_range(xs, from, to) requires 'to' to be an IntegralConstant");
+ #endif
+
+ return RemoveRange::apply(static_cast<Xs&&>(xs), from, to);
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct remove_range_impl<S, when<condition>> : default_ {
+ template <std::size_t offset, typename Xs, std::size_t ...before, std::size_t ...after>
+ static constexpr auto
+ remove_range_helper(Xs&& xs, std::index_sequence<before...>,
+ std::index_sequence<after...>)
+ {
+ return hana::make<S>(
+ hana::at_c<before>(static_cast<Xs&&>(xs))...,
+ hana::at_c<offset + after>(static_cast<Xs&&>(xs))...
+ );
+ }
+
+ template <typename Xs, typename From, typename To>
+ static constexpr auto apply(Xs&& xs, From const&, To const&) {
+ constexpr std::size_t from = From::value;
+ constexpr std::size_t to = To::value;
+ constexpr std::size_t len = decltype(hana::length(xs))::value;
+ constexpr std::size_t before = from == to ? len : from;
+ constexpr std::size_t after = from == to ? 0 : len - to;
+
+ static_assert(from <= to,
+ "hana::remove_range(xs, from, to) requires '[from, to)' to be a "
+ "valid interval, meaning that 'from <= to'");
+ static_assert(from == to || from >= 0,
+ "hana::remove_range(xs, from, to) requires 'from' to be non-negative");
+ static_assert(from == to || to <= len,
+ "hana::remove_range(xs, from, to) requires 'to <= length(xs)'");
+
+ return remove_range_helper<to>(static_cast<Xs&&>(xs),
+ std::make_index_sequence<before>{},
+ std::make_index_sequence<after>{});
+ }
+ };
+
+ template <std::size_t from, std::size_t to>
+ struct remove_range_c_t {
+ template <typename Xs>
+ constexpr decltype(auto) operator()(Xs&& xs) const {
+ return hana::remove_range(static_cast<Xs&&>(xs),
+ hana::size_c<from>,
+ hana::size_c<to>);
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_REMOVE_RANGE_HPP
diff --git a/boost/hana/repeat.hpp b/boost/hana/repeat.hpp
new file mode 100644
index 0000000000..20184f89a1
--- /dev/null
+++ b/boost/hana/repeat.hpp
@@ -0,0 +1,58 @@
+/*!
+@file
+Defines `boost::hana::repeat`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_REPEAT_HPP
+#define BOOST_HANA_REPEAT_HPP
+
+#include <boost/hana/fwd/repeat.hpp>
+
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename I, bool condition>
+ struct repeat_impl<I, when<condition>> : default_ {
+ template <typename F, std::size_t ...i>
+ static constexpr void repeat_helper(F&& f, std::index_sequence<i...>) {
+ using Swallow = std::size_t[];
+ (void)Swallow{0, ((void)f(), i)...};
+ }
+
+ template <typename N, typename F>
+ static constexpr auto apply(N const&, F&& f) {
+ static_assert(N::value >= 0, "hana::repeat(n, f) requires 'n' to be non-negative");
+ constexpr std::size_t n = N::value;
+ repeat_helper(static_cast<F&&>(f), std::make_index_sequence<n>{});
+ }
+ };
+
+ //! @cond
+ template <typename N, typename F>
+ constexpr void repeat_t::operator()(N const& n, F&& f) const {
+ using I = typename hana::tag_of<N>::type;
+ using Repeat = BOOST_HANA_DISPATCH_IF(repeat_impl<I>,
+ hana::IntegralConstant<I>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::IntegralConstant<I>::value,
+ "hana::repeat(n, f) requires 'n' to be an IntegralConstant");
+ #endif
+
+ return Repeat::apply(n, static_cast<F&&>(f));
+ }
+ //! @endcond
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_REPEAT_HPP
diff --git a/boost/hana/replace.hpp b/boost/hana/replace.hpp
new file mode 100644
index 0000000000..3ef6528116
--- /dev/null
+++ b/boost/hana/replace.hpp
@@ -0,0 +1,56 @@
+/*!
+@file
+Defines `boost::hana::replace`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_REPLACE_HPP
+#define BOOST_HANA_REPLACE_HPP
+
+#include <boost/hana/fwd/replace.hpp>
+
+#include <boost/hana/concept/functor.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/replace_if.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename OldVal, typename NewVal>
+ constexpr auto replace_t::operator()(Xs&& xs, OldVal&& oldval, NewVal&& newval) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Replace = BOOST_HANA_DISPATCH_IF(replace_impl<S>,
+ hana::Functor<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Functor<S>::value,
+ "hana::replace(xs, oldval, newval) requires 'xs' to be a Functor");
+ #endif
+
+ return Replace::apply(static_cast<Xs&&>(xs),
+ static_cast<OldVal&&>(oldval),
+ static_cast<NewVal&&>(newval));
+ }
+ //! @endcond
+
+ template <typename Fun, bool condition>
+ struct replace_impl<Fun, when<condition>> : default_ {
+ template <typename Xs, typename OldVal, typename NewVal>
+ static constexpr decltype(auto)
+ apply(Xs&& xs, OldVal&& oldval, NewVal&& newval) {
+ return hana::replace_if(
+ static_cast<Xs&&>(xs),
+ hana::equal.to(static_cast<OldVal&&>(oldval)),
+ static_cast<NewVal&&>(newval)
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_REPLACE_HPP
diff --git a/boost/hana/replace_if.hpp b/boost/hana/replace_if.hpp
new file mode 100644
index 0000000000..4d4490614d
--- /dev/null
+++ b/boost/hana/replace_if.hpp
@@ -0,0 +1,54 @@
+/*!
+@file
+Defines `boost::hana::replace_if`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_REPLACE_IF_HPP
+#define BOOST_HANA_REPLACE_IF_HPP
+
+#include <boost/hana/fwd/replace_if.hpp>
+
+#include <boost/hana/adjust_if.hpp>
+#include <boost/hana/concept/functor.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/functional/always.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Pred, typename Value>
+ constexpr auto replace_if_t::operator()(Xs&& xs, Pred&& pred, Value&& value) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using ReplaceIf = BOOST_HANA_DISPATCH_IF(replace_if_impl<S>,
+ hana::Functor<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Functor<S>::value,
+ "hana::replace_if(xs, pred, value) requires 'xs' to be a Functor");
+ #endif
+
+ return ReplaceIf::apply(static_cast<Xs&&>(xs),
+ static_cast<Pred&&>(pred),
+ static_cast<Value&&>(value));
+ }
+ //! @endcond
+
+ template <typename Fun, bool condition>
+ struct replace_if_impl<Fun, when<condition>> : default_ {
+ template <typename Xs, typename Pred, typename Value>
+ static constexpr auto apply(Xs&& xs, Pred&& pred, Value&& v) {
+ return hana::adjust_if(static_cast<Xs&&>(xs),
+ static_cast<Pred&&>(pred),
+ hana::always(static_cast<Value&&>(v))
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_REPLACE_IF_HPP
diff --git a/boost/hana/replicate.hpp b/boost/hana/replicate.hpp
new file mode 100644
index 0000000000..1f73abc280
--- /dev/null
+++ b/boost/hana/replicate.hpp
@@ -0,0 +1,74 @@
+/*!
+@file
+Defines `boost::hana::replicate`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_REPLICATE_HPP
+#define BOOST_HANA_REPLICATE_HPP
+
+#include <boost/hana/fwd/replicate.hpp>
+
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/concept/monad_plus.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/cycle.hpp>
+#include <boost/hana/lift.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename M>
+ struct replicate_t {
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::MonadPlus<M>::value,
+ "hana::replicate<M>(x, n) requires 'M' to be a MonadPlus");
+ #endif
+
+ template <typename X, typename N>
+ constexpr auto operator()(X&& x, N const& n) const {
+ using Replicate = BOOST_HANA_DISPATCH_IF(replicate_impl<M>,
+ hana::MonadPlus<M>::value &&
+ hana::IntegralConstant<N>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::IntegralConstant<N>::value,
+ "hana::replicate<M>(x, n) requires 'n' to be an IntegralConstant");
+ #endif
+
+ return Replicate::apply(static_cast<X&&>(x), n);
+ }
+ };
+
+ template <typename M, bool condition>
+ struct replicate_impl<M, when<condition>> : default_ {
+ template <typename X, typename N>
+ static constexpr auto apply(X&& x, N const& n) {
+ return hana::cycle(hana::lift<M>(static_cast<X&&>(x)), n);
+ }
+ };
+
+ template <typename S>
+ struct replicate_impl<S, when<Sequence<S>::value>> {
+ template <typename X, std::size_t ...i>
+ static constexpr auto replicate_helper(X&& x, std::index_sequence<i...>)
+ { return hana::make<S>(((void)i, x)...); }
+
+ template <typename X, typename N>
+ static constexpr auto apply(X&& x, N const&) {
+ constexpr std::size_t n = N::value;
+ return replicate_helper(static_cast<X&&>(x),
+ std::make_index_sequence<n>{});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_REPLICATE_HPP
diff --git a/boost/hana/reverse.hpp b/boost/hana/reverse.hpp
new file mode 100644
index 0000000000..d0156d076c
--- /dev/null
+++ b/boost/hana/reverse.hpp
@@ -0,0 +1,61 @@
+/*!
+@file
+Defines `boost::hana::reverse`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_REVERSE_HPP
+#define BOOST_HANA_REVERSE_HPP
+
+#include <boost/hana/fwd/reverse.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/length.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs>
+ constexpr auto reverse_t::operator()(Xs&& xs) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Reverse = BOOST_HANA_DISPATCH_IF(reverse_impl<S>,
+ hana::Sequence<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::reverse(xs) requires 'xs' to be a Sequence");
+ #endif
+
+ return Reverse::apply(static_cast<Xs&&>(xs));
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct reverse_impl<S, when<condition>> : default_ {
+ template <typename Xs, std::size_t ...i>
+ static constexpr auto reverse_helper(Xs&& xs, std::index_sequence<i...>) {
+ return hana::make<S>(
+ hana::at_c<sizeof...(i) - i - 1>(static_cast<Xs&&>(xs))...
+ );
+ }
+
+ template <typename Xs>
+ static constexpr auto apply(Xs&& xs) {
+ constexpr std::size_t N = decltype(hana::length(xs))::value;
+ return reverse_helper(static_cast<Xs&&>(xs), std::make_index_sequence<N>{});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_REVERSE_HPP
diff --git a/boost/hana/reverse_fold.hpp b/boost/hana/reverse_fold.hpp
new file mode 100644
index 0000000000..1cf07f931f
--- /dev/null
+++ b/boost/hana/reverse_fold.hpp
@@ -0,0 +1,37 @@
+/*!
+@file
+Defines `boost::hana::reverse_fold`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_REVERSE_FOLD_HPP
+#define BOOST_HANA_REVERSE_FOLD_HPP
+
+#include <boost/hana/fwd/reverse_fold.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/fold_right.hpp>
+#include <boost/hana/functional/flip.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename S, typename F>
+ constexpr decltype(auto) reverse_fold_t::operator()(Xs&& xs, S&& s, F&& f) const {
+ return hana::fold_right(static_cast<Xs&&>(xs),
+ static_cast<S&&>(s),
+ hana::flip(static_cast<F&&>(f)));
+ }
+
+ template <typename Xs, typename F>
+ constexpr decltype(auto) reverse_fold_t::operator()(Xs&& xs, F&& f) const {
+ return hana::fold_right(static_cast<Xs&&>(xs),
+ hana::flip(static_cast<F&&>(f)));
+ }
+ //! @endcond
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_REVERSE_FOLD_HPP
diff --git a/boost/hana/scan_left.hpp b/boost/hana/scan_left.hpp
new file mode 100644
index 0000000000..1660e086f1
--- /dev/null
+++ b/boost/hana/scan_left.hpp
@@ -0,0 +1,133 @@
+/*!
+@file
+Defines `boost::hana::scan_left`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_SCAN_LEFT_HPP
+#define BOOST_HANA_SCAN_LEFT_HPP
+
+#include <boost/hana/fwd/scan_left.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/empty.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/prepend.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename F>
+ constexpr auto scan_left_t::operator()(Xs&& xs, F const& f) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using ScanLeft = BOOST_HANA_DISPATCH_IF(scan_left_impl<S>,
+ hana::Sequence<S>::value
+ );
+
+#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::scan_left(xs, f) requires 'xs' to be a Sequence");
+#endif
+
+ return ScanLeft::apply(static_cast<Xs&&>(xs), f);
+ }
+
+ template <typename Xs, typename State, typename F>
+ constexpr auto scan_left_t::operator()(Xs&& xs, State&& state, F const& f) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using ScanLeft = BOOST_HANA_DISPATCH_IF(scan_left_impl<S>,
+ hana::Sequence<S>::value
+ );
+
+#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::scan_left(xs, state, f) requires 'xs' to be a Sequence");
+#endif
+
+ return ScanLeft::apply(static_cast<Xs&&>(xs),
+ static_cast<State&&>(state), f);
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct scan_left_impl<S, when<condition>> : default_ {
+ // Without initial state
+ template <typename Xs, typename F, std::size_t n1, std::size_t n2, std::size_t ...ns>
+ static constexpr auto
+ apply1_impl(Xs&& xs, F const& f, std::index_sequence<n1, n2, ns...>) {
+ static_assert(n1 == 0, "logic error in Boost.Hana: file a bug report");
+
+ // Use scan_left with the first element as an initial state.
+ return scan_left_impl::apply_impl(
+ static_cast<Xs&&>(xs),
+ hana::at_c<0>(static_cast<Xs&&>(xs)),
+ f, std::index_sequence<n2, ns...>{}
+ );
+ }
+
+ template <typename Xs, typename F, std::size_t n>
+ static constexpr auto apply1_impl(Xs&& xs, F const&, std::index_sequence<n>) {
+ return hana::make<S>(hana::at_c<n>(static_cast<Xs&&>(xs)));
+ }
+
+ template <typename Xs, typename F>
+ static constexpr auto apply1_impl(Xs&&, F const&, std::index_sequence<>) {
+ return hana::empty<S>();
+ }
+
+ template <typename Xs, typename F>
+ static constexpr auto apply(Xs&& xs, F const& f) {
+ constexpr std::size_t Len = decltype(hana::length(xs))::value;
+ return scan_left_impl::apply1_impl(static_cast<Xs&&>(xs),
+ f, std::make_index_sequence<Len>{});
+ }
+
+
+ // With initial state
+ template <typename Xs, typename State, typename F,
+ std::size_t n1, std::size_t n2, std::size_t ...ns>
+ static constexpr auto
+ apply_impl(Xs&& xs, State&& state, F const& f,
+ std::index_sequence<n1, n2, ns...>)
+ {
+ auto rest = scan_left_impl::apply_impl(
+ static_cast<Xs&&>(xs),
+ f(state, hana::at_c<n1>(static_cast<Xs&&>(xs))),
+ f, std::index_sequence<n2, ns...>{});
+ return hana::prepend(std::move(rest), static_cast<State&&>(state));
+ }
+
+ template <typename Xs, typename State, typename F, std::size_t n>
+ static constexpr auto
+ apply_impl(Xs&& xs, State&& state, F const& f, std::index_sequence<n>) {
+ auto new_state = f(state, hana::at_c<n>(static_cast<Xs&&>(xs)));
+ return hana::make<S>(static_cast<State&&>(state), std::move(new_state));
+ }
+
+ template <typename Xs, typename State, typename F>
+ static constexpr auto
+ apply_impl(Xs&&, State&& state, F const&, std::index_sequence<>) {
+ return hana::make<S>(static_cast<State&&>(state));
+ }
+
+ template <typename Xs, typename State, typename F>
+ static constexpr auto apply(Xs&& xs, State&& state, F const& f) {
+ constexpr std::size_t Len = decltype(hana::length(xs))::value;
+ return scan_left_impl::apply_impl(static_cast<Xs&&>(xs),
+ static_cast<State&&>(state),
+ f, std::make_index_sequence<Len>{});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_SCAN_LEFT_HPP
diff --git a/boost/hana/scan_right.hpp b/boost/hana/scan_right.hpp
new file mode 100644
index 0000000000..3a8a11d435
--- /dev/null
+++ b/boost/hana/scan_right.hpp
@@ -0,0 +1,130 @@
+/*!
+@file
+Defines `boost::hana::scan_right`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_SCAN_RIGHT_HPP
+#define BOOST_HANA_SCAN_RIGHT_HPP
+
+#include <boost/hana/fwd/scan_right.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/empty.hpp>
+#include <boost/hana/front.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/prepend.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename F>
+ constexpr auto scan_right_t::operator()(Xs&& xs, F const& f) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using ScanRight = BOOST_HANA_DISPATCH_IF(scan_right_impl<S>,
+ hana::Sequence<S>::value
+ );
+
+#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::scan_right(xs, f) requires 'xs' to be a Sequence");
+#endif
+
+ return ScanRight::apply(static_cast<Xs&&>(xs), f);
+ }
+
+ template <typename Xs, typename State, typename F>
+ constexpr auto scan_right_t::operator()(Xs&& xs, State&& state, F const& f) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using ScanRight = BOOST_HANA_DISPATCH_IF(scan_right_impl<S>,
+ hana::Sequence<S>::value
+ );
+
+#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::scan_right(xs, state, f) requires 'xs' to be a Sequence");
+#endif
+
+ return ScanRight::apply(static_cast<Xs&&>(xs),
+ static_cast<State&&>(state), f);
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct scan_right_impl<S, when<condition>> : default_ {
+ // Without initial state
+ template <typename Xs, typename F, std::size_t n1, std::size_t n2, std::size_t ...ns>
+ static constexpr auto
+ apply1_impl(Xs&& xs, F const& f, std::index_sequence<n1, n2, ns...>) {
+ auto rest = scan_right_impl::apply1_impl(static_cast<Xs&&>(xs),
+ f, std::index_sequence<n2, ns...>{});
+ auto element = f(hana::at_c<n1>(static_cast<Xs&&>(xs)), hana::front(rest));
+ return hana::prepend(std::move(rest), std::move(element));
+ }
+
+ template <typename Xs, typename F, std::size_t n>
+ static constexpr auto apply1_impl(Xs&& xs, F const&, std::index_sequence<n>) {
+ return hana::make<S>(hana::at_c<n>(static_cast<Xs&&>(xs)));
+ }
+
+ template <typename Xs, typename F>
+ static constexpr auto apply1_impl(Xs&&, F const&, std::index_sequence<>) {
+ return hana::empty<S>();
+ }
+
+ template <typename Xs, typename F>
+ static constexpr auto apply(Xs&& xs, F const& f) {
+ constexpr std::size_t Len = decltype(hana::length(xs))::value;
+ return scan_right_impl::apply1_impl(static_cast<Xs&&>(xs),
+ f, std::make_index_sequence<Len>{});
+ }
+
+
+ // With initial state
+ template <typename Xs, typename State, typename F,
+ std::size_t n1, std::size_t n2, std::size_t ...ns>
+ static constexpr auto
+ apply_impl(Xs&& xs, State&& state, F const& f,
+ std::index_sequence<n1, n2, ns...>)
+ {
+ auto rest = scan_right_impl::apply_impl(static_cast<Xs&&>(xs),
+ static_cast<State&&>(state),
+ f, std::index_sequence<n2, ns...>{});
+ auto element = f(hana::at_c<n1>(static_cast<Xs&&>(xs)), hana::front(rest));
+ return hana::prepend(std::move(rest), std::move(element));
+ }
+
+ template <typename Xs, typename State, typename F, std::size_t n>
+ static constexpr auto
+ apply_impl(Xs&& xs, State&& state, F const& f, std::index_sequence<n>) {
+ auto element = f(hana::at_c<n>(static_cast<Xs&&>(xs)), state);
+ return hana::make<S>(std::move(element), static_cast<State&&>(state));
+ }
+
+ template <typename Xs, typename State, typename F>
+ static constexpr auto
+ apply_impl(Xs&&, State&& state, F const&, std::index_sequence<>) {
+ return hana::make<S>(static_cast<State&&>(state));
+ }
+
+ template <typename Xs, typename State, typename F>
+ static constexpr auto apply(Xs&& xs, State&& state, F const& f) {
+ constexpr std::size_t Len = decltype(hana::length(xs))::value;
+ return scan_right_impl::apply_impl(static_cast<Xs&&>(xs),
+ static_cast<State&&>(state),
+ f, std::make_index_sequence<Len>{});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_SCAN_RIGHT_HPP
diff --git a/boost/hana/second.hpp b/boost/hana/second.hpp
new file mode 100644
index 0000000000..e5c28c9036
--- /dev/null
+++ b/boost/hana/second.hpp
@@ -0,0 +1,45 @@
+/*!
+@file
+Defines `boost::hana::second`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_SECOND_HPP
+#define BOOST_HANA_SECOND_HPP
+
+#include <boost/hana/fwd/second.hpp>
+
+#include <boost/hana/concept/product.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Pair>
+ constexpr decltype(auto) second_t::operator()(Pair&& pair) const {
+ using P = typename hana::tag_of<Pair>::type;
+ using Second = BOOST_HANA_DISPATCH_IF(second_impl<P>,
+ hana::Product<P>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Product<P>::value,
+ "hana::second(pair) requires 'pair' to be a Product");
+ #endif
+
+ return Second::apply(static_cast<Pair&&>(pair));
+ }
+ //! @endcond
+
+ template <typename P, bool condition>
+ struct second_impl<P, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_SECOND_HPP
diff --git a/boost/hana/set.hpp b/boost/hana/set.hpp
new file mode 100644
index 0000000000..c40547b77b
--- /dev/null
+++ b/boost/hana/set.hpp
@@ -0,0 +1,322 @@
+/*!
+@file
+Defines `boost::hana::set`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_SET_HPP
+#define BOOST_HANA_SET_HPP
+
+#include <boost/hana/fwd/set.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/hashable.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/contains.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/detail/decay.hpp>
+#include <boost/hana/detail/fast_and.hpp>
+#include <boost/hana/detail/has_duplicates.hpp>
+#include <boost/hana/detail/operators/adl.hpp>
+#include <boost/hana/detail/operators/comparable.hpp>
+#include <boost/hana/detail/operators/searchable.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/erase_key.hpp>
+#include <boost/hana/find_if.hpp>
+#include <boost/hana/fold_left.hpp>
+#include <boost/hana/fwd/any_of.hpp>
+#include <boost/hana/fwd/core/to.hpp>
+#include <boost/hana/fwd/difference.hpp>
+#include <boost/hana/fwd/intersection.hpp>
+#include <boost/hana/fwd/union.hpp>
+#include <boost/hana/insert.hpp>
+#include <boost/hana/is_subset.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/or.hpp>
+#include <boost/hana/remove.hpp>
+#include <boost/hana/tuple.hpp>
+#include <boost/hana/unpack.hpp>
+#include <boost/hana/value.hpp>
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //////////////////////////////////////////////////////////////////////////
+ // set
+ //////////////////////////////////////////////////////////////////////////
+ //! @cond
+ template <typename ...Xs>
+ struct set
+ : detail::operators::adl<set<Xs...>>
+ , detail::searchable_operators<set<Xs...>>
+ {
+ tuple<Xs...> storage;
+ using hana_tag = set_tag;
+ static constexpr std::size_t size = sizeof...(Xs);
+
+ explicit constexpr set(tuple<Xs...> const& xs)
+ : storage(xs)
+ { }
+
+ explicit constexpr set(tuple<Xs...>&& xs)
+ : storage(static_cast<tuple<Xs...>&&>(xs))
+ { }
+
+ constexpr set(set const& other) = default;
+ constexpr set(set&& other) = default;
+ };
+ //! @endcond
+
+ //////////////////////////////////////////////////////////////////////////
+ // Operators
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <>
+ struct comparable_operators<set_tag> {
+ static constexpr bool value = true;
+ };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // make<set_tag>
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct make_impl<set_tag> {
+ template <typename ...Xs>
+ static constexpr auto apply(Xs&& ...xs) {
+#if defined(BOOST_HANA_CONFIG_ENABLE_DEBUG_MODE)
+ static_assert(detail::fast_and<hana::Comparable<Xs>::value...>::value,
+ "hana::make_set(xs...) requires all the 'xs' to be Comparable");
+
+ static_assert(detail::fast_and<hana::Hashable<Xs>::value...>::value,
+ "hana::make_set(xs...) requires all the 'xs' to be Hashable");
+
+ static_assert(detail::fast_and<
+ Constant<decltype(hana::equal(xs, xs))>::value...
+ >::value,
+ "hana::make_set(xs...) requires all the 'xs' to be "
+ "Comparable at compile-time");
+
+ static_assert(!detail::has_duplicates<Xs&&...>::value,
+ "hana::make_set(xs...) requires all the 'xs' to be unique");
+#endif
+
+ return set<typename detail::decay<Xs>::type...>{
+ hana::make_tuple(static_cast<Xs&&>(xs)...)
+ };
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Comparable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct equal_impl<set_tag, set_tag> {
+ template <typename S1, typename S2>
+ static constexpr auto equal_helper(S1 const& s1, S2 const& s2, hana::true_)
+ { return hana::is_subset(s1, s2); }
+
+ template <typename S1, typename S2>
+ static constexpr auto equal_helper(S1 const&, S2 const&, hana::false_)
+ { return hana::false_c; }
+
+ template <typename S1, typename S2>
+ static constexpr decltype(auto) apply(S1&& s1, S2&& s2) {
+ return equal_impl::equal_helper(s1, s2, hana::bool_c<
+ decltype(hana::length(s1.storage))::value ==
+ decltype(hana::length(s2.storage))::value
+ >);
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Foldable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct unpack_impl<set_tag> {
+ template <typename Set, typename F>
+ static constexpr decltype(auto) apply(Set&& set, F&& f) {
+ return hana::unpack(static_cast<Set&&>(set).storage,
+ static_cast<F&&>(f));
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Searchable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct find_if_impl<set_tag> {
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs&& xs, Pred&& pred) {
+ return hana::find_if(static_cast<Xs&&>(xs).storage, static_cast<Pred&&>(pred));
+ }
+ };
+
+ template <>
+ struct any_of_impl<set_tag> {
+ template <typename Pred>
+ struct any_of_helper {
+ Pred const& pred;
+ template <typename ...X>
+ constexpr auto operator()(X const& ...x) const {
+ return hana::or_(pred(x)...);
+ }
+ constexpr auto operator()() const {
+ return hana::false_c;
+ }
+ };
+
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs const& xs, Pred const& pred) {
+ return hana::unpack(xs.storage, any_of_helper<Pred>{pred});
+ }
+ };
+
+ template <>
+ struct is_subset_impl<set_tag, set_tag> {
+ template <typename Ys>
+ struct all_contained {
+ Ys const& ys;
+ template <typename ...X>
+ constexpr auto operator()(X const& ...x) const {
+ return hana::bool_c<detail::fast_and<
+ hana::value<decltype(hana::contains(ys, x))>()...
+ >::value>;
+ }
+ };
+
+ template <typename Xs, typename Ys>
+ static constexpr auto apply(Xs const& xs, Ys const& ys) {
+ return hana::unpack(xs, all_contained<Ys>{ys});
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Conversions
+ //////////////////////////////////////////////////////////////////////////
+ template <typename F>
+ struct to_impl<set_tag, F, when<hana::Foldable<F>::value>> {
+ template <typename Xs>
+ static constexpr decltype(auto) apply(Xs&& xs) {
+ return hana::fold_left(static_cast<Xs&&>(xs),
+ hana::make_set(),
+ hana::insert);
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // insert
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct insert_impl<set_tag> {
+ template <typename Xs, typename X, typename Indices>
+ static constexpr auto
+ insert_helper(Xs&& xs, X&&, hana::true_, Indices) {
+ return static_cast<Xs&&>(xs);
+ }
+
+ template <typename Xs, typename X, std::size_t ...n>
+ static constexpr auto
+ insert_helper(Xs&& xs, X&& x, hana::false_, std::index_sequence<n...>) {
+ return hana::make_set(
+ hana::at_c<n>(static_cast<Xs&&>(xs).storage)..., static_cast<X&&>(x)
+ );
+ }
+
+ template <typename Xs, typename X>
+ static constexpr auto apply(Xs&& xs, X&& x) {
+ constexpr bool c = hana::value<decltype(hana::contains(xs, x))>();
+ constexpr std::size_t size = std::remove_reference<Xs>::type::size;
+ return insert_helper(static_cast<Xs&&>(xs), static_cast<X&&>(x),
+ hana::bool_c<c>, std::make_index_sequence<size>{});
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // erase_key
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct erase_key_impl<set_tag> {
+ template <typename Xs, typename X>
+ static constexpr decltype(auto) apply(Xs&& xs, X&& x) {
+ return hana::unpack(
+ hana::remove(static_cast<Xs&&>(xs).storage,
+ static_cast<X&&>(x)),
+ hana::make_set
+ );
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // intersection
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <typename Ys>
+ struct set_insert_if_contains {
+ Ys const& ys;
+
+ template <typename Result, typename Key>
+ static constexpr auto helper(Result&& result, Key&& key, hana::true_) {
+ return hana::insert(static_cast<Result&&>(result), static_cast<Key&&>(key));
+ }
+
+ template <typename Result, typename Key>
+ static constexpr auto helper(Result&& result, Key&&, hana::false_) {
+ return static_cast<Result&&>(result);
+ }
+
+ template <typename Result, typename Key>
+ constexpr auto operator()(Result&& result, Key&& key) const {
+ constexpr bool keep = hana::value<decltype(hana::contains(ys, key))>();
+ return set_insert_if_contains::helper(static_cast<Result&&>(result),
+ static_cast<Key&&>(key),
+ hana::bool_c<keep>);
+ }
+ };
+ }
+
+ template <>
+ struct intersection_impl<set_tag> {
+ template <typename Xs, typename Ys>
+ static constexpr auto apply(Xs&& xs, Ys const& ys) {
+ return hana::fold_left(static_cast<Xs&&>(xs), hana::make_set(),
+ detail::set_insert_if_contains<Ys>{ys});
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // union_
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct union_impl<set_tag> {
+ template <typename Xs, typename Ys>
+ static constexpr auto apply(Xs&& xs, Ys&& ys) {
+ return hana::fold_left(static_cast<Xs&&>(xs), static_cast<Ys&&>(ys),
+ hana::insert);
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // difference
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct difference_impl<set_tag> {
+ template <typename Xs, typename Ys>
+ static constexpr auto apply(Xs&& xs, Ys&& ys) {
+ return hana::fold_left(static_cast<Ys&&>(ys), static_cast<Xs&&>(xs),
+ hana::erase_key);
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_SET_HPP
diff --git a/boost/hana/size.hpp b/boost/hana/size.hpp
new file mode 100644
index 0000000000..8f3ba09961
--- /dev/null
+++ b/boost/hana/size.hpp
@@ -0,0 +1,17 @@
+/*!
+@file
+Defines `boost::hana::size`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_SIZE_HPP
+#define BOOST_HANA_SIZE_HPP
+
+#include <boost/hana/fwd/size.hpp>
+
+#include <boost/hana/length.hpp>
+
+#endif // !BOOST_HANA_SIZE_HPP
diff --git a/boost/hana/slice.hpp b/boost/hana/slice.hpp
new file mode 100644
index 0000000000..81eac951b1
--- /dev/null
+++ b/boost/hana/slice.hpp
@@ -0,0 +1,99 @@
+/*!
+@file
+Defines `boost::hana::slice` and `boost::hana::slice_c`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_SLICE_HPP
+#define BOOST_HANA_SLICE_HPP
+
+#include <boost/hana/fwd/slice.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/range.hpp>
+#include <boost/hana/unpack.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Indices>
+ constexpr auto slice_t::operator()(Xs&& xs, Indices&& indices) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Slice = BOOST_HANA_DISPATCH_IF(slice_impl<S>,
+ hana::Sequence<S>::value &&
+ hana::Foldable<Indices>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::slice(xs, indices) requires 'xs' to be a Sequence");
+
+ static_assert(hana::Foldable<Indices>::value,
+ "hana::slice(xs, indices) requires 'indices' to be Foldable");
+ #endif
+
+ return Slice::apply(static_cast<Xs&&>(xs), static_cast<Indices&&>(indices));
+ }
+ //! @endcond
+
+ namespace detail {
+ template <typename Xs>
+ struct take_arbitrary {
+ Xs& xs;
+ using S = typename hana::tag_of<Xs>::type;
+
+ template <typename ...N>
+ constexpr auto operator()(N const& ...) const {
+ return hana::make<S>(hana::at_c<N::value>(xs)...);
+ }
+ };
+ }
+
+ template <typename S, bool condition>
+ struct slice_impl<S, when<condition>> : default_ {
+ template <std::size_t from, typename Xs, std::size_t ...i>
+ static constexpr auto from_offset(Xs&& xs, std::index_sequence<i...>) {
+ return hana::make<S>(hana::at_c<from + i>(static_cast<Xs&&>(xs))...);
+ }
+
+ template <typename Xs, typename T, T from, T to>
+ static constexpr auto apply(Xs&& xs, hana::range<T, from, to> const&) {
+ return slice_impl::from_offset<from>(
+ static_cast<Xs&&>(xs), std::make_index_sequence<to - from>{}
+ );
+ }
+
+ //! @todo
+ //! Since we have the right to specify the same index more than once,
+ //! we can't move from the elements of the source sequence even if it
+ //! is a temporary object: we could end up double-moving. Perhaps it
+ //! would be possible to determine the indices from which we can move
+ //! without incurring a too large compile-time penalty?
+ template <typename Xs, typename Indices>
+ static constexpr auto apply(Xs const& xs, Indices const& indices) {
+ return hana::unpack(indices, detail::take_arbitrary<Xs const>{xs});
+ }
+ };
+
+ template <std::size_t from, std::size_t to>
+ struct slice_c_t {
+ template <typename Xs>
+ constexpr auto operator()(Xs&& xs) const {
+ return hana::slice(static_cast<Xs&&>(xs),
+ hana::range_c<std::size_t, from, to>);
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_SLICE_HPP
diff --git a/boost/hana/sort.hpp b/boost/hana/sort.hpp
new file mode 100644
index 0000000000..3e6edb2cbd
--- /dev/null
+++ b/boost/hana/sort.hpp
@@ -0,0 +1,173 @@
+/*!
+@file
+Defines `boost::hana::sort`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_SORT_HPP
+#define BOOST_HANA_SORT_HPP
+
+#include <boost/hana/fwd/sort.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/detail/nested_by.hpp> // required by fwd decl
+#include <boost/hana/length.hpp>
+#include <boost/hana/less.hpp>
+
+#include <utility> // std::declval, std::index_sequence
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Predicate>
+ constexpr auto sort_t::operator()(Xs&& xs, Predicate&& pred) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Sort = BOOST_HANA_DISPATCH_IF(sort_impl<S>,
+ hana::Sequence<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::sort(xs, predicate) requires 'xs' to be a Sequence");
+ #endif
+
+ return Sort::apply(static_cast<Xs&&>(xs),
+ static_cast<Predicate&&>(pred));
+ }
+
+ template <typename Xs>
+ constexpr auto sort_t::operator()(Xs&& xs) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Sort = BOOST_HANA_DISPATCH_IF(sort_impl<S>,
+ hana::Sequence<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::sort(xs) requires 'xs' to be a Sequence");
+ #endif
+
+ return Sort::apply(static_cast<Xs&&>(xs));
+ }
+ //! @endcond
+
+ namespace detail {
+ template <typename Xs, typename Pred>
+ struct sort_predicate {
+ template <std::size_t I, std::size_t J>
+ using apply = decltype(std::declval<Pred>()(
+ hana::at_c<I>(std::declval<Xs>()),
+ hana::at_c<J>(std::declval<Xs>())
+ ));
+ };
+
+ template <typename Pred, std::size_t Insert, bool IsInsertionPoint,
+ typename Left,
+ std::size_t ...Right>
+ struct insert;
+
+ // We did not find the insertion point; continue processing elements
+ // recursively.
+ template <
+ typename Pred, std::size_t Insert,
+ std::size_t ...Left,
+ std::size_t Right1, std::size_t Right2, std::size_t ...Right
+ >
+ struct insert<Pred, Insert, false,
+ std::index_sequence<Left...>,
+ Right1, Right2, Right...
+ > {
+ using type = typename insert<
+ Pred, Insert, (bool)Pred::template apply<Insert, Right2>::value,
+ std::index_sequence<Left..., Right1>,
+ Right2, Right...
+ >::type;
+ };
+
+ // We did not find the insertion point, but there is only one element
+ // left. We insert at the end of the list, and we're done.
+ template <typename Pred, std::size_t Insert, std::size_t ...Left, std::size_t Last>
+ struct insert<Pred, Insert, false, std::index_sequence<Left...>, Last> {
+ using type = std::index_sequence<Left..., Last, Insert>;
+ };
+
+ // We found the insertion point, we're done.
+ template <typename Pred, std::size_t Insert, std::size_t ...Left, std::size_t ...Right>
+ struct insert<Pred, Insert, true, std::index_sequence<Left...>, Right...> {
+ using type = std::index_sequence<Left..., Insert, Right...>;
+ };
+
+
+ template <typename Pred, typename Result, std::size_t ...T>
+ struct insertion_sort_impl;
+
+ template <typename Pred,
+ std::size_t Result1, std::size_t ...Result,
+ std::size_t T, std::size_t ...Ts>
+ struct insertion_sort_impl<Pred, std::index_sequence<Result1, Result...>, T, Ts...> {
+ using type = typename insertion_sort_impl<
+ Pred,
+ typename insert<
+ Pred, T, (bool)Pred::template apply<T, Result1>::value,
+ std::index_sequence<>,
+ Result1, Result...
+ >::type,
+ Ts...
+ >::type;
+ };
+
+ template <typename Pred, std::size_t T, std::size_t ...Ts>
+ struct insertion_sort_impl<Pred, std::index_sequence<>, T, Ts...> {
+ using type = typename insertion_sort_impl<
+ Pred, std::index_sequence<T>, Ts...
+ >::type;
+ };
+
+ template <typename Pred, typename Result>
+ struct insertion_sort_impl<Pred, Result> {
+ using type = Result;
+ };
+
+ template <typename Pred, typename Indices>
+ struct sort_helper;
+
+ template <typename Pred, std::size_t ...i>
+ struct sort_helper<Pred, std::index_sequence<i...>> {
+ using type = typename insertion_sort_impl<
+ Pred, std::index_sequence<>, i...
+ >::type;
+ };
+ } // end namespace detail
+
+ template <typename S, bool condition>
+ struct sort_impl<S, when<condition>> : default_ {
+ template <typename Xs, std::size_t ...i>
+ static constexpr auto apply_impl(Xs&& xs, std::index_sequence<i...>) {
+ return hana::make<S>(hana::at_c<i>(static_cast<Xs&&>(xs))...);
+ }
+
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs&& xs, Pred const&) {
+ constexpr std::size_t Len = decltype(hana::length(xs))::value;
+ using Indices = typename detail::sort_helper<
+ detail::sort_predicate<Xs&&, Pred>,
+ std::make_index_sequence<Len>
+ >::type;
+
+ return apply_impl(static_cast<Xs&&>(xs), Indices{});
+ }
+
+ template <typename Xs>
+ static constexpr auto apply(Xs&& xs)
+ { return sort_impl::apply(static_cast<Xs&&>(xs), hana::less); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_SORT_HPP
diff --git a/boost/hana/span.hpp b/boost/hana/span.hpp
new file mode 100644
index 0000000000..8a5f02ef36
--- /dev/null
+++ b/boost/hana/span.hpp
@@ -0,0 +1,75 @@
+/*!
+@file
+Defines `boost::hana::span`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_SPAN_HPP
+#define BOOST_HANA_SPAN_HPP
+
+#include <boost/hana/fwd/span.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/detail/nested_by.hpp> // required by fwd decl
+#include <boost/hana/detail/first_unsatisfied_index.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/pair.hpp>
+#include <boost/hana/unpack.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Pred>
+ constexpr auto span_t::operator()(Xs&& xs, Pred&& pred) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Span = BOOST_HANA_DISPATCH_IF(span_impl<S>,
+ hana::Sequence<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::span(xs, pred) requires 'xs' to be a Sequence");
+ #endif
+
+ return Span::apply(static_cast<Xs&&>(xs), static_cast<Pred&&>(pred));
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct span_impl<S, when<condition>> : default_ {
+ template <typename Xs, std::size_t ...before, std::size_t ...after>
+ static constexpr auto span_helper(Xs&& xs, std::index_sequence<before...>,
+ std::index_sequence<after...>)
+ {
+ return hana::make_pair(
+ hana::make<S>(hana::at_c<before>(static_cast<Xs&&>(xs))...),
+ hana::make<S>(hana::at_c<sizeof...(before) + after>(static_cast<Xs&&>(xs))...)
+ );
+ }
+
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs&& xs, Pred&&) {
+ using FirstUnsatisfied = decltype(
+ hana::unpack(static_cast<Xs&&>(xs),
+ detail::first_unsatisfied_index<Pred&&>{})
+ );
+ constexpr std::size_t breakpoint = FirstUnsatisfied::value;
+ constexpr std::size_t N = decltype(hana::length(xs))::value;
+ return span_helper(static_cast<Xs&&>(xs),
+ std::make_index_sequence<breakpoint>{},
+ std::make_index_sequence<N - breakpoint>{});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_SPAN_HPP
diff --git a/boost/hana/string.hpp b/boost/hana/string.hpp
new file mode 100644
index 0000000000..836a92be6a
--- /dev/null
+++ b/boost/hana/string.hpp
@@ -0,0 +1,290 @@
+/*!
+@file
+Defines `boost::hana::string`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_STRING_HPP
+#define BOOST_HANA_STRING_HPP
+
+#include <boost/hana/fwd/string.hpp>
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/detail/algorithm.hpp>
+#include <boost/hana/detail/operators/adl.hpp>
+#include <boost/hana/detail/operators/comparable.hpp>
+#include <boost/hana/detail/operators/iterable.hpp>
+#include <boost/hana/detail/operators/orderable.hpp>
+#include <boost/hana/fwd/at.hpp>
+#include <boost/hana/fwd/contains.hpp>
+#include <boost/hana/fwd/core/tag_of.hpp>
+#include <boost/hana/fwd/core/to.hpp>
+#include <boost/hana/fwd/drop_front.hpp>
+#include <boost/hana/fwd/equal.hpp>
+#include <boost/hana/fwd/find.hpp>
+#include <boost/hana/fwd/front.hpp>
+#include <boost/hana/fwd/hash.hpp>
+#include <boost/hana/fwd/is_empty.hpp>
+#include <boost/hana/fwd/length.hpp>
+#include <boost/hana/fwd/less.hpp>
+#include <boost/hana/fwd/unpack.hpp>
+#include <boost/hana/if.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/optional.hpp>
+#include <boost/hana/type.hpp>
+
+#include <utility>
+#include <cstddef>
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //////////////////////////////////////////////////////////////////////////
+ // string<>
+ //////////////////////////////////////////////////////////////////////////
+ //! @cond
+ template <char ...s>
+ struct string
+ : detail::operators::adl<string<s...>>
+ , detail::iterable_operators<string<s...>>
+ { };
+ //! @endcond
+
+ template <char ...s>
+ struct tag_of<string<s...>> {
+ using type = string_tag;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // make<string_tag>
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct make_impl<string_tag> {
+ template <typename ...Chars>
+ static constexpr auto apply(Chars const& ...) {
+ return hana::string<hana::value<Chars>()...>{};
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // BOOST_HANA_STRING
+ //////////////////////////////////////////////////////////////////////////
+ namespace string_detail {
+ template <typename S, std::size_t ...N>
+ constexpr string<S::get()[N]...>
+ prepare_impl(S, std::index_sequence<N...>)
+ { return {}; }
+
+ template <typename S>
+ constexpr decltype(auto) prepare(S s) {
+ return prepare_impl(s,
+ std::make_index_sequence<sizeof(S::get()) - 1>{});
+ }
+ }
+
+#define BOOST_HANA_STRING(s) \
+ (::boost::hana::string_detail::prepare([]{ \
+ struct tmp { \
+ static constexpr decltype(auto) get() { return s; } \
+ }; \
+ return tmp{}; \
+ }())) \
+/**/
+
+#ifdef BOOST_HANA_CONFIG_ENABLE_STRING_UDL
+ //////////////////////////////////////////////////////////////////////////
+ // _s user-defined literal
+ //////////////////////////////////////////////////////////////////////////
+ namespace literals {
+ template <typename CharT, CharT ...s>
+ constexpr auto operator"" _s() {
+ static_assert(std::is_same<CharT, char>::value,
+ "hana::string: Only narrow string literals are supported with "
+ "the _s string literal right now. See https://goo.gl/fBbKD7 "
+ "if you need support for fancier types of compile-time strings.");
+ return hana::string_c<s...>;
+ }
+ }
+#endif
+
+ //////////////////////////////////////////////////////////////////////////
+ // Operators
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <>
+ struct comparable_operators<string_tag> {
+ static constexpr bool value = true;
+ };
+ template <>
+ struct orderable_operators<string_tag> {
+ static constexpr bool value = true;
+ };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // to<char const*>
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct to_impl<char const*, string_tag> {
+ template <char ...c>
+ static constexpr char const c_string[sizeof...(c) + 1] = {c..., '\0'};
+
+ template <char ...c>
+ static constexpr char const* apply(string<c...> const&)
+ { return c_string<c...>; }
+ };
+
+ template <char ...c>
+ constexpr char const to_impl<char const*, string_tag>::c_string[sizeof...(c) + 1];
+
+ //////////////////////////////////////////////////////////////////////////
+ // Comparable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct equal_impl<string_tag, string_tag> {
+ template <typename S>
+ static constexpr auto apply(S const&, S const&)
+ { return hana::true_c; }
+
+ template <typename S1, typename S2>
+ static constexpr auto apply(S1 const&, S2 const&)
+ { return hana::false_c; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Orderable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct less_impl<string_tag, string_tag> {
+ template <char ...s1, char ...s2>
+ static constexpr auto
+ apply(string<s1...> const&, string<s2...> const&) {
+ // We put a '\0' at the end only to avoid empty arrays.
+ constexpr char const c_str1[] = {s1..., '\0'};
+ constexpr char const c_str2[] = {s2..., '\0'};
+ return hana::bool_c<detail::lexicographical_compare(
+ c_str1, c_str1 + sizeof...(s1),
+ c_str2, c_str2 + sizeof...(s2)
+ )>;
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Foldable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct unpack_impl<string_tag> {
+ template <char ...s, typename F>
+ static constexpr decltype(auto) apply(string<s...> const&, F&& f)
+ { return static_cast<F&&>(f)(char_<s>{}...); }
+ };
+
+ template <>
+ struct length_impl<string_tag> {
+ template <char ...s>
+ static constexpr auto apply(string<s...> const&)
+ { return hana::size_c<sizeof...(s)>; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Iterable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct front_impl<string_tag> {
+ template <char x, char ...xs>
+ static constexpr auto apply(string<x, xs...> const&)
+ { return hana::char_c<x>; }
+ };
+
+ template <>
+ struct drop_front_impl<string_tag> {
+ template <std::size_t N, char ...xs, std::size_t ...i>
+ static constexpr auto helper(string<xs...> const&, std::index_sequence<i...>) {
+ constexpr char s[] = {xs...};
+ return hana::string_c<s[i + N]...>;
+ }
+
+ 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
+ >{});
+ }
+
+ template <typename N>
+ static constexpr auto apply(string<> const& s, N const&)
+ { return s; }
+ };
+
+ template <>
+ struct is_empty_impl<string_tag> {
+ template <char ...s>
+ static constexpr auto apply(string<s...> const&)
+ { return hana::bool_c<sizeof...(s) == 0>; }
+ };
+
+ template <>
+ struct at_impl<string_tag> {
+ template <char ...s, typename N>
+ static constexpr auto apply(string<s...> const&, N const&) {
+ // We put a '\0' at the end to avoid an empty array.
+ constexpr char characters[] = {s..., '\0'};
+ constexpr auto n = N::value;
+ return hana::char_c<characters[n]>;
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Searchable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct contains_impl<string_tag> {
+ template <char ...s, typename C>
+ static constexpr auto
+ helper(string<s...> const&, C const&, hana::true_) {
+ constexpr char const characters[] = {s..., '\0'};
+ constexpr char c = hana::value<C>();
+ return hana::bool_c<
+ detail::find(characters, characters + sizeof...(s), c)
+ != characters + sizeof...(s)
+ >;
+ }
+
+ template <typename S, typename C>
+ static constexpr auto helper(S const&, C const&, hana::false_)
+ { return hana::false_c; }
+
+ template <typename S, typename C>
+ static constexpr auto apply(S const& s, C const& c)
+ { return helper(s, c, hana::bool_c<hana::Constant<C>::value>); }
+ };
+
+ template <>
+ struct find_impl<string_tag> {
+ template <char ...s, typename Char>
+ static constexpr auto apply(string<s...> const& str, Char const& c) {
+ return hana::if_(contains_impl<string_tag>::apply(str, c),
+ hana::just(c),
+ hana::nothing
+ );
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Hashable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct hash_impl<string_tag> {
+ template <typename String>
+ static constexpr auto apply(String const&) {
+ return hana::type_c<String>;
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_STRING_HPP
diff --git a/boost/hana/suffix.hpp b/boost/hana/suffix.hpp
new file mode 100644
index 0000000000..aca7064016
--- /dev/null
+++ b/boost/hana/suffix.hpp
@@ -0,0 +1,52 @@
+/*!
+@file
+Defines `boost::hana::suffix`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_SUFFIX_HPP
+#define BOOST_HANA_SUFFIX_HPP
+
+#include <boost/hana/fwd/suffix.hpp>
+
+#include <boost/hana/chain.hpp>
+#include <boost/hana/concept/monad_plus.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/lift.hpp>
+#include <boost/hana/prepend.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Sfx>
+ constexpr auto suffix_t::operator()(Xs&& xs, Sfx&& sfx) const {
+ using M = typename hana::tag_of<Xs>::type;
+ using Suffix = BOOST_HANA_DISPATCH_IF(suffix_impl<M>,
+ hana::MonadPlus<M>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::MonadPlus<M>::value,
+ "hana::suffix(xs, sfx) requires 'xs' to be a MonadPlus");
+ #endif
+
+ return Suffix::apply(static_cast<Xs&&>(xs), static_cast<Sfx&&>(sfx));
+ }
+ //! @endcond
+
+ template <typename M, bool condition>
+ struct suffix_impl<M, when<condition>> : default_ {
+ template <typename Xs, typename Z>
+ static constexpr auto apply(Xs&& xs, Z&& z) {
+ return hana::chain(static_cast<Xs&&>(xs),
+ hana::partial(hana::prepend, hana::lift<M>(static_cast<Z&&>(z))));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_SUFFIX_HPP
diff --git a/boost/hana/sum.hpp b/boost/hana/sum.hpp
new file mode 100644
index 0000000000..58713290b6
--- /dev/null
+++ b/boost/hana/sum.hpp
@@ -0,0 +1,58 @@
+/*!
+@file
+Defines `boost::hana::sum`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_SUM_HPP
+#define BOOST_HANA_SUM_HPP
+
+#include <boost/hana/fwd/sum.hpp>
+
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/concept/monoid.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/fold_left.hpp>
+#include <boost/hana/integral_constant.hpp> // required by fwd decl
+#include <boost/hana/plus.hpp>
+#include <boost/hana/zero.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename M>
+ struct sum_t {
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Monoid<M>::value,
+ "hana::sum<M> requires 'M' to be a Monoid");
+ #endif
+
+ template <typename Xs>
+ constexpr decltype(auto) operator()(Xs&& xs) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Sum = BOOST_HANA_DISPATCH_IF(sum_impl<S>,
+ hana::Foldable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Foldable<S>::value,
+ "hana::sum<M>(xs) requires 'xs' to be Foldable");
+ #endif
+
+ return Sum::template apply<M>(static_cast<Xs&&>(xs));
+ }
+ };
+
+ template <typename T, bool condition>
+ struct sum_impl<T, when<condition>> : default_ {
+ template <typename M, typename Xs>
+ static constexpr decltype(auto) apply(Xs&& xs) {
+ return hana::fold_left(static_cast<Xs&&>(xs), hana::zero<M>(), hana::plus);
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_SUM_HPP
diff --git a/boost/hana/symmetric_difference.hpp b/boost/hana/symmetric_difference.hpp
new file mode 100644
index 0000000000..f753c99561
--- /dev/null
+++ b/boost/hana/symmetric_difference.hpp
@@ -0,0 +1,46 @@
+/*!
+@file
+Defines `boost::hana::symmetric_difference`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_SYMMETRIC_DIFFERENCE_HPP
+#define BOOST_HANA_SYMMETRIC_DIFFERENCE_HPP
+
+#include <boost/hana/fwd/symmetric_difference.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/difference.hpp>
+#include <boost/hana/union.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Ys>
+ constexpr auto symmetric_difference_t::operator()(Xs&& xs, Ys&& ys) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using SymmetricDifference = BOOST_HANA_DISPATCH_IF(symmetric_difference_impl<S>,
+ true
+ );
+
+ return SymmetricDifference::apply(static_cast<Xs&&>(xs), static_cast<Ys&&>(ys));
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct symmetric_difference_impl<S, when<condition>> : default_ {
+ template <typename Xs, typename Ys>
+ static constexpr auto apply(Xs&& xs, Ys&& ys) {
+ return hana::union_(
+ hana::difference(xs, ys),
+ hana::difference(ys, xs)
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_SYMMETRIC_DIFFERENCE_HPP
diff --git a/boost/hana/take_back.hpp b/boost/hana/take_back.hpp
new file mode 100644
index 0000000000..9a12d93b23
--- /dev/null
+++ b/boost/hana/take_back.hpp
@@ -0,0 +1,68 @@
+/*!
+@file
+Defines `boost::hana::take_back`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_TAKE_BACK_HPP
+#define BOOST_HANA_TAKE_BACK_HPP
+
+#include <boost/hana/fwd/take_back.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/length.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename N>
+ constexpr auto take_back_t::operator()(Xs&& xs, N const& n) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using TakeBack = BOOST_HANA_DISPATCH_IF(take_back_impl<S>,
+ hana::Sequence<S>::value &&
+ hana::IntegralConstant<N>::value
+ );
+
+#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::take_back(xs, n) requires 'xs' to be a Sequence");
+
+ static_assert(hana::IntegralConstant<N>::value,
+ "hana::take_back(xs, n) requires 'n' to be an IntegralConstant");
+#endif
+
+ return TakeBack::apply(static_cast<Xs&&>(xs), n);
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct take_back_impl<S, when<condition>> : default_ {
+ template <std::size_t start, typename Xs, std::size_t ...n>
+ static constexpr auto take_back_helper(Xs&& xs, std::index_sequence<n...>) {
+ return hana::make<S>(hana::at_c<start + n>(static_cast<Xs&&>(xs))...);
+ }
+
+ template <typename Xs, typename N>
+ static constexpr auto apply(Xs&& xs, N const&) {
+ constexpr std::size_t n = N::value;
+ constexpr std::size_t size = decltype(hana::length(xs))::value;
+ constexpr std::size_t start = n < size ? size - n : 0;
+ return take_back_helper<start>(static_cast<Xs&&>(xs),
+ std::make_index_sequence<(n < size ? n : size)>{});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_TAKE_BACK_HPP
diff --git a/boost/hana/take_front.hpp b/boost/hana/take_front.hpp
new file mode 100644
index 0000000000..65c851aaf4
--- /dev/null
+++ b/boost/hana/take_front.hpp
@@ -0,0 +1,75 @@
+/*!
+@file
+Defines `boost::hana::take_front` and `boost::hana::take_front_c`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_TAKE_FRONT_HPP
+#define BOOST_HANA_TAKE_FRONT_HPP
+
+#include <boost/hana/fwd/take_front.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/length.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename N>
+ constexpr auto take_front_t::operator()(Xs&& xs, N const& n) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using TakeFront = BOOST_HANA_DISPATCH_IF(take_front_impl<S>,
+ hana::Sequence<S>::value &&
+ hana::IntegralConstant<N>::value
+ );
+
+#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::take_front(xs, n) requires 'xs' to be a Sequence");
+
+ static_assert(hana::IntegralConstant<N>::value,
+ "hana::take_front(xs, n) requires 'n' to be an IntegralConstant");
+#endif
+
+ return TakeFront::apply(static_cast<Xs&&>(xs), n);
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct take_front_impl<S, when<condition>> : default_ {
+ template <typename Xs, std::size_t ...n>
+ static constexpr auto take_front_helper(Xs&& xs, std::index_sequence<n...>) {
+ return hana::make<S>(hana::at_c<n>(static_cast<Xs&&>(xs))...);
+ }
+
+ template <typename Xs, typename N>
+ static constexpr auto apply(Xs&& xs, N const&) {
+ constexpr std::size_t n = N::value;
+ constexpr std::size_t size = decltype(hana::length(xs))::value;
+ return take_front_helper(static_cast<Xs&&>(xs),
+ std::make_index_sequence<(n < size ? n : size)>{});
+ }
+ };
+
+ template <std::size_t n>
+ struct take_front_c_t {
+ template <typename Xs>
+ constexpr auto operator()(Xs&& xs) const {
+ return hana::take_front(static_cast<Xs&&>(xs), hana::size_c<n>);
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_TAKE_FRONT_HPP
diff --git a/boost/hana/take_while.hpp b/boost/hana/take_while.hpp
new file mode 100644
index 0000000000..cda4816294
--- /dev/null
+++ b/boost/hana/take_while.hpp
@@ -0,0 +1,55 @@
+/*!
+@file
+Defines `boost::hana::take_while`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_TAKE_WHILE_HPP
+#define BOOST_HANA_TAKE_WHILE_HPP
+
+#include <boost/hana/fwd/take_while.hpp>
+
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/first_unsatisfied_index.hpp>
+#include <boost/hana/take_front.hpp>
+#include <boost/hana/unpack.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Pred>
+ constexpr auto take_while_t::operator()(Xs&& xs, Pred&& pred) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using TakeWhile = BOOST_HANA_DISPATCH_IF(take_while_impl<S>,
+ hana::Sequence<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::take_while(xs, pred) requires 'xs' to be a Sequence");
+ #endif
+
+ return TakeWhile::apply(static_cast<Xs&&>(xs),
+ static_cast<Pred&&>(pred));
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct take_while_impl<S, when<condition>> : default_ {
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs&& xs, Pred&&) {
+ using FirstUnsatisfied = decltype(
+ hana::unpack(static_cast<Xs&&>(xs),
+ detail::first_unsatisfied_index<Pred&&>{})
+ );
+ return hana::take_front(static_cast<Xs&&>(xs), FirstUnsatisfied{});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_TAKE_WHILE_HPP
diff --git a/boost/hana/tap.hpp b/boost/hana/tap.hpp
new file mode 100644
index 0000000000..37f757e7cc
--- /dev/null
+++ b/boost/hana/tap.hpp
@@ -0,0 +1,59 @@
+/*!
+@file
+Defines `boost::hana::tap`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_TAP_HPP
+#define BOOST_HANA_TAP_HPP
+
+#include <boost/hana/fwd/tap.hpp>
+
+#include <boost/hana/concept/monad.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/lift.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename M>
+ struct tap_t {
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Monad<M>::value,
+ "hana::tap<M> requires 'M' to be a Monad");
+ #endif
+
+ template <typename F>
+ constexpr auto operator()(F&& f) const {
+ using Tap = BOOST_HANA_DISPATCH_IF(tap_impl<M>,
+ hana::Monad<M>::value
+ );
+
+ return Tap::apply(static_cast<F&&>(f));
+ }
+ };
+
+ namespace detail {
+ template <typename M>
+ struct tap_helper {
+ template <typename F, typename X>
+ constexpr auto operator()(F&& f, X&& x) const {
+ (void)static_cast<F&&>(f)(x);
+ return hana::lift<M>(static_cast<X&&>(x));
+ }
+ };
+ }
+
+ template <typename M, bool condition>
+ struct tap_impl<M, when<condition>> : default_ {
+ template <typename F>
+ static constexpr auto apply(F&& f)
+ { return hana::partial(detail::tap_helper<M>{}, static_cast<F&&>(f)); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_TAP_HPP
diff --git a/boost/hana/then.hpp b/boost/hana/then.hpp
new file mode 100644
index 0000000000..9ee05ced0f
--- /dev/null
+++ b/boost/hana/then.hpp
@@ -0,0 +1,55 @@
+/*!
+@file
+Defines `boost::hana::then`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_THEN_HPP
+#define BOOST_HANA_THEN_HPP
+
+#include <boost/hana/fwd/then.hpp>
+
+#include <boost/hana/chain.hpp>
+#include <boost/hana/concept/monad.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/functional/always.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Before, typename Xs>
+ constexpr decltype(auto) then_t::operator()(Before&& before, Xs&& xs) const {
+ using M = typename hana::tag_of<Before>::type;
+ using Then = BOOST_HANA_DISPATCH_IF(then_impl<M>,
+ hana::Monad<M>::value &&
+ hana::Monad<Xs>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Monad<M>::value,
+ "hana::then(before, xs) requires 'before' to be a Monad");
+
+ static_assert(hana::Monad<Xs>::value,
+ "hana::then(before, xs) requires 'xs' to be a Monad");
+ #endif
+
+ return Then::apply(static_cast<Before&&>(before),
+ static_cast<Xs&&>(xs));
+ }
+ //! @endcond
+
+ template <typename M, bool condition>
+ struct then_impl<M, when<condition>> : default_ {
+ template <typename Xs, typename Ys>
+ static constexpr decltype(auto) apply(Xs&& xs, Ys&& ys) {
+ return hana::chain(static_cast<Xs&&>(xs),
+ hana::always(static_cast<Ys&&>(ys)));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_THEN_HPP
diff --git a/boost/hana/traits.hpp b/boost/hana/traits.hpp
new file mode 100644
index 0000000000..2f599d78ab
--- /dev/null
+++ b/boost/hana/traits.hpp
@@ -0,0 +1,213 @@
+/*!
+@file
+Defines function-like equivalents to the standard `<type_traits>`, and also
+to some utilities like `std::declval`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_TRAITS_HPP
+#define BOOST_HANA_TRAITS_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/type.hpp>
+
+#include <cstddef>
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace traits {
+ namespace detail {
+ // We use this instead of hana::integral because we want to return
+ // hana::integral_constants instead of std::integral_constants.
+ template <template <typename ...> class F>
+ struct hana_trait {
+ template <typename ...T>
+ constexpr auto operator()(T const& ...) const {
+ using Result = typename F<typename T::type...>::type;
+ return hana::integral_c<typename Result::value_type, Result::value>;
+ }
+ };
+ }
+
+ ///////////////////////
+ // Type properties
+ ///////////////////////
+ // Primary type categories
+ constexpr auto is_void = detail::hana_trait<std::is_void>{};
+ constexpr auto is_null_pointer = detail::hana_trait<std::is_null_pointer>{};
+ constexpr auto is_integral = detail::hana_trait<std::is_integral>{};
+ constexpr auto is_floating_point = detail::hana_trait<std::is_floating_point>{};
+ constexpr auto is_array = detail::hana_trait<std::is_array>{};
+ constexpr auto is_enum = detail::hana_trait<std::is_enum>{};
+ constexpr auto is_union = detail::hana_trait<std::is_union>{};
+ constexpr auto is_class = detail::hana_trait<std::is_class>{};
+ constexpr auto is_function = detail::hana_trait<std::is_function>{};
+ constexpr auto is_pointer = detail::hana_trait<std::is_pointer>{};
+ constexpr auto is_lvalue_reference = detail::hana_trait<std::is_lvalue_reference>{};
+ constexpr auto is_rvalue_reference = detail::hana_trait<std::is_rvalue_reference>{};
+ constexpr auto is_member_object_pointer = detail::hana_trait<std::is_member_object_pointer>{};
+ constexpr auto is_member_function_pointer = detail::hana_trait<std::is_member_function_pointer>{};
+
+ // Composite type categories
+ constexpr auto is_fundamental = detail::hana_trait<std::is_fundamental>{};
+ constexpr auto is_arithmetic = detail::hana_trait<std::is_arithmetic>{};
+ constexpr auto is_scalar = detail::hana_trait<std::is_scalar>{};
+ constexpr auto is_object = detail::hana_trait<std::is_object>{};
+ constexpr auto is_compound = detail::hana_trait<std::is_compound>{};
+ constexpr auto is_reference = detail::hana_trait<std::is_reference>{};
+ constexpr auto is_member_pointer = detail::hana_trait<std::is_member_pointer>{};
+
+ // Type properties
+ constexpr auto is_const = detail::hana_trait<std::is_const>{};
+ constexpr auto is_volatile = detail::hana_trait<std::is_volatile>{};
+ constexpr auto is_trivial = detail::hana_trait<std::is_trivial>{};
+ constexpr auto is_trivially_copyable = detail::hana_trait<std::is_trivially_copyable>{};
+ constexpr auto is_standard_layout = detail::hana_trait<std::is_standard_layout>{};
+ constexpr auto is_pod = detail::hana_trait<std::is_pod>{};
+ constexpr auto is_literal_type = detail::hana_trait<std::is_literal_type>{};
+ constexpr auto is_empty = detail::hana_trait<std::is_empty>{};
+ constexpr auto is_polymorphic = detail::hana_trait<std::is_polymorphic>{};
+ constexpr auto is_abstract = detail::hana_trait<std::is_abstract>{};
+ constexpr auto is_signed = detail::hana_trait<std::is_signed>{};
+ constexpr auto is_unsigned = detail::hana_trait<std::is_unsigned>{};
+
+ // Supported operations
+ constexpr auto is_constructible = detail::hana_trait<std::is_constructible>{};
+ constexpr auto is_trivially_constructible = detail::hana_trait<std::is_trivially_constructible>{};
+ constexpr auto is_nothrow_constructible = detail::hana_trait<std::is_nothrow_constructible>{};
+
+ constexpr auto is_default_constructible = detail::hana_trait<std::is_default_constructible>{};
+ constexpr auto is_trivially_default_constructible = detail::hana_trait<std::is_trivially_default_constructible>{};
+ constexpr auto is_nothrow_default_constructible = detail::hana_trait<std::is_nothrow_default_constructible>{};
+
+ constexpr auto is_copy_constructible = detail::hana_trait<std::is_copy_constructible>{};
+ constexpr auto is_trivially_copy_constructible = detail::hana_trait<std::is_trivially_copy_constructible>{};
+ constexpr auto is_nothrow_copy_constructible = detail::hana_trait<std::is_nothrow_copy_constructible>{};
+
+ constexpr auto is_move_constructible = detail::hana_trait<std::is_move_constructible>{};
+ constexpr auto is_trivially_move_constructible = detail::hana_trait<std::is_trivially_move_constructible>{};
+ constexpr auto is_nothrow_move_constructible = detail::hana_trait<std::is_nothrow_move_constructible>{};
+
+ constexpr auto is_assignable = detail::hana_trait<std::is_assignable>{};
+ constexpr auto is_trivially_assignable = detail::hana_trait<std::is_trivially_assignable>{};
+ constexpr auto is_nothrow_assignable = detail::hana_trait<std::is_nothrow_assignable>{};
+
+ constexpr auto is_copy_assignable = detail::hana_trait<std::is_copy_assignable>{};
+ constexpr auto is_trivially_copy_assignable = detail::hana_trait<std::is_trivially_copy_assignable>{};
+ constexpr auto is_nothrow_copy_assignable = detail::hana_trait<std::is_nothrow_copy_assignable>{};
+
+ constexpr auto is_move_assignable = detail::hana_trait<std::is_move_assignable>{};
+ constexpr auto is_trivially_move_assignable = detail::hana_trait<std::is_trivially_move_assignable>{};
+ constexpr auto is_nothrow_move_assignable = detail::hana_trait<std::is_nothrow_move_assignable>{};
+
+ constexpr auto is_destructible = detail::hana_trait<std::is_destructible>{};
+ constexpr auto is_trivially_destructible = detail::hana_trait<std::is_trivially_destructible>{};
+ constexpr auto is_nothrow_destructible = detail::hana_trait<std::is_nothrow_destructible>{};
+
+ constexpr auto has_virtual_destructor = detail::hana_trait<std::has_virtual_destructor>{};
+
+ // Property queries
+ constexpr auto alignment_of = detail::hana_trait<std::alignment_of>{};
+ constexpr auto rank = detail::hana_trait<std::rank>{};
+ constexpr struct extent_t {
+ template <typename T, typename N>
+ constexpr auto operator()(T const&, N const&) const {
+ constexpr unsigned n = N::value;
+ using Result = typename std::extent<typename T::type, n>::type;
+ return hana::integral_c<typename Result::value_type, Result::value>;
+ }
+
+ template <typename T>
+ constexpr auto operator()(T const& t) const
+ { return (*this)(t, hana::uint_c<0>); }
+ } extent{};
+
+ // Type relationships
+ constexpr auto is_same = detail::hana_trait<std::is_same>{};
+ constexpr auto is_base_of = detail::hana_trait<std::is_base_of>{};
+ constexpr auto is_convertible = detail::hana_trait<std::is_convertible>{};
+
+ ///////////////////////
+ // Type modifications
+ ///////////////////////
+ // Const-volatility specifiers
+ constexpr auto remove_cv = metafunction<std::remove_cv>;
+ constexpr auto remove_const = metafunction<std::remove_const>;
+ constexpr auto remove_volatile = metafunction<std::remove_volatile>;
+
+ constexpr auto add_cv = metafunction<std::add_cv>;
+ constexpr auto add_const = metafunction<std::add_const>;
+ constexpr auto add_volatile = metafunction<std::add_volatile>;
+
+ // References
+ constexpr auto remove_reference = metafunction<std::remove_reference>;
+ constexpr auto add_lvalue_reference = metafunction<std::add_lvalue_reference>;
+ constexpr auto add_rvalue_reference = metafunction<std::add_rvalue_reference>;
+
+ // Pointers
+ constexpr auto remove_pointer = metafunction<std::remove_pointer>;
+ constexpr auto add_pointer = metafunction<std::add_pointer>;
+
+ // Sign modifiers
+ constexpr auto make_signed = metafunction<std::make_signed>;
+ constexpr auto make_unsigned = metafunction<std::make_unsigned>;
+
+ // Arrays
+ constexpr auto remove_extent = metafunction<std::remove_extent>;
+ constexpr auto remove_all_extents = metafunction<std::remove_all_extents>;
+
+ // Miscellaneous transformations
+ constexpr struct aligned_storage_t {
+ template <typename Len, typename Align>
+ constexpr auto operator()(Len const&, Align const&) const {
+ constexpr std::size_t len = Len::value;
+ constexpr std::size_t align = Align::value;
+ using Result = typename std::aligned_storage<len, align>::type;
+ return hana::type_c<Result>;
+ }
+
+ template <typename Len>
+ constexpr auto operator()(Len const&) const {
+ constexpr std::size_t len = Len::value;
+ using Result = typename std::aligned_storage<len>::type;
+ return hana::type_c<Result>;
+ }
+ } aligned_storage{};
+
+ constexpr struct aligned_union_t {
+ template <typename Len, typename ...T>
+ constexpr auto operator()(Len const&, T const&...) const {
+ constexpr std::size_t len = Len::value;
+ using Result = typename std::aligned_union<len, typename T::type...>::type;
+ return hana::type_c<Result>;
+ }
+ } aligned_union{};
+
+ constexpr auto decay = metafunction<std::decay>;
+ // enable_if
+ // disable_if
+ // conditional
+
+ constexpr auto common_type = metafunction<std::common_type>;
+ constexpr auto underlying_type = metafunction<std::underlying_type>;
+ constexpr auto result_of = metafunction<std::result_of>;
+
+
+ ///////////////////////
+ // Utilities
+ ///////////////////////
+ struct declval_t {
+ template <typename T>
+ typename std::add_rvalue_reference<
+ typename T::type
+ >::type operator()(T const&) const;
+ };
+
+ constexpr declval_t declval{};
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_TRAITS_HPP
diff --git a/boost/hana/transform.hpp b/boost/hana/transform.hpp
new file mode 100644
index 0000000000..7ecba83602
--- /dev/null
+++ b/boost/hana/transform.hpp
@@ -0,0 +1,76 @@
+/*!
+@file
+Defines `boost::hana::transform`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_TRANSFORM_HPP
+#define BOOST_HANA_TRANSFORM_HPP
+
+#include <boost/hana/fwd/transform.hpp>
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/functor.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/functional/always.hpp>
+#include <boost/hana/fwd/adjust_if.hpp>
+#include <boost/hana/unpack.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename F>
+ constexpr auto transform_t::operator()(Xs&& xs, F&& f) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Transform = BOOST_HANA_DISPATCH_IF(transform_impl<S>,
+ hana::Functor<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Functor<S>::value,
+ "hana::transform(xs, f) requires 'xs' to be a Functor");
+ #endif
+
+ return Transform::apply(static_cast<Xs&&>(xs), static_cast<F&&>(f));
+ }
+ //! @endcond
+
+ template <typename Fun, bool condition>
+ struct transform_impl<Fun, when<condition>> : default_ {
+ template <typename Xs, typename F>
+ static constexpr auto apply(Xs&& xs, F&& f) {
+ return hana::adjust_if(static_cast<Xs&&>(xs),
+ hana::always(hana::true_c),
+ static_cast<F&&>(f));
+ }
+ };
+
+ template <typename S>
+ struct transform_impl<S, when<Sequence<S>::value>> {
+ //! @cond
+ template <typename F>
+ struct transformer {
+ F f;
+ template <typename ...Xs>
+ constexpr auto operator()(Xs&& ...xs) const {
+ return hana::make<S>((*f)(static_cast<Xs&&>(xs))...);
+ }
+ };
+ //! @endcond
+
+ template <typename Xs, typename F>
+ static constexpr auto apply(Xs&& xs, F&& f) {
+ // We use a pointer to workaround a Clang 3.5 ICE
+ return hana::unpack(static_cast<Xs&&>(xs),
+ transformer<decltype(&f)>{&f});
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_TRANSFORM_HPP
diff --git a/boost/hana/tuple.hpp b/boost/hana/tuple.hpp
new file mode 100644
index 0000000000..7273a6c2e0
--- /dev/null
+++ b/boost/hana/tuple.hpp
@@ -0,0 +1,305 @@
+/*!
+@file
+Defines `boost::hana::tuple`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_TUPLE_HPP
+#define BOOST_HANA_TUPLE_HPP
+
+#include <boost/hana/fwd/tuple.hpp>
+
+#include <boost/hana/basic_tuple.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/decay.hpp>
+#include <boost/hana/detail/fast_and.hpp>
+#include <boost/hana/detail/index_if.hpp>
+#include <boost/hana/detail/intrinsics.hpp>
+#include <boost/hana/detail/operators/adl.hpp>
+#include <boost/hana/detail/operators/comparable.hpp>
+#include <boost/hana/detail/operators/iterable.hpp>
+#include <boost/hana/detail/operators/monad.hpp>
+#include <boost/hana/detail/operators/orderable.hpp>
+#include <boost/hana/fwd/at.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+#include <boost/hana/fwd/drop_front.hpp>
+#include <boost/hana/fwd/find_if.hpp>
+#include <boost/hana/fwd/is_empty.hpp>
+#include <boost/hana/fwd/length.hpp>
+#include <boost/hana/fwd/optional.hpp>
+#include <boost/hana/fwd/unpack.hpp>
+#include <boost/hana/type.hpp> // required by fwd decl of tuple_t
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ namespace detail {
+ template <typename Xs, typename Ys, std::size_t ...n>
+ constexpr void assign(Xs& xs, Ys&& ys, std::index_sequence<n...>) {
+ int sequence[] = {int{}, ((void)(
+ hana::get_impl<n>(xs) = hana::get_impl<n>(static_cast<Ys&&>(ys))
+ ), int{})...};
+ (void)sequence;
+ }
+
+ struct from_index_sequence_t { };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // tuple
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct tuple<>
+ : detail::operators::adl<tuple<>>
+ , detail::iterable_operators<tuple<>>
+ {
+ constexpr tuple() { }
+ using hana_tag = tuple_tag;
+ };
+
+ template <typename ...Xn>
+ struct tuple
+ : detail::operators::adl<tuple<Xn...>>
+ , detail::iterable_operators<tuple<Xn...>>
+ {
+ basic_tuple<Xn...> storage_;
+ using hana_tag = tuple_tag;
+
+ private:
+ template <typename Other, std::size_t ...n>
+ explicit constexpr tuple(detail::from_index_sequence_t, std::index_sequence<n...>, Other&& other)
+ : storage_(hana::get_impl<n>(static_cast<Other&&>(other))...)
+ { }
+
+ public:
+ template <typename ...dummy, typename = typename std::enable_if<
+ detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, dummy...)...>::value
+ >::type>
+ constexpr tuple()
+ : storage_()
+ { }
+
+ template <typename ...dummy, typename = typename std::enable_if<
+ detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn const&, dummy...)...>::value
+ >::type>
+ constexpr tuple(Xn const& ...xn)
+ : storage_(xn...)
+ { }
+
+ template <typename ...Yn, typename = typename std::enable_if<
+ detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Yn&&)...>::value
+ >::type>
+ constexpr tuple(Yn&& ...yn)
+ : storage_(static_cast<Yn&&>(yn)...)
+ { }
+
+ template <typename ...Yn, typename = typename std::enable_if<
+ detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Yn const&)...>::value
+ >::type>
+ constexpr tuple(tuple<Yn...> const& other)
+ : tuple(detail::from_index_sequence_t{},
+ std::make_index_sequence<sizeof...(Xn)>{},
+ other.storage_)
+ { }
+
+ template <typename ...Yn, typename = typename std::enable_if<
+ detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Yn&&)...>::value
+ >::type>
+ constexpr tuple(tuple<Yn...>&& other)
+ : tuple(detail::from_index_sequence_t{},
+ std::make_index_sequence<sizeof...(Xn)>{},
+ static_cast<tuple<Yn...>&&>(other).storage_)
+ { }
+
+ // The three following constructors are required to make sure that
+ // the tuple(Yn&&...) constructor is _not_ preferred over the copy
+ // constructor for unary tuples containing a type that is constructible
+ // from tuple<...>. See test/tuple/trap_construct.cpp
+ template <typename ...dummy, typename = typename std::enable_if<
+ detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn const&, dummy...)...>::value
+ >::type>
+ constexpr tuple(tuple const& other)
+ : tuple(detail::from_index_sequence_t{},
+ std::make_index_sequence<sizeof...(Xn)>{},
+ other.storage_)
+ { }
+
+ template <typename ...dummy, typename = typename std::enable_if<
+ detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn const&, dummy...)...>::value
+ >::type>
+ constexpr tuple(tuple& other)
+ : tuple(const_cast<tuple const&>(other))
+ { }
+
+ template <typename ...dummy, typename = typename std::enable_if<
+ detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn&&, dummy...)...>::value
+ >::type>
+ constexpr tuple(tuple&& other)
+ : tuple(detail::from_index_sequence_t{},
+ std::make_index_sequence<sizeof...(Xn)>{},
+ static_cast<tuple&&>(other).storage_)
+ { }
+
+
+ template <typename ...Yn, typename = typename std::enable_if<
+ detail::fast_and<BOOST_HANA_TT_IS_ASSIGNABLE(Xn&, Yn const&)...>::value
+ >::type>
+ constexpr tuple& operator=(tuple<Yn...> const& other) {
+ detail::assign(this->storage_, other.storage_,
+ std::make_index_sequence<sizeof...(Xn)>{});
+ return *this;
+ }
+
+ template <typename ...Yn, typename = typename std::enable_if<
+ detail::fast_and<BOOST_HANA_TT_IS_ASSIGNABLE(Xn&, Yn&&)...>::value
+ >::type>
+ constexpr tuple& operator=(tuple<Yn...>&& other) {
+ detail::assign(this->storage_, static_cast<tuple<Yn...>&&>(other).storage_,
+ std::make_index_sequence<sizeof...(Xn)>{});
+ return *this;
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Operators
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <>
+ struct comparable_operators<tuple_tag> {
+ static constexpr bool value = true;
+ };
+ template <>
+ struct orderable_operators<tuple_tag> {
+ static constexpr bool value = true;
+ };
+ template <>
+ struct monad_operators<tuple_tag> {
+ static constexpr bool value = true;
+ };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Foldable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct unpack_impl<tuple_tag> {
+ template <typename F>
+ static constexpr decltype(auto) apply(tuple<>&&, F&& f)
+ { return static_cast<F&&>(f)(); }
+ template <typename F>
+ static constexpr decltype(auto) apply(tuple<>&, F&& f)
+ { return static_cast<F&&>(f)(); }
+ template <typename F>
+ static constexpr decltype(auto) apply(tuple<> const&, F&& f)
+ { return static_cast<F&&>(f)(); }
+
+ template <typename Xs, typename F>
+ static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
+ return hana::unpack(static_cast<Xs&&>(xs).storage_, static_cast<F&&>(f));
+ }
+ };
+
+ template <>
+ struct length_impl<tuple_tag> {
+ template <typename ...Xs>
+ static constexpr auto apply(tuple<Xs...> const&)
+ { return hana::size_c<sizeof...(Xs)>; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Iterable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct at_impl<tuple_tag> {
+ template <typename Xs, typename N>
+ static constexpr decltype(auto) apply(Xs&& xs, N const&) {
+ constexpr std::size_t index = N::value;
+ return hana::get_impl<index>(static_cast<Xs&&>(xs).storage_);
+ }
+ };
+
+ template <>
+ struct drop_front_impl<tuple_tag> {
+ template <std::size_t N, typename Xs, std::size_t ...i>
+ static constexpr auto helper(Xs&& xs, std::index_sequence<i...>) {
+ return hana::make<tuple_tag>(hana::at_c<i+N>(static_cast<Xs&&>(xs))...);
+ }
+
+ template <typename Xs, typename N>
+ 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
+ >{});
+ }
+ };
+
+ template <>
+ struct is_empty_impl<tuple_tag> {
+ template <typename ...Xs>
+ static constexpr auto apply(tuple<Xs...> const&)
+ { return hana::bool_c<sizeof...(Xs) == 0>; }
+ };
+
+ // compile-time optimizations (to reduce the # of function instantiations)
+ template <std::size_t n, typename ...Xs>
+ constexpr decltype(auto) at_c(tuple<Xs...> const& xs) {
+ return hana::get_impl<n>(xs.storage_);
+ }
+
+ template <std::size_t n, typename ...Xs>
+ constexpr decltype(auto) at_c(tuple<Xs...>& xs) {
+ return hana::get_impl<n>(xs.storage_);
+ }
+
+ template <std::size_t n, typename ...Xs>
+ constexpr decltype(auto) at_c(tuple<Xs...>&& xs) {
+ return hana::get_impl<n>(static_cast<tuple<Xs...>&&>(xs).storage_);
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Sequence
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct Sequence<tuple_tag> {
+ static constexpr bool value = true;
+ };
+
+ template <>
+ struct make_impl<tuple_tag> {
+ template <typename ...Xs>
+ static constexpr
+ tuple<typename detail::decay<Xs>::type...> apply(Xs&& ...xs)
+ { return {static_cast<Xs&&>(xs)...}; }
+ };
+
+ template <>
+ struct find_if_impl<tuple_tag> {
+ template <std::size_t index, typename Xs>
+ static constexpr auto helper(Xs&&, hana::true_) {
+ return hana::nothing;
+ }
+
+ template <std::size_t index, typename Xs>
+ static constexpr auto helper(Xs&& xs, hana::false_) {
+ return hana::just(hana::at_c<index>(static_cast<Xs&&>(xs)));
+ }
+
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs&& xs, Pred&&) {
+ using Pack = typename detail::make_pack<Xs>::type;
+ constexpr std::size_t index = detail::index_if<Pred&&, Pack>::value;
+ constexpr std::size_t len = Pack::length;
+ return helper<index>(static_cast<Xs&&>(xs), hana::bool_c<index == len>);
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_TUPLE_HPP
diff --git a/boost/hana/type.hpp b/boost/hana/type.hpp
new file mode 100644
index 0000000000..71d3c89086
--- /dev/null
+++ b/boost/hana/type.hpp
@@ -0,0 +1,223 @@
+/*!
+@file
+Defines `boost::hana::type` and related utilities.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_TYPE_HPP
+#define BOOST_HANA_TYPE_HPP
+
+#include <boost/hana/fwd/type.hpp>
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/operators/adl.hpp>
+#include <boost/hana/detail/operators/comparable.hpp>
+#include <boost/hana/fwd/concept/metafunction.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+#include <boost/hana/fwd/equal.hpp>
+#include <boost/hana/fwd/hash.hpp>
+#include <boost/hana/integral_constant.hpp>
+
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //////////////////////////////////////////////////////////////////////////
+ // basic_type
+ //////////////////////////////////////////////////////////////////////////
+ //! @cond
+ template <typename T>
+ struct basic_type : detail::operators::adl<basic_type<T>> {
+ using hana_tag = type_tag;
+
+ using type = T;
+ constexpr auto operator+() const { return *this; }
+ };
+ //! @endcond
+
+ //////////////////////////////////////////////////////////////////////////
+ // type
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T>
+ struct type_impl {
+ struct _ : basic_type<T> { };
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // decltype_
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <typename T, typename = type_tag>
+ struct decltype_t {
+ using type = typename std::remove_reference<T>::type;
+ };
+
+ template <typename T>
+ struct decltype_t<T, typename hana::tag_of<T>::type> {
+ using type = typename std::remove_reference<T>::type::type;
+ };
+ }
+
+ //! @cond
+ template <typename T>
+ constexpr auto decltype_t::operator()(T&&) const
+ { return hana::type_c<typename detail::decltype_t<T>::type>; }
+ //! @endcond
+
+ //////////////////////////////////////////////////////////////////////////
+ // make<type_tag>
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct make_impl<type_tag> {
+ template <typename T>
+ static constexpr auto apply(T&& t)
+ { return hana::decltype_(static_cast<T&&>(t)); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // sizeof_
+ //////////////////////////////////////////////////////////////////////////
+ //! @cond
+ template <typename T>
+ constexpr auto sizeof_t::operator()(T&&) const
+ { return hana::size_c<sizeof(typename detail::decltype_t<T>::type)>; }
+ //! @endcond
+
+ //////////////////////////////////////////////////////////////////////////
+ // alignof_
+ //////////////////////////////////////////////////////////////////////////
+ //! @cond
+ template <typename T>
+ constexpr auto alignof_t::operator()(T&&) const
+ { return hana::size_c<alignof(typename detail::decltype_t<T>::type)>; }
+ //! @endcond
+
+ //////////////////////////////////////////////////////////////////////////
+ // is_valid
+ //////////////////////////////////////////////////////////////////////////
+ namespace type_detail {
+ template <typename F, typename ...Args, typename = decltype(
+ std::declval<F&&>()(std::declval<Args&&>()...)
+ )>
+ constexpr auto is_valid_impl(int) { return hana::true_c; }
+
+ template <typename F, typename ...Args>
+ constexpr auto is_valid_impl(...) { return hana::false_c; }
+
+ template <typename F>
+ struct is_valid_fun {
+ template <typename ...Args>
+ constexpr auto operator()(Args&& ...) const
+ { return is_valid_impl<F, Args&&...>(int{}); }
+ };
+ }
+
+ //! @cond
+ template <typename F>
+ constexpr auto is_valid_t::operator()(F&&) const
+ { return type_detail::is_valid_fun<F&&>{}; }
+
+ template <typename F, typename ...Args>
+ constexpr auto is_valid_t::operator()(F&&, Args&& ...) const
+ { return type_detail::is_valid_impl<F&&, Args&&...>(int{}); }
+ //! @endcond
+
+ //////////////////////////////////////////////////////////////////////////
+ // template_
+ //////////////////////////////////////////////////////////////////////////
+ template <template <typename ...> class F>
+ struct template_t {
+ template <typename ...T>
+ struct apply {
+ using type = F<T...>;
+ };
+
+ template <typename ...T>
+ constexpr auto operator()(T const& ...) const
+ { return hana::type<F<typename T::type...>>{}; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // metafunction
+ //////////////////////////////////////////////////////////////////////////
+ template <template <typename ...> class F>
+ struct metafunction_t {
+ template <typename ...T>
+ using apply = F<T...>;
+
+ template <typename ...T>
+ constexpr hana::type<typename F<typename T::type...>::type>
+ operator()(T const& ...) const { return {}; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Metafunction
+ //////////////////////////////////////////////////////////////////////////
+ template <template <typename ...> class F>
+ struct Metafunction<template_t<F>> {
+ static constexpr bool value = true;
+ };
+
+ template <template <typename ...> class F>
+ struct Metafunction<metafunction_t<F>> {
+ static constexpr bool value = true;
+ };
+
+ template <typename F>
+ struct Metafunction<metafunction_class_t<F>> {
+ static constexpr bool value = true;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // integral
+ //////////////////////////////////////////////////////////////////////////
+ template <typename F>
+ struct integral_t {
+ template <typename ...T>
+ constexpr auto operator()(T const& ...) const {
+ using Result = typename F::template apply<typename T::type...>::type;
+ return Result{};
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Operators
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <>
+ struct comparable_operators<type_tag> {
+ static constexpr bool value = true;
+ };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Comparable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct equal_impl<type_tag, type_tag> {
+ template <typename T, typename U>
+ static constexpr auto apply(basic_type<T> const&, basic_type<U> const&)
+ { return hana::false_c; }
+
+ template <typename T>
+ static constexpr auto apply(basic_type<T> const&, basic_type<T> const&)
+ { return hana::true_c; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Hashable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct hash_impl<hana::type_tag> {
+ template <typename T>
+ static constexpr T apply(T const& t)
+ { return t; }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_TYPE_HPP
diff --git a/boost/hana/unfold_left.hpp b/boost/hana/unfold_left.hpp
new file mode 100644
index 0000000000..fff29f77ca
--- /dev/null
+++ b/boost/hana/unfold_left.hpp
@@ -0,0 +1,71 @@
+/*!
+@file
+Defines `boost::hana::unfold_left`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_UNFOLD_LEFT_HPP
+#define BOOST_HANA_UNFOLD_LEFT_HPP
+
+#include <boost/hana/fwd/unfold_left.hpp>
+
+#include <boost/hana/append.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/empty.hpp>
+#include <boost/hana/first.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/optional.hpp>
+#include <boost/hana/second.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename S>
+ struct unfold_left_t {
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::unfold_left<S> requires 'S' to be a Sequence");
+ #endif
+
+ template <typename State, typename F>
+ constexpr auto operator()(State&& state, F&& f) const {
+ return unfold_left_impl<S>::apply(
+ static_cast<State&&>(state),
+ static_cast<F&&>(f)
+ );
+ }
+ };
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct unfold_left_impl<S, when<condition>> : default_ {
+ struct unfold_left_helper {
+ template <typename F, typename P>
+ constexpr auto operator()(F&& f, P&& p) const {
+ return hana::append(
+ unfold_left_impl::apply(
+ hana::first(static_cast<P&&>(p)),
+ static_cast<F&&>(f)
+ ),
+ hana::second(static_cast<P&&>(p))
+ );
+ }
+ };
+
+ template <typename Init, typename F>
+ static constexpr auto apply(Init&& init, F&& f) {
+ decltype(auto) elt = f(static_cast<Init&&>(init));
+ return hana::maybe(empty<S>(),
+ hana::partial(unfold_left_helper{}, static_cast<F&&>(f)),
+ static_cast<decltype(elt)&&>(elt)
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_UNFOLD_LEFT_HPP
diff --git a/boost/hana/unfold_right.hpp b/boost/hana/unfold_right.hpp
new file mode 100644
index 0000000000..c0f4457c53
--- /dev/null
+++ b/boost/hana/unfold_right.hpp
@@ -0,0 +1,71 @@
+/*!
+@file
+Defines `boost::hana::unfold_right`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_UNFOLD_RIGHT_HPP
+#define BOOST_HANA_UNFOLD_RIGHT_HPP
+
+#include <boost/hana/fwd/unfold_right.hpp>
+
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/empty.hpp>
+#include <boost/hana/first.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/optional.hpp>
+#include <boost/hana/prepend.hpp>
+#include <boost/hana/second.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename S>
+ struct unfold_right_t {
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::unfold_right<S> requires 'S' to be a Sequence");
+ #endif
+
+ template <typename State, typename F>
+ constexpr auto operator()(State&& state, F&& f) const {
+ return unfold_right_impl<S>::apply(
+ static_cast<State&&>(state),
+ static_cast<F&&>(f)
+ );
+ }
+ };
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct unfold_right_impl<S, when<condition>> : default_ {
+ struct unfold_right_helper {
+ template <typename F, typename P>
+ constexpr auto operator()(F&& f, P&& p) const {
+ return hana::prepend(
+ unfold_right_impl::apply(
+ hana::second(static_cast<P&&>(p)),
+ static_cast<F&&>(f)
+ ),
+ hana::first(static_cast<P&&>(p))
+ );
+ }
+ };
+
+ template <typename Init, typename F>
+ static constexpr auto apply(Init&& init, F&& f) {
+ decltype(auto) elt = f(static_cast<Init&&>(init));
+ return hana::maybe(hana::empty<S>(),
+ hana::partial(unfold_right_helper{}, static_cast<F&&>(f)),
+ static_cast<decltype(elt)&&>(elt)
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_UNFOLD_RIGHT_HPP
diff --git a/boost/hana/union.hpp b/boost/hana/union.hpp
new file mode 100644
index 0000000000..733f7b6bcd
--- /dev/null
+++ b/boost/hana/union.hpp
@@ -0,0 +1,39 @@
+/*!
+@file
+Defines `boost::hana::union`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_UNION_HPP
+#define BOOST_HANA_UNION_HPP
+
+#include <boost/hana/fwd/union.hpp>
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename Ys>
+ constexpr auto union_t::operator()(Xs&& xs, Ys&& ys) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Union = BOOST_HANA_DISPATCH_IF(union_impl<S>,
+ true
+ );
+
+ return Union::apply(static_cast<Xs&&>(xs), static_cast<Ys&&>(ys));
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct union_impl<S, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_UNION_HPP
diff --git a/boost/hana/unique.hpp b/boost/hana/unique.hpp
new file mode 100644
index 0000000000..c4f30798eb
--- /dev/null
+++ b/boost/hana/unique.hpp
@@ -0,0 +1,75 @@
+/*!
+@file
+Defines `boost::hana::unique`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_UNIQUE_HPP
+#define BOOST_HANA_UNIQUE_HPP
+
+#include <boost/hana/fwd/unique.hpp>
+
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/nested_by.hpp> // required by fwd decl
+#include <boost/hana/equal.hpp>
+#include <boost/hana/front.hpp>
+#include <boost/hana/group.hpp>
+#include <boost/hana/transform.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs>
+ constexpr auto unique_t::operator()(Xs&& xs) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Unique = BOOST_HANA_DISPATCH_IF(unique_impl<S>,
+ hana::Sequence<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::unique(xs) requires 'xs' to be a Sequence");
+ #endif
+
+ return Unique::apply(static_cast<Xs&&>(xs));
+ }
+
+ template <typename Xs, typename Predicate>
+ constexpr auto unique_t::operator()(Xs&& xs, Predicate&& predicate) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Unique = BOOST_HANA_DISPATCH_IF(unique_impl<S>,
+ hana::Sequence<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Sequence<S>::value,
+ "hana::unique(xs, predicate) requires 'xs' to be a Sequence");
+ #endif
+
+ return Unique::apply(static_cast<Xs&&>(xs),
+ static_cast<Predicate&&>(predicate));
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct unique_impl<S, when<condition>> : default_ {
+ template <typename Xs, typename Pred>
+ static constexpr auto apply(Xs&& xs, Pred&& pred) {
+ return hana::transform(
+ hana::group(static_cast<Xs&&>(xs), static_cast<Pred&&>(pred)),
+ hana::front
+ );
+ }
+
+ template <typename Xs>
+ static constexpr auto apply(Xs&& xs)
+ { return unique_impl::apply(static_cast<Xs&&>(xs), hana::equal); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_UNIQUE_HPP
diff --git a/boost/hana/unpack.hpp b/boost/hana/unpack.hpp
new file mode 100644
index 0000000000..03a4faed93
--- /dev/null
+++ b/boost/hana/unpack.hpp
@@ -0,0 +1,141 @@
+/*!
+@file
+Defines `boost::hana::unpack`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_UNPACK_HPP
+#define BOOST_HANA_UNPACK_HPP
+
+#include <boost/hana/fwd/unpack.hpp>
+
+#include <boost/hana/accessors.hpp>
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/concept/iterable.hpp>
+#include <boost/hana/concept/struct.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/first.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/fwd/fold_left.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/pair.hpp>
+#include <boost/hana/second.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename F>
+ constexpr decltype(auto) unpack_t::operator()(Xs&& xs, F&& f) const {
+ using S = typename hana::tag_of<Xs>::type;
+ using Unpack = BOOST_HANA_DISPATCH_IF(unpack_impl<S>,
+ hana::Foldable<S>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Foldable<S>::value,
+ "hana::unpack(xs, f) requires 'xs' to be Foldable");
+ #endif
+
+ return Unpack::apply(static_cast<Xs&&>(xs), static_cast<F&&>(f));
+ }
+ //! @endcond
+
+ template <typename T, bool condition>
+ struct unpack_impl<T, when<condition>> : default_ {
+ template <typename Xs, typename F>
+ static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
+ return hana::fold_left(static_cast<Xs&&>(xs),
+ static_cast<F&&>(f),
+ hana::partial)();
+ }
+ };
+
+ template <typename It>
+ struct unpack_impl<It, when<
+ hana::Iterable<It>::value && !is_default<length_impl<It>>::value
+ >> {
+ template <typename Xs, typename F, std::size_t ...i>
+ static constexpr decltype(auto)
+ unpack_helper(Xs&& xs, F&& f, std::index_sequence<i...>) {
+ return static_cast<F&&>(f)(hana::at_c<i>(static_cast<Xs&&>(xs))...);
+ }
+
+ template <typename Xs, typename F>
+ static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
+ constexpr std::size_t N = decltype(hana::length(xs))::value;
+ return unpack_helper(static_cast<Xs&&>(xs), static_cast<F&&>(f),
+ std::make_index_sequence<N>{});
+ }
+ };
+
+ template <typename T, std::size_t N>
+ struct unpack_impl<T[N]> {
+ template <typename Xs, typename F, std::size_t ...i>
+ static constexpr decltype(auto)
+ unpack_helper(Xs&& xs, F&& f, std::index_sequence<i...>) {
+ return static_cast<F&&>(f)(static_cast<Xs&&>(xs)[i]...);
+ }
+
+ template <typename Xs, typename F>
+ static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
+ return unpack_impl::unpack_helper(static_cast<Xs&&>(xs),
+ static_cast<F&&>(f),
+ std::make_index_sequence<N>{});
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for Products
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T>
+ struct unpack_impl<T, when<hana::Product<T>::value>> {
+ template <typename P, typename F>
+ static constexpr decltype(auto) apply(P&& p, F&& f) {
+ return static_cast<F&&>(f)(
+ hana::first(static_cast<P&&>(p)),
+ hana::second(static_cast<P&&>(p))
+ );
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for Structs
+ //////////////////////////////////////////////////////////////////////////
+ namespace struct_detail {
+ // This is equivalent to `demux`, except that `demux` can't forward
+ // the `udt` because it does not know the `g`s are accessors. Hence,
+ // this can result in faster code.
+ struct almost_demux {
+ template <typename F, typename Udt, typename ...Members>
+ constexpr decltype(auto)
+ operator()(F&& f, Udt&& udt, Members&& ...g) const {
+ return static_cast<F&&>(f)(hana::make_pair(
+ hana::first(static_cast<Members&&>(g)),
+ hana::second(static_cast<Members&&>(g))
+ (static_cast<Udt&&>(udt))
+ )...);
+ }
+ };
+ }
+
+ template <typename S>
+ struct unpack_impl<S, when<hana::Struct<S>::value>> {
+ template <typename Udt, typename F>
+ static constexpr decltype(auto) apply(Udt&& udt, F&& f) {
+ return hana::unpack(hana::accessors<S>(),
+ hana::partial(struct_detail::almost_demux{},
+ static_cast<F&&>(f),
+ static_cast<Udt&&>(udt)));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_UNPACK_HPP
diff --git a/boost/hana/value.hpp b/boost/hana/value.hpp
new file mode 100644
index 0000000000..fd5b5c4029
--- /dev/null
+++ b/boost/hana/value.hpp
@@ -0,0 +1,56 @@
+/*!
+@file
+Defines `boost::hana::value`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_VALUE_HPP
+#define BOOST_HANA_VALUE_HPP
+
+#include <boost/hana/fwd/value.hpp>
+
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename C, bool condition>
+ struct value_impl<C, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...args) = delete;
+ };
+
+ template <typename T>
+ constexpr decltype(auto) value() {
+ using RawT = typename std::remove_cv<
+ typename std::remove_reference<T>::type
+ >::type;
+ using C = typename hana::tag_of<RawT>::type;
+ using Value = BOOST_HANA_DISPATCH_IF(
+ value_impl<C>, hana::Constant<C>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Constant<C>::value,
+ "hana::value<T>() requires 'T' to be a Constant");
+ #endif
+
+ return Value::template apply<RawT>();
+ }
+
+ template <typename I>
+ struct value_impl<I, when<hana::IntegralConstant<I>::value>> {
+ template <typename C>
+ static constexpr auto apply()
+ { return C::value; }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_VALUE_HPP
diff --git a/boost/hana/version.hpp b/boost/hana/version.hpp
new file mode 100644
index 0000000000..232825bc65
--- /dev/null
+++ b/boost/hana/version.hpp
@@ -0,0 +1,53 @@
+/*!
+@file
+Defines macros for tracking the version of the library.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_VERSION_HPP
+#define BOOST_HANA_VERSION_HPP
+
+//! @internal
+//! Transforms a (version, revision, patchlevel) triple into a number of the
+//! form 0xVVRRPPPP to allow comparing versions in a normalized way.
+//!
+//! See http://sourceforge.net/p/predef/wiki/VersionNormalization.
+#define BOOST_HANA_CONFIG_VERSION(version, revision, patch) \
+ (((version) << 24) + ((revision) << 16) + (patch))
+
+//! @ingroup group-config
+//! Macro expanding to the major version of the library, i.e. the `x` in `x.y.z`.
+#define BOOST_HANA_MAJOR_VERSION 1
+
+//! @ingroup group-config
+//! Macro expanding to the minor version of the library, i.e. the `y` in `x.y.z`.
+#define BOOST_HANA_MINOR_VERSION 0
+
+//! @ingroup group-config
+//! Macro expanding to the patch level of the library, i.e. the `z` in `x.y.z`.
+#define BOOST_HANA_PATCH_VERSION 0
+
+//! @ingroup group-config
+//! Macro expanding to the full version of the library, in hexadecimal
+//! representation.
+//!
+//! Specifically, `BOOST_HANA_VERSION` expands to an hexadecimal number of the
+//! form 0xVVRRPPPP, where `VV` is the major version of the library, `RR` is
+//! the minor version and `PPPP` is the patch level. This allows the version
+//! of the library to be compared:
+//! @snippet example/version.cpp main
+//!
+//!
+//! @note
+//! The major, minor and patch versions of the library are also available
+//! individually with the `BOOST_HANA_{MAJOR,MINOR,PATCH}_VERSION` macros.
+#define BOOST_HANA_VERSION \
+ BOOST_HANA_CONFIG_VERSION(BOOST_HANA_MAJOR_VERSION, \
+ BOOST_HANA_MINOR_VERSION, \
+ BOOST_HANA_PATCH_VERSION) \
+/**/
+
+#endif // !BOOST_HANA_VERSION_HPP
diff --git a/boost/hana/while.hpp b/boost/hana/while.hpp
new file mode 100644
index 0000000000..36ff9ab64b
--- /dev/null
+++ b/boost/hana/while.hpp
@@ -0,0 +1,117 @@
+/*!
+@file
+Defines `boost::hana::while_`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_WHILE_HPP
+#define BOOST_HANA_WHILE_HPP
+
+#include <boost/hana/fwd/while.hpp>
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/logical.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/canonical_constant.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Pred, typename State, typename F>
+ constexpr decltype(auto) while_t::operator()(Pred&& pred, State&& state, F&& f) const {
+ using Cond = decltype(pred(state));
+ using Bool = typename hana::tag_of<Cond>::type;
+ using While = BOOST_HANA_DISPATCH_IF(while_impl<Bool>,
+ hana::Logical<Bool>::value
+ );
+
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Logical<Bool>::value,
+ "hana::while_(pred, state, f) requires 'pred(state)' to be a Logical");
+ #endif
+
+ return While::apply(static_cast<Pred&&>(pred),
+ static_cast<State&&>(state),
+ static_cast<F&&>(f));
+ }
+ //! @endcond
+
+ template <typename L, bool condition>
+ struct while_impl<L, hana::when<condition>> : hana::default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+
+ template <typename L>
+ struct while_impl<L, hana::when<std::is_arithmetic<L>::value>> {
+ template <typename Pred, typename State, typename F>
+ static auto apply(Pred&& pred, State&& state, F&& f)
+ -> decltype(
+ true ? f(static_cast<State&&>(state))
+ : static_cast<State&&>(state)
+ )
+ {
+ if (pred(state)) {
+ decltype(auto) r = f(static_cast<State&&>(state));
+ return hana::while_(static_cast<Pred&&>(pred),
+ static_cast<decltype(r)&&>(r),
+ static_cast<F&&>(f));
+ }
+ else {
+ return static_cast<State&&>(state);
+ }
+ }
+ };
+
+ template <typename C>
+ struct while_impl<C, hana::when<
+ hana::Constant<C>::value &&
+ hana::Logical<typename C::value_type>::value
+ >> {
+ template <typename Pred, typename State, typename F>
+ static constexpr State
+ while_helper(hana::false_, Pred&&, State&& state, F&&) {
+ return static_cast<State&&>(state);
+ }
+
+ template <typename Pred, typename State, typename F>
+ static constexpr decltype(auto)
+ while_helper(hana::true_, Pred&& pred, State&& state, F&& f) {
+ decltype(auto) r = f(static_cast<State&&>(state));
+ return hana::while_(static_cast<Pred&&>(pred),
+ static_cast<decltype(r)&&>(r),
+ static_cast<F&&>(f));
+ }
+
+ template <typename Pred, typename State, typename F>
+ static constexpr decltype(auto)
+ apply(Pred&& pred, State&& state, F&& f) {
+ // Since `pred(state)` returns a `Constant`, we do not actually
+ // need to call it; we only need its decltype. However, we still
+ // call it to run potential side effects. I'm not sure whether
+ // that is desirable, since we pretty much take for granted that
+ // functions are pure, but we'll do it like this for now. Also, I
+ // think there is something rather deep hidden behind this, and
+ // understanding what must be done here should give us a better
+ // understanding of something non-trivial.
+ auto cond_ = pred(state);
+ constexpr auto cond = hana::value(cond_);
+ constexpr bool truth_value = hana::if_(cond, true, false);
+ return while_helper(hana::bool_c<truth_value>,
+ static_cast<Pred&&>(pred),
+ static_cast<State&&>(state),
+ static_cast<F&&>(f));
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_WHILE_HPP
diff --git a/boost/hana/zero.hpp b/boost/hana/zero.hpp
new file mode 100644
index 0000000000..6c71c9247d
--- /dev/null
+++ b/boost/hana/zero.hpp
@@ -0,0 +1,81 @@
+/*!
+@file
+Defines `boost::hana::zero`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_ZERO_HPP
+#define BOOST_HANA_ZERO_HPP
+
+#include <boost/hana/fwd/zero.hpp>
+
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/monoid.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/canonical_constant.hpp>
+
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ template <typename M>
+ struct zero_t {
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(hana::Monoid<M>::value,
+ "hana::zero<M>() requires 'M' to be a Monoid");
+ #endif
+
+ constexpr decltype(auto) operator()() const {
+ using Zero = BOOST_HANA_DISPATCH_IF(zero_impl<M>,
+ hana::Monoid<M>::value
+ );
+
+ return Zero::apply();
+ }
+ };
+
+ template <typename M, bool condition>
+ struct zero_impl<M, when<condition>> : default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for non-boolean arithmetic data types
+ //////////////////////////////////////////////////////////////////////////
+ template <typename T>
+ struct zero_impl<T, when<
+ std::is_arithmetic<T>::value &&
+ !std::is_same<T, bool>::value
+ >> {
+ static constexpr T apply()
+ { return static_cast<T>(0); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model for Constants over a Monoid
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <typename C>
+ struct constant_from_zero {
+ static constexpr auto value = hana::zero<typename C::value_type>();
+ using hana_tag = detail::CanonicalConstant<typename C::value_type>;
+ };
+ }
+
+ template <typename C>
+ struct zero_impl<C, when<
+ hana::Constant<C>::value &&
+ Monoid<typename C::value_type>::value
+ >> {
+ static constexpr decltype(auto) apply()
+ { return hana::to<C>(detail::constant_from_zero<C>{}); }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_ZERO_HPP
diff --git a/boost/hana/zip.hpp b/boost/hana/zip.hpp
new file mode 100644
index 0000000000..d777701ad9
--- /dev/null
+++ b/boost/hana/zip.hpp
@@ -0,0 +1,50 @@
+/*!
+@file
+Defines `boost::hana::zip`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_ZIP_HPP
+#define BOOST_HANA_ZIP_HPP
+
+#include <boost/hana/fwd/zip.hpp>
+
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/fast_and.hpp>
+#include <boost/hana/tuple.hpp>
+#include <boost/hana/zip_with.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename ...Ys>
+ constexpr auto zip_t::operator()(Xs&& xs, Ys&& ...ys) const {
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(detail::fast_and<
+ hana::Sequence<Xs>::value, hana::Sequence<Ys>::value...
+ >::value,
+ "hana::zip(xs, ys...) requires 'xs' and 'ys...' to be Sequences");
+ #endif
+
+ return zip_impl<typename hana::tag_of<Xs>::type>::apply(
+ static_cast<Xs&&>(xs),
+ static_cast<Ys&&>(ys)...
+ );
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct zip_impl<S, when<condition>> : default_ {
+ template <typename ...Xs>
+ static constexpr decltype(auto) apply(Xs&& ...xs) {
+ return hana::zip_with(hana::make_tuple, static_cast<Xs&&>(xs)...);
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_ZIP_HPP
diff --git a/boost/hana/zip_shortest.hpp b/boost/hana/zip_shortest.hpp
new file mode 100644
index 0000000000..4976d79f42
--- /dev/null
+++ b/boost/hana/zip_shortest.hpp
@@ -0,0 +1,51 @@
+/*!
+@file
+Defines `boost::hana::zip_shortest`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_ZIP_SHORTEST_HPP
+#define BOOST_HANA_ZIP_SHORTEST_HPP
+
+#include <boost/hana/fwd/zip_shortest.hpp>
+
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/detail/fast_and.hpp>
+#include <boost/hana/tuple.hpp>
+#include <boost/hana/zip_shortest_with.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename Xs, typename ...Ys>
+ constexpr auto zip_shortest_t::operator()(Xs&& xs, Ys&& ...ys) const {
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(detail::fast_and<
+ hana::Sequence<Xs>::value, hana::Sequence<Ys>::value...
+ >::value,
+ "hana::zip_shortest(xs, ys...) requires 'xs' and 'ys...' to be Sequences");
+ #endif
+
+ return zip_shortest_impl<typename hana::tag_of<Xs>::type>::apply(
+ static_cast<Xs&&>(xs),
+ static_cast<Ys&&>(ys)...
+ );
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct zip_shortest_impl<S, when<condition>> : default_ {
+ template <typename ...Xs>
+ static constexpr decltype(auto) apply(Xs&& ...xs) {
+ return hana::zip_shortest_with(hana::make_tuple,
+ static_cast<Xs&&>(xs)...);
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_ZIP_SHORTEST_HPP
diff --git a/boost/hana/zip_shortest_with.hpp b/boost/hana/zip_shortest_with.hpp
new file mode 100644
index 0000000000..c0e6dcdf65
--- /dev/null
+++ b/boost/hana/zip_shortest_with.hpp
@@ -0,0 +1,63 @@
+/*!
+@file
+Defines `boost::hana::zip_shortest_with`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_ZIP_SHORTEST_WITH_HPP
+#define BOOST_HANA_ZIP_SHORTEST_WITH_HPP
+
+#include <boost/hana/fwd/zip_shortest_with.hpp>
+
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/algorithm.hpp>
+#include <boost/hana/detail/fast_and.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/take_front.hpp>
+#include <boost/hana/zip_with.hpp>
+
+#include <cstddef>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename F, typename Xs, typename ...Ys>
+ constexpr auto
+ zip_shortest_with_t::operator()(F&& f, Xs&& xs, Ys&& ...ys) const {
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(detail::fast_and<
+ hana::Sequence<Xs>::value, hana::Sequence<Ys>::value...
+ >::value,
+ "hana::zip_shortest_with(f, xs, ys...) requires 'xs' and 'ys...' to be Sequences");
+ #endif
+
+ return zip_shortest_with_impl<typename hana::tag_of<Xs>::type>::apply(
+ static_cast<F&&>(f),
+ static_cast<Xs&&>(xs),
+ static_cast<Ys&&>(ys)...
+ );
+ }
+ //! @endcond
+
+ template <typename S, bool condition>
+ struct zip_shortest_with_impl<S, when<condition>> : default_ {
+ template <typename F, typename ...Xs>
+ static constexpr decltype(auto) apply(F&& f, Xs&& ...xs) {
+ constexpr std::size_t lengths[] = {
+ decltype(hana::length(xs))::value...
+ };
+ constexpr std::size_t min = *detail::min_element(lengths, lengths + sizeof...(xs));
+ return hana::zip_with(static_cast<F&&>(f),
+ hana::take_front(static_cast<Xs&&>(xs), hana::size_c<min>)...
+ );
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_ZIP_SHORTEST_WITH_HPP
diff --git a/boost/hana/zip_with.hpp b/boost/hana/zip_with.hpp
new file mode 100644
index 0000000000..821b97d5db
--- /dev/null
+++ b/boost/hana/zip_with.hpp
@@ -0,0 +1,70 @@
+/*!
+@file
+Defines `boost::hana::zip_with`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_ZIP_WITH_HPP
+#define BOOST_HANA_ZIP_WITH_HPP
+
+#include <boost/hana/fwd/zip_with.hpp>
+
+#include <boost/hana/at.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/dispatch.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/detail/fast_and.hpp>
+#include <boost/hana/length.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @cond
+ template <typename F, typename Xs, typename ...Ys>
+ constexpr auto zip_with_t::operator()(F&& f, Xs&& xs, Ys&& ...ys) const {
+ #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
+ static_assert(detail::fast_and<
+ hana::Sequence<Xs>::value, hana::Sequence<Ys>::value...
+ >::value,
+ "hana::zip_with(f, xs, ys...) requires 'xs' and 'ys...' to be Sequences");
+ #endif
+
+ return zip_with_impl<typename hana::tag_of<Xs>::type>::apply(
+ static_cast<F&&>(f),
+ static_cast<Xs&&>(xs),
+ static_cast<Ys&&>(ys)...
+ );
+ }
+ //! @endcond
+
+ template <typename S>
+ struct zip_with_impl<S, when<Sequence<S>::value>> {
+ template <std::size_t N, typename F, typename ...Xs>
+ static constexpr decltype(auto) transverse(F&& f, Xs&& ...xs) {
+ return static_cast<F&&>(f)(hana::at_c<N>(static_cast<Xs&&>(xs))...);
+ }
+
+ template <std::size_t ...N, typename F, typename ...Xs>
+ static constexpr auto
+ zip_helper(std::index_sequence<N...>, F&& f, Xs&& ...xs) {
+ return hana::make<S>(transverse<N>(f, xs...)...);
+ }
+
+ template <typename F, typename X, typename ...Xs>
+ static constexpr auto
+ apply(F&& f, X&& x, Xs&& ...xs) {
+ constexpr std::size_t N = decltype(hana::length(x))::value;
+ return zip_helper(std::make_index_sequence<N>{},
+ static_cast<F&&>(f),
+ static_cast<X&&>(x), static_cast<Xs&&>(xs)...);
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_ZIP_WITH_HPP
diff --git a/boost/heap/binomial_heap.hpp b/boost/heap/binomial_heap.hpp
index 01ccf3fc8d..a6f75c3aee 100644
--- a/boost/heap/binomial_heap.hpp
+++ b/boost/heap/binomial_heap.hpp
@@ -516,8 +516,7 @@ public:
siftdown(n);
- if (n == top_element)
- update_top_element();
+ update_top_element();
}
/**
@@ -792,7 +791,6 @@ private:
trees.insert(it, *n);
}
n->add_child(parent);
- BOOST_HEAP_ASSERT(parent->child_count() == n->child_count());
}
}
diff --git a/boost/heap/detail/stable_heap.hpp b/boost/heap/detail/stable_heap.hpp
index 768c0bf7af..29efc48b50 100644
--- a/boost/heap/detail/stable_heap.hpp
+++ b/boost/heap/detail/stable_heap.hpp
@@ -20,6 +20,9 @@
#include <boost/heap/policies.hpp>
#include <boost/heap/heap_merge.hpp>
+#include <boost/type_traits/is_nothrow_move_constructible.hpp>
+#include <boost/type_traits/is_nothrow_move_assignable.hpp>
+
namespace boost {
namespace heap {
namespace detail {
@@ -30,54 +33,54 @@ struct size_holder
static const bool constant_time_size = ConstantSize;
typedef SizeType size_type;
- size_holder(void):
+ size_holder(void) BOOST_NOEXCEPT:
size_(0)
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- size_holder(size_holder && rhs):
+ size_holder(size_holder && rhs) BOOST_NOEXCEPT:
size_(rhs.size_)
{
rhs.size_ = 0;
}
- size_holder(size_holder const & rhs):
+ size_holder(size_holder const & rhs) BOOST_NOEXCEPT:
size_(rhs.size_)
{}
- size_holder & operator=(size_holder && rhs)
+ size_holder & operator=(size_holder && rhs) BOOST_NOEXCEPT
{
size_ = rhs.size_;
rhs.size_ = 0;
return *this;
}
- size_holder & operator=(size_holder const & rhs)
+ size_holder & operator=(size_holder const & rhs) BOOST_NOEXCEPT
{
size_ = rhs.size_;
return *this;
}
#endif
- SizeType get_size() const
+ SizeType get_size() const BOOST_NOEXCEPT
{ return size_; }
- void set_size(SizeType size)
+ void set_size(SizeType size) BOOST_NOEXCEPT
{ size_ = size; }
- void decrement()
+ void decrement() BOOST_NOEXCEPT
{ --size_; }
- void increment()
+ void increment() BOOST_NOEXCEPT
{ ++size_; }
- void add(SizeType value)
+ void add(SizeType value) BOOST_NOEXCEPT
{ size_ += value; }
- void sub(SizeType value)
+ void sub(SizeType value) BOOST_NOEXCEPT
{ size_ -= value; }
- void swap(size_holder & rhs)
+ void swap(size_holder & rhs) BOOST_NOEXCEPT
{ std::swap(size_, rhs.size_); }
SizeType size_;
@@ -89,46 +92,46 @@ struct size_holder<false, SizeType>
static const bool constant_time_size = false;
typedef SizeType size_type;
- size_holder(void)
+ size_holder(void) BOOST_NOEXCEPT
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- size_holder(size_holder && rhs)
+ size_holder(size_holder && rhs) BOOST_NOEXCEPT
{}
- size_holder(size_holder const & rhs)
+ size_holder(size_holder const & rhs) BOOST_NOEXCEPT
{}
- size_holder & operator=(size_holder && rhs)
+ size_holder & operator=(size_holder && rhs) BOOST_NOEXCEPT
{
return *this;
}
- size_holder & operator=(size_holder const & rhs)
+ size_holder & operator=(size_holder const & rhs) BOOST_NOEXCEPT
{
return *this;
}
#endif
- size_type get_size() const
+ size_type get_size() const BOOST_NOEXCEPT
{ return 0; }
- void set_size(size_type)
+ void set_size(size_type) BOOST_NOEXCEPT
{}
- void decrement()
+ void decrement() BOOST_NOEXCEPT
{}
- void increment()
+ void increment() BOOST_NOEXCEPT
{}
- void add(SizeType value)
+ void add(SizeType /*value*/) BOOST_NOEXCEPT
{}
- void sub(SizeType value)
+ void sub(SizeType /*value*/) BOOST_NOEXCEPT
{}
- void swap(size_holder & rhs)
+ void swap(size_holder & /*rhs*/) BOOST_NOEXCEPT
{}
};
@@ -167,7 +170,7 @@ struct heap_base:
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- heap_base(heap_base && rhs):
+ 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
@@ -185,7 +188,7 @@ struct heap_base:
size_holder_type(static_cast<size_holder_type const &>(rhs))
{}
- heap_base & operator=(heap_base && rhs)
+ heap_base & operator=(heap_base && rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_assignable<Cmp>::value)
{
value_comp_ref().operator=(std::move(rhs.value_comp_ref()));
size_holder_type::operator=(std::move(static_cast<size_holder_type&>(rhs)));
@@ -225,17 +228,17 @@ struct heap_base:
}
#endif
- static T & get_value(internal_type & val)
+ static T & get_value(internal_type & val) BOOST_NOEXCEPT
{
return val;
}
- static T const & get_value(internal_type const & val)
+ static T const & get_value(internal_type const & val) BOOST_NOEXCEPT
{
return val;
}
- Cmp const & value_comp(void) const
+ Cmp const & value_comp(void) const BOOST_NOEXCEPT
{
#ifndef BOOST_MSVC
return *this;
@@ -244,23 +247,23 @@ struct heap_base:
#endif
}
- Cmp const & get_internal_cmp(void) const
+ Cmp const & get_internal_cmp(void) const BOOST_NOEXCEPT
{
return value_comp();
}
- void swap(heap_base & rhs)
+ void swap(heap_base & rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<Cmp>::value && boost::is_nothrow_move_assignable<Cmp>::value)
{
std::swap(value_comp_ref(), rhs.value_comp_ref());
size_holder<constant_time_size, size_t>::swap(rhs);
}
- stability_counter_type get_stability_count(void) const
+ stability_counter_type get_stability_count(void) const BOOST_NOEXCEPT
{
return 0;
}
- void set_stability_count(stability_counter_type)
+ void set_stability_count(stability_counter_type) BOOST_NOEXCEPT
{}
template <typename Heap1, typename Heap2>
@@ -326,7 +329,7 @@ struct heap_base<T, Cmp, constant_time_size, StabilityCounterType, true>:
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- heap_base(heap_base && rhs):
+ 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
@@ -346,7 +349,7 @@ struct heap_base<T, Cmp, constant_time_size, StabilityCounterType, true>:
size_holder_type(static_cast<size_holder_type const &>(rhs)), counter_(rhs.counter_)
{}
- heap_base & operator=(heap_base && rhs)
+ heap_base & operator=(heap_base && rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_assignable<Cmp>::value)
{
value_comp_ref().operator=(std::move(rhs.value_comp_ref()));
size_holder_type::operator=(std::move(static_cast<size_holder_type&>(rhs)));
@@ -395,17 +398,17 @@ struct heap_base<T, Cmp, constant_time_size, StabilityCounterType, true>:
}
#endif
- static T & get_value(internal_type & val)
+ static T & get_value(internal_type & val) BOOST_NOEXCEPT
{
return val.first;
}
- static T const & get_value(internal_type const & val)
+ static T const & get_value(internal_type const & val) BOOST_NOEXCEPT
{
return val.first;
}
- Cmp const & value_comp(void) const
+ Cmp const & value_comp(void) const BOOST_NOEXCEPT
{
#ifndef BOOST_MSVC
return *this;
@@ -438,7 +441,7 @@ struct heap_base<T, Cmp, constant_time_size, StabilityCounterType, true>:
return internal_compare(value_comp());
}
- void swap(heap_base & rhs)
+ void swap(heap_base & rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<Cmp>::value && boost::is_nothrow_move_assignable<Cmp>::value)
{
#ifndef BOOST_MSVC
std::swap(static_cast<Cmp&>(*this), static_cast<Cmp&>(rhs));
@@ -463,7 +466,7 @@ struct heap_base<T, Cmp, constant_time_size, StabilityCounterType, true>:
friend struct heap_merge_emulate;
private:
- Cmp & value_comp_ref(void)
+ Cmp & value_comp_ref(void) BOOST_NOEXCEPT
{
#ifndef BOOST_MSVC
return *this;
diff --git a/boost/heap/detail/tree_iterator.hpp b/boost/heap/detail/tree_iterator.hpp
index 2bc05ea1ab..c7ab2e80b3 100644
--- a/boost/heap/detail/tree_iterator.hpp
+++ b/boost/heap/detail/tree_iterator.hpp
@@ -23,10 +23,10 @@ namespace detail {
template<typename type>
struct identity
{
- type& operator()(type& x) const
+ type& operator()(type& x) const BOOST_NOEXCEPT
{ return x; }
- const type& operator()(const type& x) const
+ const type& operator()(const type& x) const BOOST_NOEXCEPT
{ return x; }
};
@@ -127,7 +127,7 @@ struct ordered_tree_iterator_storage:
return data_.top();
}
- bool empty(void) const
+ bool empty(void) const BOOST_NOEXCEPT
{
return data_.empty();
}
diff --git a/boost/heap/priority_queue.hpp b/boost/heap/priority_queue.hpp
index 45f2151739..fe2470dc22 100644
--- a/boost/heap/priority_queue.hpp
+++ b/boost/heap/priority_queue.hpp
@@ -136,7 +136,7 @@ public:
*
* \b Note: Only available, if BOOST_NO_CXX11_RVALUE_REFERENCES is not defined
* */
- priority_queue(priority_queue && rhs):
+ priority_queue(priority_queue && rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<super_t>::value):
super_t(std::move(rhs)), q_(std::move(rhs.q_))
{}
@@ -147,7 +147,7 @@ public:
*
* \b Note: Only available, if BOOST_NO_CXX11_RVALUE_REFERENCES is not defined
* */
- priority_queue & operator=(priority_queue && rhs)
+ priority_queue & operator=(priority_queue && rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_assignable<super_t>::value)
{
super_t::operator=(std::move(rhs));
q_ = std::move(rhs.q_);
@@ -174,7 +174,7 @@ public:
* \b Complexity: Constant.
*
* */
- bool empty(void) const
+ bool empty(void) const BOOST_NOEXCEPT
{
return q_.empty();
}
@@ -185,7 +185,7 @@ public:
* \b Complexity: Constant.
*
* */
- size_type size(void) const
+ size_type size(void) const BOOST_NOEXCEPT
{
return q_.size();
}
@@ -196,7 +196,7 @@ public:
* \b Complexity: Constant.
*
* */
- size_type max_size(void) const
+ size_type max_size(void) const BOOST_NOEXCEPT
{
return q_.max_size();
}
@@ -207,7 +207,7 @@ public:
* \b Complexity: Linear.
*
* */
- void clear(void)
+ void clear(void) BOOST_NOEXCEPT
{
q_.clear();
}
@@ -281,7 +281,7 @@ public:
* \b Complexity: Constant.
*
* */
- void swap(priority_queue & rhs)
+ void swap(priority_queue & rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<super_t>::value && boost::is_nothrow_move_assignable<super_t>::value)
{
super_t::swap(rhs);
q_.swap(rhs.q_);
@@ -293,7 +293,7 @@ public:
* \b Complexity: Constant.
*
* */
- iterator begin(void) const
+ iterator begin(void) const BOOST_NOEXCEPT
{
return iterator(q_.begin());
}
@@ -304,7 +304,7 @@ public:
* \b Complexity: Constant.
*
* */
- iterator end(void) const
+ iterator end(void) const BOOST_NOEXCEPT
{
return iterator(q_.end());
}
diff --git a/boost/interprocess/detail/utilities.hpp b/boost/interprocess/detail/utilities.hpp
index 7ff3def65b..e1be2f1598 100644
--- a/boost/interprocess/detail/utilities.hpp
+++ b/boost/interprocess/detail/utilities.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012.
+// (C) Copyright Ion Gaztanaga 2005-2015.
// (C) Copyright Gennaro Prota 2003 - 2004.
//
// Distributed under the Boost Software License, Version 1.0.
@@ -123,8 +123,8 @@ struct is_intrusive_index
static const bool value = false;
};
-template <typename T> T*
-addressof(T& v)
+template <typename T>
+BOOST_INTERPROCESS_FORCEINLINE T* addressof(T& v)
{
return reinterpret_cast<T*>(
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
@@ -148,7 +148,7 @@ inline bool multiplication_overflows(SizeType a, SizeType b)
}
template<std::size_t SztSizeOfType, class SizeType>
-inline bool size_overflows(SizeType count)
+BOOST_INTERPROCESS_FORCEINLINE bool size_overflows(SizeType count)
{
//Compile time-check
BOOST_STATIC_ASSERT(SztSizeOfType <= SizeType(-1));
@@ -163,18 +163,18 @@ template<class T>
class pointer_uintptr_caster<T*>
{
public:
- BOOST_FORCEINLINE explicit pointer_uintptr_caster(uintptr_t sz)
+ BOOST_INTERPROCESS_FORCEINLINE explicit pointer_uintptr_caster(uintptr_t sz)
: m_uintptr(sz)
{}
- BOOST_FORCEINLINE explicit pointer_uintptr_caster(const volatile T *p)
+ BOOST_INTERPROCESS_FORCEINLINE explicit pointer_uintptr_caster(const volatile T *p)
: m_uintptr(reinterpret_cast<uintptr_t>(p))
{}
- BOOST_FORCEINLINE uintptr_t uintptr() const
+ BOOST_INTERPROCESS_FORCEINLINE uintptr_t uintptr() const
{ return m_uintptr; }
- BOOST_FORCEINLINE T* pointer() const
+ BOOST_INTERPROCESS_FORCEINLINE T* pointer() const
{ return reinterpret_cast<T*>(m_uintptr); }
private:
@@ -196,7 +196,7 @@ class value_eraser
~value_eraser()
{ if(m_erase) m_cont.erase(m_index_it); }
- void release() { m_erase = false; }
+ BOOST_INTERPROCESS_FORCEINLINE void release() { m_erase = false; }
private:
Cont &m_cont;
diff --git a/boost/interprocess/detail/win32_api.hpp b/boost/interprocess/detail/win32_api.hpp
index 0329b6dbe4..f1bfee66d5 100644
--- a/boost/interprocess/detail/win32_api.hpp
+++ b/boost/interprocess/detail/win32_api.hpp
@@ -35,11 +35,11 @@
#include <windows.h>
# if defined(BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME)
-# include <Wbemidl.h>
-# include <Objbase.h>
+# include <wbemidl.h>
+# include <objbase.h>
# endif
-#include <Shlobj.h>
+#include <shlobj.h>
#endif
#if defined(_MSC_VER)
diff --git a/boost/interprocess/detail/workaround.hpp b/boost/interprocess/detail/workaround.hpp
index d7e86f464d..5089696fb6 100644
--- a/boost/interprocess/detail/workaround.hpp
+++ b/boost/interprocess/detail/workaround.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -19,8 +19,6 @@
# pragma once
#endif
-#include <boost/interprocess/detail/config_begin.hpp>
-
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#define BOOST_INTERPROCESS_WINDOWS
#define BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION
@@ -191,6 +189,17 @@
#define BOOST_INTERPROCESS_I ,
#define BOOST_INTERPROCESS_DOCIGN(T1) T1
-#include <boost/interprocess/detail/config_end.hpp>
+//#define BOOST_INTERPROCESS_DISABLE_FORCEINLINE
+
+#if defined(BOOST_INTERPROCESS_DISABLE_FORCEINLINE)
+ #define BOOST_INTERPROCESS_FORCEINLINE inline
+#elif defined(BOOST_INTERPROCESS_FORCEINLINE_IS_BOOST_FORCELINE)
+ #define BOOST_INTERPROCESS_FORCEINLINE BOOST_FORCEINLINE
+#elif defined(BOOST_MSVC) && defined(_DEBUG)
+ //"__forceinline" and MSVC seems to have some bugs in debug mode
+ #define BOOST_INTERPROCESS_FORCEINLINE inline
+#else
+ #define BOOST_INTERPROCESS_FORCEINLINE BOOST_FORCEINLINE
+#endif
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP
diff --git a/boost/interprocess/offset_ptr.hpp b/boost/interprocess/offset_ptr.hpp
index 622b3cd6e3..d668fca6ba 100644
--- a/boost/interprocess/offset_ptr.hpp
+++ b/boost/interprocess/offset_ptr.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2014. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2005-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -79,7 +79,7 @@ namespace ipcdetail {
//
////////////////////////////////////////////////////////////////////////
#define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR
- BOOST_FORCEINLINE void * offset_ptr_to_raw_pointer(const volatile void *this_ptr, uintptr_t offset)
+ BOOST_INTERPROCESS_FORCEINLINE void * offset_ptr_to_raw_pointer(const volatile void *this_ptr, uintptr_t offset)
{
typedef pointer_uintptr_caster<void*> caster_t;
#ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR
@@ -104,7 +104,7 @@ namespace ipcdetail {
//
////////////////////////////////////////////////////////////////////////
#define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF
- BOOST_FORCEINLINE uintptr_t offset_ptr_to_offset(const volatile void *ptr, const volatile void *this_ptr)
+ BOOST_INTERPROCESS_FORCEINLINE uintptr_t offset_ptr_to_offset(const volatile void *ptr, const volatile void *this_ptr)
{
typedef pointer_uintptr_caster<void*> caster_t;
#ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF
@@ -137,7 +137,7 @@ namespace ipcdetail {
//
////////////////////////////////////////////////////////////////////////
#define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER
- BOOST_FORCEINLINE uintptr_t offset_ptr_to_offset_from_other
+ BOOST_INTERPROCESS_FORCEINLINE uintptr_t offset_ptr_to_offset_from_other
(const volatile void *this_ptr, const volatile void *other_ptr, uintptr_t other_offset)
{
typedef pointer_uintptr_caster<void*> caster_t;
@@ -242,20 +242,20 @@ class offset_ptr
//!Default constructor (null pointer).
//!Never throws.
- BOOST_FORCEINLINE offset_ptr() BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE offset_ptr() BOOST_NOEXCEPT
: internal(1)
{}
//!Constructor from raw pointer (allows "0" pointer conversion).
//!Never throws.
- BOOST_FORCEINLINE offset_ptr(pointer ptr) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE offset_ptr(pointer ptr) BOOST_NOEXCEPT
: internal(static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset(ptr, this)))
{}
//!Constructor from other pointer.
//!Never throws.
template <class T>
- BOOST_FORCEINLINE offset_ptr( T *ptr
+ BOOST_INTERPROCESS_FORCEINLINE offset_ptr( T *ptr
, typename ipcdetail::enable_if< ipcdetail::is_convertible<T*, PointedType*> >::type * = 0) BOOST_NOEXCEPT
: internal(static_cast<OffsetType>
(ipcdetail::offset_ptr_to_offset(static_cast<PointedType*>(ptr), this)))
@@ -263,7 +263,7 @@ class offset_ptr
//!Constructor from other offset_ptr
//!Never throws.
- BOOST_FORCEINLINE offset_ptr(const offset_ptr& ptr) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr& ptr) BOOST_NOEXCEPT
: internal(static_cast<OffsetType>
(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset)))
{}
@@ -271,7 +271,7 @@ class offset_ptr
//!Constructor from other offset_ptr. If pointers of pointee types are
//!convertible, offset_ptrs will be convertibles. Never throws.
template<class T2>
- BOOST_FORCEINLINE offset_ptr( const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr
+ BOOST_INTERPROCESS_FORCEINLINE offset_ptr( const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
, typename ipcdetail::enable_if_convertible_equal_address<T2, PointedType>::type* = 0
#endif
@@ -285,7 +285,7 @@ class offset_ptr
//!Constructor from other offset_ptr. If pointers of pointee types are
//!convertible, offset_ptrs will be convertibles. Never throws.
template<class T2>
- BOOST_FORCEINLINE offset_ptr( const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr
+ BOOST_INTERPROCESS_FORCEINLINE offset_ptr( const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr
, typename ipcdetail::enable_if_convertible_unequal_address<T2, PointedType>::type* = 0) BOOST_NOEXCEPT
: internal(static_cast<OffsetType>
(ipcdetail::offset_ptr_to_offset(static_cast<PointedType*>(ptr.get()), this)))
@@ -296,7 +296,7 @@ class offset_ptr
//!Emulates static_cast operator.
//!Never throws.
template<class T2, class P2, class O2, std::size_t A2>
- BOOST_FORCEINLINE offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::static_cast_tag) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::static_cast_tag) BOOST_NOEXCEPT
: internal(static_cast<OffsetType>
(ipcdetail::offset_ptr_to_offset(static_cast<PointedType*>(r.get()), this)))
{}
@@ -304,7 +304,7 @@ class offset_ptr
//!Emulates const_cast operator.
//!Never throws.
template<class T2, class P2, class O2, std::size_t A2>
- BOOST_FORCEINLINE offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::const_cast_tag) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::const_cast_tag) BOOST_NOEXCEPT
: internal(static_cast<OffsetType>
(ipcdetail::offset_ptr_to_offset(const_cast<PointedType*>(r.get()), this)))
{}
@@ -312,7 +312,7 @@ class offset_ptr
//!Emulates dynamic_cast operator.
//!Never throws.
template<class T2, class P2, class O2, std::size_t A2>
- BOOST_FORCEINLINE offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::dynamic_cast_tag) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::dynamic_cast_tag) BOOST_NOEXCEPT
: internal(static_cast<OffsetType>
(ipcdetail::offset_ptr_to_offset(dynamic_cast<PointedType*>(r.get()), this)))
{}
@@ -320,27 +320,27 @@ class offset_ptr
//!Emulates reinterpret_cast operator.
//!Never throws.
template<class T2, class P2, class O2, std::size_t A2>
- BOOST_FORCEINLINE offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::reinterpret_cast_tag) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::reinterpret_cast_tag) BOOST_NOEXCEPT
: internal(static_cast<OffsetType>
(ipcdetail::offset_ptr_to_offset(reinterpret_cast<PointedType*>(r.get()), this)))
{}
//!Obtains raw pointer from offset.
//!Never throws.
- BOOST_FORCEINLINE pointer get() const BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE pointer get() const BOOST_NOEXCEPT
{ return (pointer)ipcdetail::offset_ptr_to_raw_pointer(this, this->internal.m_offset); }
- BOOST_FORCEINLINE offset_type get_offset() const BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE offset_type get_offset() const BOOST_NOEXCEPT
{ return this->internal.m_offset; }
//!Pointer-like -> operator. It can return 0 pointer.
//!Never throws.
- BOOST_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT
{ return this->get(); }
//!Dereferencing operator, if it is a null offset_ptr behavior
//! is undefined. Never throws.
- BOOST_FORCEINLINE reference operator* () const BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE reference operator* () const BOOST_NOEXCEPT
{
pointer p = this->get();
reference r = *p;
@@ -349,12 +349,12 @@ class offset_ptr
//!Indexing operator.
//!Never throws.
- BOOST_FORCEINLINE reference operator[](difference_type idx) const BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE reference operator[](difference_type idx) const BOOST_NOEXCEPT
{ return this->get()[idx]; }
//!Assignment from pointer (saves extra conversion).
//!Never throws.
- BOOST_FORCEINLINE offset_ptr& operator= (pointer from) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator= (pointer from) BOOST_NOEXCEPT
{
this->internal.m_offset =
static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset(from, this));
@@ -363,7 +363,7 @@ class offset_ptr
//!Assignment from other offset_ptr.
//!Never throws.
- BOOST_FORCEINLINE offset_ptr& operator= (const offset_ptr & ptr) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator= (const offset_ptr & ptr) BOOST_NOEXCEPT
{
this->internal.m_offset =
static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset));
@@ -372,7 +372,7 @@ class offset_ptr
//!Assignment from related offset_ptr. If pointers of pointee types
//! are assignable, offset_ptrs will be assignable. Never throws.
- template<class T2> BOOST_FORCEINLINE
+ template<class T2> BOOST_INTERPROCESS_FORCEINLINE
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
typename ipcdetail::enable_if_c
< ipcdetail::is_convertible<T2*, PointedType*>::value, offset_ptr&>::type
@@ -389,22 +389,22 @@ class offset_ptr
//!offset_ptr += difference_type.
//!Never throws.
- BOOST_FORCEINLINE offset_ptr &operator+= (difference_type offset) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE offset_ptr &operator+= (difference_type offset) BOOST_NOEXCEPT
{ this->inc_offset(offset * sizeof (PointedType)); return *this; }
//!offset_ptr -= difference_type.
//!Never throws.
- BOOST_FORCEINLINE offset_ptr &operator-= (difference_type offset) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE offset_ptr &operator-= (difference_type offset) BOOST_NOEXCEPT
{ this->dec_offset(offset * sizeof (PointedType)); return *this; }
//!++offset_ptr.
//!Never throws.
- BOOST_FORCEINLINE offset_ptr& operator++ (void) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator++ (void) BOOST_NOEXCEPT
{ this->inc_offset(sizeof (PointedType)); return *this; }
//!offset_ptr++.
//!Never throws.
- BOOST_FORCEINLINE offset_ptr operator++ (int) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE offset_ptr operator++ (int) BOOST_NOEXCEPT
{
offset_ptr tmp(*this);
this->inc_offset(sizeof (PointedType));
@@ -413,12 +413,12 @@ class offset_ptr
//!--offset_ptr.
//!Never throws.
- BOOST_FORCEINLINE offset_ptr& operator-- (void) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator-- (void) BOOST_NOEXCEPT
{ this->dec_offset(sizeof (PointedType)); return *this; }
//!offset_ptr--.
//!Never throws.
- BOOST_FORCEINLINE offset_ptr operator-- (int) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE offset_ptr operator-- (int) BOOST_NOEXCEPT
{
offset_ptr tmp(*this);
this->dec_offset(sizeof (PointedType));
@@ -428,7 +428,7 @@ class offset_ptr
//!safe bool conversion operator.
//!Never throws.
#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
- BOOST_FORCEINLINE operator unspecified_bool_type() const BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE operator unspecified_bool_type() const BOOST_NOEXCEPT
{ return this->internal.m_offset != 1? &self_t::unspecified_bool_type_func : 0; }
#else
explicit operator bool() const BOOST_NOEXCEPT
@@ -437,7 +437,7 @@ class offset_ptr
//!Not operator. Not needed in theory, but improves portability.
//!Never throws
- BOOST_FORCEINLINE bool operator! () const BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE bool operator! () const BOOST_NOEXCEPT
{ return this->internal.m_offset == 1; }
//!Compatibility with pointer_traits
@@ -448,92 +448,92 @@ class offset_ptr
//!Compatibility with pointer_traits
//!
- BOOST_FORCEINLINE static offset_ptr pointer_to(reference r) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE static offset_ptr pointer_to(reference r) BOOST_NOEXCEPT
{ return offset_ptr(&r); }
//!difference_type + offset_ptr
//!operation
- BOOST_FORCEINLINE friend offset_ptr operator+(difference_type diff, offset_ptr right) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend offset_ptr operator+(difference_type diff, offset_ptr right) BOOST_NOEXCEPT
{ right += diff; return right; }
//!offset_ptr + difference_type
//!operation
- BOOST_FORCEINLINE friend offset_ptr operator+(offset_ptr left, difference_type diff) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend offset_ptr operator+(offset_ptr left, difference_type diff) BOOST_NOEXCEPT
{ left += diff; return left; }
//!offset_ptr - diff
//!operation
- BOOST_FORCEINLINE friend offset_ptr operator-(offset_ptr left, difference_type diff) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend offset_ptr operator-(offset_ptr left, difference_type diff) BOOST_NOEXCEPT
{ left -= diff; return left; }
//!offset_ptr - diff
//!operation
- BOOST_FORCEINLINE friend offset_ptr operator-(difference_type diff, offset_ptr right) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend offset_ptr operator-(difference_type diff, offset_ptr right) BOOST_NOEXCEPT
{ right -= diff; return right; }
//!offset_ptr - offset_ptr
//!operation
- BOOST_FORCEINLINE friend difference_type operator-(const offset_ptr &pt, const offset_ptr &pt2) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend difference_type operator-(const offset_ptr &pt, const offset_ptr &pt2) BOOST_NOEXCEPT
{ return difference_type(pt.get()- pt2.get()); }
//Comparison
- BOOST_FORCEINLINE friend bool operator== (const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend bool operator== (const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
{ return pt1.get() == pt2.get(); }
- BOOST_FORCEINLINE friend bool operator!= (const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend bool operator!= (const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
{ return pt1.get() != pt2.get(); }
- BOOST_FORCEINLINE friend bool operator<(const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend bool operator<(const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
{ return pt1.get() < pt2.get(); }
- BOOST_FORCEINLINE friend bool operator<=(const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend bool operator<=(const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
{ return pt1.get() <= pt2.get(); }
- BOOST_FORCEINLINE friend bool operator>(const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend bool operator>(const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
{ return pt1.get() > pt2.get(); }
- BOOST_FORCEINLINE friend bool operator>=(const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend bool operator>=(const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
{ return pt1.get() >= pt2.get(); }
//Comparison to raw ptr to support literal 0
- BOOST_FORCEINLINE friend bool operator== (pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend bool operator== (pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
{ return pt1 == pt2.get(); }
- BOOST_FORCEINLINE friend bool operator!= (pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend bool operator!= (pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
{ return pt1 != pt2.get(); }
- BOOST_FORCEINLINE friend bool operator<(pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend bool operator<(pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
{ return pt1 < pt2.get(); }
- BOOST_FORCEINLINE friend bool operator<=(pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend bool operator<=(pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
{ return pt1 <= pt2.get(); }
- BOOST_FORCEINLINE friend bool operator>(pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend bool operator>(pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
{ return pt1 > pt2.get(); }
- BOOST_FORCEINLINE friend bool operator>=(pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend bool operator>=(pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
{ return pt1 >= pt2.get(); }
//Comparison
- BOOST_FORCEINLINE friend bool operator== (const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend bool operator== (const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT
{ return pt1.get() == pt2; }
- BOOST_FORCEINLINE friend bool operator!= (const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend bool operator!= (const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT
{ return pt1.get() != pt2; }
- BOOST_FORCEINLINE friend bool operator<(const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend bool operator<(const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT
{ return pt1.get() < pt2; }
- BOOST_FORCEINLINE friend bool operator<=(const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend bool operator<=(const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT
{ return pt1.get() <= pt2; }
- BOOST_FORCEINLINE friend bool operator>(const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend bool operator>(const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT
{ return pt1.get() > pt2; }
- BOOST_FORCEINLINE friend bool operator>=(const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend bool operator>=(const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT
{ return pt1.get() >= pt2; }
- BOOST_FORCEINLINE friend void swap(offset_ptr &left, offset_ptr &right) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE friend void swap(offset_ptr &left, offset_ptr &right) BOOST_NOEXCEPT
{
pointer ptr = right.get();
right = left;
@@ -542,33 +542,33 @@ class offset_ptr
private:
template<class T2>
- BOOST_FORCEINLINE void assign(const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr, ipcdetail::bool_<true>) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE void assign(const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr, ipcdetail::bool_<true>) BOOST_NOEXCEPT
{ //no need to pointer adjustment
this->internal.m_offset =
static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.get_offset()));
}
template<class T2>
- BOOST_FORCEINLINE void assign(const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr, ipcdetail::bool_<false>) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE void assign(const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr, ipcdetail::bool_<false>) BOOST_NOEXCEPT
{ //we must convert to raw before calculating the offset
this->internal.m_offset =
static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset(static_cast<PointedType*>(ptr.get()), this));
}
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
- BOOST_FORCEINLINE void inc_offset(DifferenceType bytes) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE void inc_offset(DifferenceType bytes) BOOST_NOEXCEPT
{ internal.m_offset += bytes; }
- BOOST_FORCEINLINE void dec_offset(DifferenceType bytes) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE void dec_offset(DifferenceType bytes) BOOST_NOEXCEPT
{ internal.m_offset -= bytes; }
ipcdetail::offset_ptr_internal<OffsetType, OffsetAlignment> internal;
public:
- BOOST_FORCEINLINE const OffsetType &priv_offset() const BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE const OffsetType &priv_offset() const BOOST_NOEXCEPT
{ return internal.m_offset; }
- BOOST_FORCEINLINE OffsetType &priv_offset() BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE OffsetType &priv_offset() BOOST_NOEXCEPT
{ return internal.m_offset; }
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
@@ -590,7 +590,7 @@ inline std::basic_istream<E, T> & operator>>
//!Simulation of static_cast between pointers. Never throws.
template<class T1, class P1, class O1, std::size_t A1, class T2, class P2, class O2, std::size_t A2>
-BOOST_FORCEINLINE boost::interprocess::offset_ptr<T1, P1, O1, A1>
+BOOST_INTERPROCESS_FORCEINLINE boost::interprocess::offset_ptr<T1, P1, O1, A1>
static_pointer_cast(const boost::interprocess::offset_ptr<T2, P2, O2, A2> & r) BOOST_NOEXCEPT
{
return boost::interprocess::offset_ptr<T1, P1, O1, A1>
@@ -599,7 +599,7 @@ BOOST_FORCEINLINE boost::interprocess::offset_ptr<T1, P1, O1, A1>
//!Simulation of const_cast between pointers. Never throws.
template<class T1, class P1, class O1, std::size_t A1, class T2, class P2, class O2, std::size_t A2>
-BOOST_FORCEINLINE boost::interprocess::offset_ptr<T1, P1, O1, A1>
+BOOST_INTERPROCESS_FORCEINLINE boost::interprocess::offset_ptr<T1, P1, O1, A1>
const_pointer_cast(const boost::interprocess::offset_ptr<T2, P2, O2, A2> & r) BOOST_NOEXCEPT
{
return boost::interprocess::offset_ptr<T1, P1, O1, A1>
@@ -608,7 +608,7 @@ BOOST_FORCEINLINE boost::interprocess::offset_ptr<T1, P1, O1, A1>
//!Simulation of dynamic_cast between pointers. Never throws.
template<class T1, class P1, class O1, std::size_t A1, class T2, class P2, class O2, std::size_t A2>
-BOOST_FORCEINLINE boost::interprocess::offset_ptr<T1, P1, O1, A1>
+BOOST_INTERPROCESS_FORCEINLINE boost::interprocess::offset_ptr<T1, P1, O1, A1>
dynamic_pointer_cast(const boost::interprocess::offset_ptr<T2, P2, O2, A2> & r) BOOST_NOEXCEPT
{
return boost::interprocess::offset_ptr<T1, P1, O1, A1>
@@ -617,7 +617,7 @@ BOOST_FORCEINLINE boost::interprocess::offset_ptr<T1, P1, O1, A1>
//!Simulation of reinterpret_cast between pointers. Never throws.
template<class T1, class P1, class O1, std::size_t A1, class T2, class P2, class O2, std::size_t A2>
-BOOST_FORCEINLINE boost::interprocess::offset_ptr<T1, P1, O1, A1>
+BOOST_INTERPROCESS_FORCEINLINE boost::interprocess::offset_ptr<T1, P1, O1, A1>
reinterpret_pointer_cast(const boost::interprocess::offset_ptr<T2, P2, O2, A2> & r) BOOST_NOEXCEPT
{
return boost::interprocess::offset_ptr<T1, P1, O1, A1>
@@ -651,7 +651,7 @@ namespace interprocess {
//!to_raw_pointer() enables boost::mem_fn to recognize offset_ptr.
//!Never throws.
template <class T, class P, class O, std::size_t A>
-BOOST_FORCEINLINE T * to_raw_pointer(boost::interprocess::offset_ptr<T, P, O, A> const & p) BOOST_NOEXCEPT
+BOOST_INTERPROCESS_FORCEINLINE T * to_raw_pointer(boost::interprocess::offset_ptr<T, P, O, A> const & p) BOOST_NOEXCEPT
{ return ipcdetail::to_raw_pointer(p); }
} //namespace interprocess
@@ -696,7 +696,7 @@ struct pointer_plus_bits<boost::interprocess::offset_ptr<T, P, O, A>, NumBits>
//We must ALWAYS take argument "n" by reference as a copy of a null pointer
//with a bit (e.g. offset == 3) would be incorrectly copied and interpreted as non-null.
- BOOST_FORCEINLINE static pointer get_pointer(const pointer &n) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE static pointer get_pointer(const pointer &n) BOOST_NOEXCEPT
{
pointer p;
O const tmp_off = n.priv_offset() & O(~Mask);
@@ -704,7 +704,7 @@ struct pointer_plus_bits<boost::interprocess::offset_ptr<T, P, O, A>, NumBits>
return p;
}
- BOOST_FORCEINLINE static void set_pointer(pointer &n, const pointer &p) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE static void set_pointer(pointer &n, const pointer &p) BOOST_NOEXCEPT
{
BOOST_ASSERT(0 == (get_bits)(p));
O const stored_bits = O(n.priv_offset() & Mask);
@@ -712,12 +712,12 @@ struct pointer_plus_bits<boost::interprocess::offset_ptr<T, P, O, A>, NumBits>
n.priv_offset() |= stored_bits;
}
- BOOST_FORCEINLINE static std::size_t get_bits(const pointer &n) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE static std::size_t get_bits(const pointer &n) BOOST_NOEXCEPT
{
return std::size_t((n.priv_offset() & Mask) >> 1u);
}
- BOOST_FORCEINLINE static void set_bits(pointer &n, std::size_t const b) BOOST_NOEXCEPT
+ BOOST_INTERPROCESS_FORCEINLINE static void set_bits(pointer &n, std::size_t const b) BOOST_NOEXCEPT
{
BOOST_ASSERT(b < (std::size_t(1) << NumBits));
O tmp = n.priv_offset();
diff --git a/boost/intrusive/avl_set.hpp b/boost/intrusive/avl_set.hpp
index 5c51e5978d..2c962046e5 100644
--- a/boost/intrusive/avl_set.hpp
+++ b/boost/intrusive/avl_set.hpp
@@ -82,9 +82,13 @@ class avl_set_impl
public:
+ //! @copydoc ::boost::intrusive::avltree::avltree()
+ avl_set_impl()
+ : tree_type()
+ {}
+
//! @copydoc ::boost::intrusive::avltree::avltree(const key_compare &,const value_traits &)
- explicit avl_set_impl( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ explicit avl_set_impl( const key_compare &cmp, const value_traits &v_traits = value_traits())
: tree_type(cmp, v_traits)
{}
@@ -196,6 +200,17 @@ class avl_set_impl
iterator insert(const_iterator hint, reference value)
{ return tree_type::insert_unique(hint, value); }
+ //! @copydoc ::boost::intrusive::avltree::insert_unique_check(const key_type&,insert_commit_data&)
+ std::pair<iterator, bool> insert_check
+ (const key_type &key, insert_commit_data &commit_data)
+ { return tree_type::insert_unique_check(key, commit_data); }
+
+ //! @copydoc ::boost::intrusive::avltree::insert_unique_check(const_iterator,const key_type&,insert_commit_data&)
+ std::pair<iterator, bool> insert_check
+ (const_iterator hint, const key_type &key
+ ,insert_commit_data &commit_data)
+ { return tree_type::insert_unique_check(hint, key, commit_data); }
+
//! @copydoc ::boost::intrusive::avltree::insert_unique_check(const KeyType&,KeyTypeKeyCompare,insert_commit_data&)
template<class KeyType, class KeyTypeKeyCompare>
std::pair<iterator, bool> insert_check
@@ -321,21 +336,21 @@ class avl_set_impl
#endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
- //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &)
+ //! @copydoc ::boost::intrusive::avltree::equal_range(const key_type &)
std::pair<iterator,iterator> equal_range(const key_type &key)
{ return this->tree_type::lower_bound_range(key); }
- //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyTypeKeyCompare)
+ //! @copydoc ::boost::intrusive::avltree::equal_range(const KeyType&,KeyTypeKeyCompare)
template<class KeyType, class KeyTypeKeyCompare>
std::pair<iterator,iterator> equal_range(const KeyType& key, KeyTypeKeyCompare comp)
{ return this->tree_type::equal_range(key, comp); }
- //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &)const
+ //! @copydoc ::boost::intrusive::avltree::equal_range(const key_type &)const
std::pair<const_iterator, const_iterator>
equal_range(const key_type &key) const
{ return this->tree_type::lower_bound_range(key); }
- //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyTypeKeyCompare)const
+ //! @copydoc ::boost::intrusive::avltree::equal_range(const KeyType&,KeyTypeKeyCompare)const
template<class KeyType, class KeyTypeKeyCompare>
std::pair<const_iterator, const_iterator>
equal_range(const KeyType& key, KeyTypeKeyCompare comp) const
@@ -476,8 +491,11 @@ class avl_set
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
- explicit avl_set( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ avl_set()
+ : Base()
+ {}
+
+ explicit avl_set( const key_compare &cmp, const value_traits &v_traits = value_traits())
: Base(cmp, v_traits)
{}
@@ -573,9 +591,13 @@ class avl_multiset_impl
static const bool constant_time_size = tree_type::constant_time_size;
public:
+ //! @copydoc ::boost::intrusive::avltree::avltree()
+ avl_multiset_impl()
+ : tree_type()
+ {}
+
//! @copydoc ::boost::intrusive::avltree::avltree(const key_compare &,const value_traits &)
- explicit avl_multiset_impl( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ explicit avl_multiset_impl( const key_compare &cmp, const value_traits &v_traits = value_traits())
: tree_type(cmp, v_traits)
{}
@@ -936,8 +958,11 @@ class avl_multiset
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
- explicit avl_multiset( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ avl_multiset()
+ : Base()
+ {}
+
+ explicit avl_multiset( const key_compare &cmp, const value_traits &v_traits = value_traits())
: Base(cmp, v_traits)
{}
diff --git a/boost/intrusive/avltree.hpp b/boost/intrusive/avltree.hpp
index 8462293d6f..741d482827 100644
--- a/boost/intrusive/avltree.hpp
+++ b/boost/intrusive/avltree.hpp
@@ -121,10 +121,13 @@ class avltree_impl
typedef typename implementation_defined::insert_commit_data insert_commit_data;
+ //! @copydoc ::boost::intrusive::bstree::bstree()
+ avltree_impl()
+ : tree_type()
+ {}
//! @copydoc ::boost::intrusive::bstree::bstree(const key_compare &,const value_traits &)
- explicit avltree_impl( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ explicit avltree_impl( const key_compare &cmp, const value_traits &v_traits = value_traits())
: tree_type(cmp, v_traits)
{}
@@ -257,6 +260,14 @@ class avltree_impl
(const_iterator hint, const KeyType &key
,KeyTypeKeyCompare comp, insert_commit_data &commit_data);
+ //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const key_type&,insert_commit_data&)
+ std::pair<iterator, bool> insert_unique_check
+ (const key_type &key, insert_commit_data &commit_data);
+
+ //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const key_type&,insert_commit_data&)
+ std::pair<iterator, bool> insert_unique_check
+ (const_iterator hint, const key_type &key, insert_commit_data &commit_data);
+
//! @copydoc ::boost::intrusive::bstree::insert_unique_commit
iterator insert_unique_commit(reference value, const insert_commit_data &commit_data);
@@ -507,8 +518,11 @@ class avltree
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
- explicit avltree( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ avltree()
+ : Base()
+ {}
+
+ explicit avltree( const key_compare &cmp, const value_traits &v_traits = value_traits())
: Base(cmp, v_traits)
{}
diff --git a/boost/intrusive/bs_set.hpp b/boost/intrusive/bs_set.hpp
index 2f560f5863..60f18a16a9 100644
--- a/boost/intrusive/bs_set.hpp
+++ b/boost/intrusive/bs_set.hpp
@@ -80,9 +80,13 @@ class bs_set_impl
static const bool constant_time_size = tree_type::constant_time_size;
public:
+ //! @copydoc ::boost::intrusive::bstree::bstree()
+ bs_set_impl()
+ : tree_type()
+ {}
+
//! @copydoc ::boost::intrusive::bstree::bstree(const key_compare &,const value_traits &)
- explicit bs_set_impl( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ explicit bs_set_impl( const key_compare &cmp, const value_traits &v_traits = value_traits())
: tree_type(cmp, v_traits)
{}
@@ -193,6 +197,17 @@ class bs_set_impl
iterator insert(const_iterator hint, reference value)
{ return tree_type::insert_unique(hint, value); }
+ //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const key_type&,insert_commit_data&)
+ std::pair<iterator, bool> insert_check
+ (const key_type &key, insert_commit_data &commit_data)
+ { return tree_type::insert_unique_check(key, commit_data); }
+
+ //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const key_type&,insert_commit_data&)
+ std::pair<iterator, bool> insert_check
+ (const_iterator hint, const key_type &key
+ ,insert_commit_data &commit_data)
+ { return tree_type::insert_unique_check(hint, key, commit_data); }
+
//! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyTypeKeyCompare,insert_commit_data&)
template<class KeyType, class KeyTypeKeyCompare>
std::pair<iterator, bool> insert_check
@@ -473,8 +488,11 @@ class bs_set
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
- explicit bs_set( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ bs_set()
+ : Base()
+ {}
+
+ explicit bs_set( const key_compare &cmp, const value_traits &v_traits = value_traits())
: Base(cmp, v_traits)
{}
@@ -569,9 +587,13 @@ class bs_multiset_impl
static const bool constant_time_size = tree_type::constant_time_size;
public:
+ //! @copydoc ::boost::intrusive::bstree::bstree()
+ bs_multiset_impl()
+ : tree_type()
+ {}
+
//! @copydoc ::boost::intrusive::bstree::bstree(const key_compare &,const value_traits &)
- explicit bs_multiset_impl( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ explicit bs_multiset_impl( const key_compare &cmp, const value_traits &v_traits = value_traits())
: tree_type(cmp, v_traits)
{}
@@ -932,8 +954,11 @@ class bs_multiset
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
- explicit bs_multiset( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ bs_multiset()
+ : Base()
+ {}
+
+ explicit bs_multiset( const key_compare &cmp, const value_traits &v_traits = value_traits())
: Base(cmp, v_traits)
{}
diff --git a/boost/intrusive/bstree.hpp b/boost/intrusive/bstree.hpp
index b08c49b5f1..0fb921887d 100644
--- a/boost/intrusive/bstree.hpp
+++ b/boost/intrusive/bstree.hpp
@@ -476,8 +476,20 @@ struct bstbase2
}
//insert_unique_check
- template<class KeyType, class KeyTypeKeyCompare>
std::pair<iterator, bool> insert_unique_check
+ (const key_type &key, insert_commit_data &commit_data)
+ { return this->insert_unique_check(key, this->key_comp(), commit_data); }
+
+ std::pair<iterator, bool> insert_unique_check
+ (const_iterator hint, const key_type &key, insert_commit_data &commit_data)
+ { return this->insert_unique_check(hint, key, this->key_comp(), commit_data); }
+
+ template<class KeyType, class KeyTypeKeyCompare>
+ BOOST_INTRUSIVE_DOC1ST(std::pair<iterator BOOST_INTRUSIVE_I bool>
+ , typename detail::disable_if_convertible
+ <KeyType BOOST_INTRUSIVE_I const_iterator BOOST_INTRUSIVE_I
+ std::pair<iterator BOOST_INTRUSIVE_I bool> >::type)
+ insert_unique_check
(const KeyType &key, KeyTypeKeyCompare comp, insert_commit_data &commit_data)
{
std::pair<node_ptr, bool> ret =
@@ -488,8 +500,7 @@ struct bstbase2
template<class KeyType, class KeyTypeKeyCompare>
std::pair<iterator, bool> insert_unique_check
- (const_iterator hint, const KeyType &key
- ,KeyTypeKeyCompare comp, insert_commit_data &commit_data)
+ (const_iterator hint, const KeyType &key, KeyTypeKeyCompare comp, insert_commit_data &commit_data)
{
std::pair<node_ptr, bool> ret =
(node_algorithms::insert_unique_check
@@ -679,8 +690,18 @@ class bstree_impl
//! <b>Throws</b>: If value_traits::node_traits::node
//! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
//! or the copy constructor of the key_compare object throws. Basic guarantee.
- explicit bstree_impl( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ bstree_impl()
+ : data_type(key_compare(), value_traits())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container with given comparison and traits.
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Throws</b>: If value_traits::node_traits::node
+ //! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
+ //! or the copy constructor of the key_compare object throws. Basic guarantee.
+ explicit bstree_impl( const key_compare &cmp, const value_traits &v_traits = value_traits())
: data_type(cmp, v_traits)
{}
@@ -2052,8 +2073,11 @@ class bstree
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
- bstree( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ bstree()
+ : Base()
+ {}
+
+ explicit bstree( const key_compare &cmp, const value_traits &v_traits = value_traits())
: Base(cmp, v_traits)
{}
diff --git a/boost/intrusive/detail/any_node_and_algorithms.hpp b/boost/intrusive/detail/any_node_and_algorithms.hpp
index 3c76e58528..4b087b582b 100644
--- a/boost/intrusive/detail/any_node_and_algorithms.hpp
+++ b/boost/intrusive/detail/any_node_and_algorithms.hpp
@@ -21,6 +21,7 @@
# pragma once
#endif
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/pointer_rebind.hpp>
#include <cstddef>
#include <boost/intrusive/detail/mpl.hpp>
@@ -47,16 +48,16 @@ struct any_list_node_traits
typedef typename node::node_ptr node_ptr;
typedef typename node::const_node_ptr const_node_ptr;
- static node_ptr get_next(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_next(const const_node_ptr & n)
{ return n->node_ptr_1; }
- static void set_next(const node_ptr & n, const node_ptr & next)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_next(const node_ptr & n, const node_ptr & next)
{ n->node_ptr_1 = next; }
- static node_ptr get_previous(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_previous(const const_node_ptr & n)
{ return n->node_ptr_2; }
- static void set_previous(const node_ptr & n, const node_ptr & prev)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_previous(const node_ptr & n, const node_ptr & prev)
{ n->node_ptr_2 = prev; }
};
@@ -68,10 +69,10 @@ struct any_slist_node_traits
typedef typename node::node_ptr node_ptr;
typedef typename node::const_node_ptr const_node_ptr;
- static node_ptr get_next(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_next(const const_node_ptr & n)
{ return n->node_ptr_1; }
- static void set_next(const node_ptr & n, const node_ptr & next)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_next(const node_ptr & n, const node_ptr & next)
{ n->node_ptr_1 = next; }
};
@@ -88,22 +89,22 @@ struct any_unordered_node_traits
static const bool store_hash = true;
static const bool optimize_multikey = true;
- static node_ptr get_next(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_next(const const_node_ptr & n)
{ return n->node_ptr_1; }
- static void set_next(const node_ptr & n, const node_ptr & next)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_next(const node_ptr & n, const node_ptr & next)
{ n->node_ptr_1 = next; }
- static node_ptr get_prev_in_group(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_prev_in_group(const const_node_ptr & n)
{ return n->node_ptr_2; }
- static void set_prev_in_group(const node_ptr & n, const node_ptr & prev)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_prev_in_group(const node_ptr & n, const node_ptr & prev)
{ n->node_ptr_2 = prev; }
- static std::size_t get_hash(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static std::size_t get_hash(const const_node_ptr & n)
{ return n->size_t_1; }
- static void set_hash(const node_ptr & n, std::size_t h)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_hash(const node_ptr & n, std::size_t h)
{ n->size_t_1 = h; }
};
@@ -117,34 +118,34 @@ struct any_rbtree_node_traits
typedef std::size_t color;
- static node_ptr get_parent(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_parent(const const_node_ptr & n)
{ return n->node_ptr_1; }
- static void set_parent(const node_ptr & n, const node_ptr & p)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_parent(const node_ptr & n, const node_ptr & p)
{ n->node_ptr_1 = p; }
- static node_ptr get_left(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_left(const const_node_ptr & n)
{ return n->node_ptr_2; }
- static void set_left(const node_ptr & n, const node_ptr & l)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_left(const node_ptr & n, const node_ptr & l)
{ n->node_ptr_2 = l; }
- static node_ptr get_right(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_right(const const_node_ptr & n)
{ return n->node_ptr_3; }
- static void set_right(const node_ptr & n, const node_ptr & r)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_right(const node_ptr & n, const node_ptr & r)
{ n->node_ptr_3 = r; }
- static color get_color(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static color get_color(const const_node_ptr & n)
{ return n->size_t_1; }
- static void set_color(const node_ptr & n, color c)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_color(const node_ptr & n, color c)
{ n->size_t_1 = c; }
- static color black()
+ BOOST_INTRUSIVE_FORCEINLINE static color black()
{ return 0u; }
- static color red()
+ BOOST_INTRUSIVE_FORCEINLINE static color red()
{ return 1u; }
};
@@ -158,37 +159,37 @@ struct any_avltree_node_traits
typedef std::size_t balance;
- static node_ptr get_parent(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_parent(const const_node_ptr & n)
{ return n->node_ptr_1; }
- static void set_parent(const node_ptr & n, const node_ptr & p)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_parent(const node_ptr & n, const node_ptr & p)
{ n->node_ptr_1 = p; }
- static node_ptr get_left(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_left(const const_node_ptr & n)
{ return n->node_ptr_2; }
- static void set_left(const node_ptr & n, const node_ptr & l)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_left(const node_ptr & n, const node_ptr & l)
{ n->node_ptr_2 = l; }
- static node_ptr get_right(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_right(const const_node_ptr & n)
{ return n->node_ptr_3; }
- static void set_right(const node_ptr & n, const node_ptr & r)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_right(const node_ptr & n, const node_ptr & r)
{ n->node_ptr_3 = r; }
- static balance get_balance(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static balance get_balance(const const_node_ptr & n)
{ return n->size_t_1; }
- static void set_balance(const node_ptr & n, balance b)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_balance(const node_ptr & n, balance b)
{ n->size_t_1 = b; }
- static balance negative()
+ BOOST_INTRUSIVE_FORCEINLINE static balance negative()
{ return 0u; }
- static balance zero()
+ BOOST_INTRUSIVE_FORCEINLINE static balance zero()
{ return 1u; }
- static balance positive()
+ BOOST_INTRUSIVE_FORCEINLINE static balance positive()
{ return 2u; }
};
@@ -200,22 +201,22 @@ struct any_tree_node_traits
typedef typename node::node_ptr node_ptr;
typedef typename node::const_node_ptr const_node_ptr;
- static node_ptr get_parent(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_parent(const const_node_ptr & n)
{ return n->node_ptr_1; }
- static void set_parent(const node_ptr & n, const node_ptr & p)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_parent(const node_ptr & n, const node_ptr & p)
{ n->node_ptr_1 = p; }
- static node_ptr get_left(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_left(const const_node_ptr & n)
{ return n->node_ptr_2; }
- static void set_left(const node_ptr & n, const node_ptr & l)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_left(const node_ptr & n, const node_ptr & l)
{ n->node_ptr_2 = l; }
- static node_ptr get_right(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_right(const const_node_ptr & n)
{ return n->node_ptr_3; }
- static void set_right(const node_ptr & n, const node_ptr & r)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_right(const node_ptr & n, const node_ptr & r)
{ n->node_ptr_3 = r; }
};
@@ -250,19 +251,19 @@ class any_algorithms
//! <b>Throws</b>: Nothing.
//!
//! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
- static void init(const node_ptr & node)
- { node->node_ptr_1 = 0; };
+ BOOST_INTRUSIVE_FORCEINLINE static void init(const node_ptr & node)
+ { node->node_ptr_1 = node_ptr(); };
//! <b>Effects</b>: Returns true if node is in the same state as if called init(node)
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Throws</b>: Nothing.
- static bool inited(const const_node_ptr & node)
+ BOOST_INTRUSIVE_FORCEINLINE static bool inited(const const_node_ptr & node)
{ return !node->node_ptr_1; };
- static bool unique(const const_node_ptr & node)
- { return 0 == node->node_ptr_1; }
+ BOOST_INTRUSIVE_FORCEINLINE static bool unique(const const_node_ptr & node)
+ { return !node->node_ptr_1; }
static void unlink(const node_ptr &)
{
diff --git a/boost/intrusive/detail/avltree_node.hpp b/boost/intrusive/detail/avltree_node.hpp
index 22b8fd1219..16d1c1d291 100644
--- a/boost/intrusive/detail/avltree_node.hpp
+++ b/boost/intrusive/detail/avltree_node.hpp
@@ -22,6 +22,7 @@
#endif
#include <boost/intrusive/detail/config_begin.hpp>
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/pointer_rebind.hpp>
#include <boost/intrusive/avltree_algorithms.hpp>
#include <boost/intrusive/pointer_plus_bits.hpp>
@@ -68,49 +69,49 @@ struct default_avltree_node_traits_impl
typedef typename node::balance balance;
- static node_ptr get_parent(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_parent(const const_node_ptr & n)
{ return n->parent_; }
- static node_ptr get_parent(const node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_parent(const node_ptr & n)
{ return n->parent_; }
- static void set_parent(const node_ptr & n, const node_ptr & p)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_parent(const node_ptr & n, const node_ptr & p)
{ n->parent_ = p; }
- static node_ptr get_left(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_left(const const_node_ptr & n)
{ return n->left_; }
- static node_ptr get_left(const node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_left(const node_ptr & n)
{ return n->left_; }
- static void set_left(const node_ptr & n, const node_ptr & l)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_left(const node_ptr & n, const node_ptr & l)
{ n->left_ = l; }
- static node_ptr get_right(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_right(const const_node_ptr & n)
{ return n->right_; }
- static node_ptr get_right(const node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_right(const node_ptr & n)
{ return n->right_; }
- static void set_right(const node_ptr & n, const node_ptr & r)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_right(const node_ptr & n, const node_ptr & r)
{ n->right_ = r; }
- static balance get_balance(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static balance get_balance(const const_node_ptr & n)
{ return n->balance_; }
- static balance get_balance(const node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static balance get_balance(const node_ptr & n)
{ return n->balance_; }
- static void set_balance(const node_ptr & n, balance b)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_balance(const node_ptr & n, balance b)
{ n->balance_ = b; }
- static balance negative()
+ BOOST_INTRUSIVE_FORCEINLINE static balance negative()
{ return node::negative_t; }
- static balance zero()
+ BOOST_INTRUSIVE_FORCEINLINE static balance zero()
{ return node::zero_t; }
- static balance positive()
+ BOOST_INTRUSIVE_FORCEINLINE static balance positive()
{ return node::positive_t; }
};
@@ -126,37 +127,37 @@ struct compact_avltree_node_traits_impl
typedef pointer_plus_bits<node_ptr, 2> ptr_bit;
- static node_ptr get_parent(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_parent(const const_node_ptr & n)
{ return ptr_bit::get_pointer(n->parent_); }
- static void set_parent(const node_ptr & n, const node_ptr & p)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_parent(const node_ptr & n, const node_ptr & p)
{ ptr_bit::set_pointer(n->parent_, p); }
- static node_ptr get_left(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_left(const const_node_ptr & n)
{ return n->left_; }
- static void set_left(const node_ptr & n, const node_ptr & l)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_left(const node_ptr & n, const node_ptr & l)
{ n->left_ = l; }
- static node_ptr get_right(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_right(const const_node_ptr & n)
{ return n->right_; }
- static void set_right(const node_ptr & n, const node_ptr & r)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_right(const node_ptr & n, const node_ptr & r)
{ n->right_ = r; }
- static balance get_balance(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static balance get_balance(const const_node_ptr & n)
{ return (balance)ptr_bit::get_bits(n->parent_); }
- static void set_balance(const node_ptr & n, balance b)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_balance(const node_ptr & n, balance b)
{ ptr_bit::set_bits(n->parent_, (std::size_t)b); }
- static balance negative()
+ BOOST_INTRUSIVE_FORCEINLINE static balance negative()
{ return node::negative_t; }
- static balance zero()
+ BOOST_INTRUSIVE_FORCEINLINE static balance zero()
{ return node::zero_t; }
- static balance positive()
+ BOOST_INTRUSIVE_FORCEINLINE static balance positive()
{ return node::positive_t; }
};
diff --git a/boost/intrusive/detail/bstree_algorithms_base.hpp b/boost/intrusive/detail/bstree_algorithms_base.hpp
index ed28a430ea..8404010565 100644
--- a/boost/intrusive/detail/bstree_algorithms_base.hpp
+++ b/boost/intrusive/detail/bstree_algorithms_base.hpp
@@ -69,8 +69,8 @@ class bstree_algorithms_base
static node_ptr prev_node(const node_ptr & node)
{
if(is_header(node)){
- return NodeTraits::get_right(node);
- //return maximum(NodeTraits::get_parent(node));
+ //return NodeTraits::get_right(node);
+ return maximum(NodeTraits::get_parent(node));
}
else if(NodeTraits::get_left(node)){
return maximum(NodeTraits::get_left(node));
diff --git a/boost/intrusive/detail/config_begin.hpp b/boost/intrusive/detail/config_begin.hpp
index 36d605d072..cef8616812 100644
--- a/boost/intrusive/detail/config_begin.hpp
+++ b/boost/intrusive/detail/config_begin.hpp
@@ -38,13 +38,18 @@
#pragma warning (disable : 4284) // odd return type for operator->
#pragma warning (disable : 4244) // possible loss of data
#pragma warning (disable : 4521) ////Disable "multiple copy constructors specified"
- #pragma warning (disable : 4522)
+ #pragma warning (disable : 4127) //conditional expression is constant
#pragma warning (disable : 4146)
#pragma warning (disable : 4267) //conversion from 'X' to 'Y', possible loss of data
- #pragma warning (disable : 4127) //conditional expression is constant
- #pragma warning (disable : 4706) //assignment within conditional expression
#pragma warning (disable : 4541) //'typeid' used on polymorphic type 'boost::exception' with /GR-
#pragma warning (disable : 4512) //'typeid' used on polymorphic type 'boost::exception' with /GR-
+ #pragma warning (disable : 4522)
+ #pragma warning (disable : 4706) //assignment within conditional expression
+ #pragma warning (disable : 4710) // function not inlined
+ #pragma warning (disable : 4714) // "function": marked as __forceinline not inlined
+ #pragma warning (disable : 4711) // function selected for automatic inline expansion
+ #pragma warning (disable : 4786) // identifier truncated in debug info
+ #pragma warning (disable : 4996) // "function": was declared deprecated
#endif
//#define BOOST_INTRUSIVE_USE_ITERATOR_FACADE
diff --git a/boost/intrusive/detail/default_header_holder.hpp b/boost/intrusive/detail/default_header_holder.hpp
index 5f9cd9a444..288f8a0e41 100644
--- a/boost/intrusive/detail/default_header_holder.hpp
+++ b/boost/intrusive/detail/default_header_holder.hpp
@@ -21,6 +21,7 @@
# pragma once
#endif
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/detail/to_raw_pointer.hpp>
@@ -39,14 +40,14 @@ struct default_header_holder : public NodeTraits::node
default_header_holder() : node() {}
- const_node_ptr get_node() const
+ BOOST_INTRUSIVE_FORCEINLINE const_node_ptr get_node() const
{ return pointer_traits< const_node_ptr >::pointer_to(*static_cast< const node* >(this)); }
- node_ptr get_node()
+ BOOST_INTRUSIVE_FORCEINLINE node_ptr get_node()
{ return pointer_traits< node_ptr >::pointer_to(*static_cast< node* >(this)); }
// (unsafe) downcast used to implement container-from-iterator
- static default_header_holder* get_holder(const node_ptr &p)
+ BOOST_INTRUSIVE_FORCEINLINE static default_header_holder* get_holder(const node_ptr &p)
{ return static_cast< default_header_holder* >(boost::intrusive::detail::to_raw_pointer(p)); }
};
diff --git a/boost/intrusive/detail/ebo_functor_holder.hpp b/boost/intrusive/detail/ebo_functor_holder.hpp
index 9fec5a32b7..ef278ed805 100644
--- a/boost/intrusive/detail/ebo_functor_holder.hpp
+++ b/boost/intrusive/detail/ebo_functor_holder.hpp
@@ -22,6 +22,7 @@
# pragma once
#endif
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/move/utility_core.hpp>
namespace boost {
@@ -165,57 +166,57 @@ class ebo_functor_holder
public:
typedef T functor_type;
- ebo_functor_holder()
+ BOOST_INTRUSIVE_FORCEINLINE ebo_functor_holder()
: t_()
{}
- explicit ebo_functor_holder(const T &t)
+ BOOST_INTRUSIVE_FORCEINLINE explicit ebo_functor_holder(const T &t)
: t_(t)
{}
- explicit ebo_functor_holder(BOOST_RV_REF(T) t)
+ BOOST_INTRUSIVE_FORCEINLINE explicit ebo_functor_holder(BOOST_RV_REF(T) t)
: t_(::boost::move(t))
{}
template<class Arg1, class Arg2>
- ebo_functor_holder(BOOST_FWD_REF(Arg1) arg1, BOOST_FWD_REF(Arg2) arg2)
+ BOOST_INTRUSIVE_FORCEINLINE ebo_functor_holder(BOOST_FWD_REF(Arg1) arg1, BOOST_FWD_REF(Arg2) arg2)
: t_(::boost::forward<Arg1>(arg1), ::boost::forward<Arg2>(arg2))
{}
- ebo_functor_holder(const ebo_functor_holder &x)
- : t_(x)
+ BOOST_INTRUSIVE_FORCEINLINE ebo_functor_holder(const ebo_functor_holder &x)
+ : t_(x.t_)
{}
- ebo_functor_holder(BOOST_RV_REF(ebo_functor_holder) x)
+ BOOST_INTRUSIVE_FORCEINLINE ebo_functor_holder(BOOST_RV_REF(ebo_functor_holder) x)
: t_(x.t_)
{}
- ebo_functor_holder& operator=(BOOST_COPY_ASSIGN_REF(ebo_functor_holder) x)
+ BOOST_INTRUSIVE_FORCEINLINE ebo_functor_holder& operator=(BOOST_COPY_ASSIGN_REF(ebo_functor_holder) x)
{
this->get() = x.get();
return *this;
}
- ebo_functor_holder& operator=(BOOST_RV_REF(ebo_functor_holder) x)
+ BOOST_INTRUSIVE_FORCEINLINE ebo_functor_holder& operator=(BOOST_RV_REF(ebo_functor_holder) x)
{
this->get() = ::boost::move(x.get());
return *this;
}
- ebo_functor_holder& operator=(const T &x)
+ BOOST_INTRUSIVE_FORCEINLINE ebo_functor_holder& operator=(const T &x)
{
this->get() = x;
return *this;
}
- ebo_functor_holder& operator=(BOOST_RV_REF(T) x)
+ BOOST_INTRUSIVE_FORCEINLINE ebo_functor_holder& operator=(BOOST_RV_REF(T) x)
{
this->get() = ::boost::move(x);
return *this;
}
- T& get(){return t_;}
- const T& get()const{return t_;}
+ BOOST_INTRUSIVE_FORCEINLINE T& get(){return t_;}
+ BOOST_INTRUSIVE_FORCEINLINE const T& get()const{return t_;}
private:
T t_;
@@ -230,58 +231,58 @@ class ebo_functor_holder<T, false>
public:
typedef T functor_type;
- ebo_functor_holder()
+ BOOST_INTRUSIVE_FORCEINLINE ebo_functor_holder()
: T()
{}
- explicit ebo_functor_holder(const T &t)
+ BOOST_INTRUSIVE_FORCEINLINE explicit ebo_functor_holder(const T &t)
: T(t)
{}
- explicit ebo_functor_holder(BOOST_RV_REF(T) t)
+ BOOST_INTRUSIVE_FORCEINLINE explicit ebo_functor_holder(BOOST_RV_REF(T) t)
: T(::boost::move(t))
{}
template<class Arg1, class Arg2>
- ebo_functor_holder(BOOST_FWD_REF(Arg1) arg1, BOOST_FWD_REF(Arg2) arg2)
+ BOOST_INTRUSIVE_FORCEINLINE ebo_functor_holder(BOOST_FWD_REF(Arg1) arg1, BOOST_FWD_REF(Arg2) arg2)
: T(::boost::forward<Arg1>(arg1), ::boost::forward<Arg2>(arg2))
{}
- ebo_functor_holder(const ebo_functor_holder &x)
+ BOOST_INTRUSIVE_FORCEINLINE ebo_functor_holder(const ebo_functor_holder &x)
: T(static_cast<const T&>(x))
{}
- ebo_functor_holder(BOOST_RV_REF(ebo_functor_holder) x)
+ BOOST_INTRUSIVE_FORCEINLINE ebo_functor_holder(BOOST_RV_REF(ebo_functor_holder) x)
: T(BOOST_MOVE_BASE(T, x))
{}
- ebo_functor_holder& operator=(BOOST_COPY_ASSIGN_REF(ebo_functor_holder) x)
+ BOOST_INTRUSIVE_FORCEINLINE ebo_functor_holder& operator=(BOOST_COPY_ASSIGN_REF(ebo_functor_holder) x)
{
const ebo_functor_holder&r = x;
this->get() = x.get();
return *this;
}
- ebo_functor_holder& operator=(BOOST_RV_REF(ebo_functor_holder) x)
+ BOOST_INTRUSIVE_FORCEINLINE ebo_functor_holder& operator=(BOOST_RV_REF(ebo_functor_holder) x)
{
this->get() = ::boost::move(x.get());
return *this;
}
- ebo_functor_holder& operator=(const T &x)
+ BOOST_INTRUSIVE_FORCEINLINE ebo_functor_holder& operator=(const T &x)
{
this->get() = x;
return *this;
}
- ebo_functor_holder& operator=(BOOST_RV_REF(T) x)
+ BOOST_INTRUSIVE_FORCEINLINE ebo_functor_holder& operator=(BOOST_RV_REF(T) x)
{
this->get() = ::boost::move(x);
return *this;
}
- T& get(){return *this;}
- const T& get()const{return *this;}
+ BOOST_INTRUSIVE_FORCEINLINE T& get(){return *this;}
+ BOOST_INTRUSIVE_FORCEINLINE const T& get()const{return *this;}
};
} //namespace detail {
diff --git a/boost/intrusive/detail/equal_to_value.hpp b/boost/intrusive/detail/equal_to_value.hpp
index c341f488e9..c5d9e5305c 100644
--- a/boost/intrusive/detail/equal_to_value.hpp
+++ b/boost/intrusive/detail/equal_to_value.hpp
@@ -21,6 +21,8 @@
# pragma once
#endif
+#include <boost/intrusive/detail/workaround.hpp>
+
namespace boost {
namespace intrusive {
namespace detail {
@@ -37,7 +39,7 @@ class equal_to_value
: t_(t)
{}
- bool operator()(ConstReference t)const
+ BOOST_INTRUSIVE_FORCEINLINE bool operator()(ConstReference t)const
{ return t_ == t; }
};
diff --git a/boost/intrusive/detail/exception_disposer.hpp b/boost/intrusive/detail/exception_disposer.hpp
index a10d63a75d..91c5bf3b67 100644
--- a/boost/intrusive/detail/exception_disposer.hpp
+++ b/boost/intrusive/detail/exception_disposer.hpp
@@ -21,6 +21,8 @@
# pragma once
#endif
+#include <boost/intrusive/detail/workaround.hpp>
+
namespace boost {
namespace intrusive {
namespace detail {
@@ -39,7 +41,7 @@ class exception_disposer
: cont_(&cont), disp_(disp)
{}
- void release()
+ BOOST_INTRUSIVE_FORCEINLINE void release()
{ cont_ = 0; }
~exception_disposer()
@@ -67,7 +69,7 @@ class exception_array_disposer
: cont_(&cont), disp_(disp), constructed_(constructed)
{}
- void release()
+ BOOST_INTRUSIVE_FORCEINLINE void release()
{ cont_ = 0; }
~exception_array_disposer()
diff --git a/boost/intrusive/detail/has_member_function_callable_with.hpp b/boost/intrusive/detail/has_member_function_callable_with.hpp
index c9a8e7e637..2e73305d17 100644
--- a/boost/intrusive/detail/has_member_function_callable_with.hpp
+++ b/boost/intrusive/detail/has_member_function_callable_with.hpp
@@ -164,13 +164,14 @@ BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG
{
struct BaseMixin
{
- void BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME();
+ void BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME()
+ {} //Some compilers require the definition or linker errors happen
};
struct Base
: public boost_intrusive_hmfcw::remove_cv<Type>::type, public BaseMixin
{ //Declare the unneeded default constructor as some old compilers wrongly require it with is_convertible
- Base();
+ Base(){}
};
template <typename T, T t> class Helper{};
diff --git a/boost/intrusive/detail/hashtable_node.hpp b/boost/intrusive/detail/hashtable_node.hpp
index 352be28cbe..0471ebe684 100644
--- a/boost/intrusive/detail/hashtable_node.hpp
+++ b/boost/intrusive/detail/hashtable_node.hpp
@@ -21,6 +21,7 @@
# pragma once
#endif
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/detail/assert.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/detail/mpl.hpp>
@@ -99,10 +100,10 @@ struct bucket_traits_impl
buckets_ = x.buckets_; buckets_len_ = x.buckets_len_; return *this;
}
- const bucket_ptr &bucket_begin() const
+ BOOST_INTRUSIVE_FORCEINLINE const bucket_ptr &bucket_begin() const
{ return buckets_; }
- size_type bucket_count() const
+ BOOST_INTRUSIVE_FORCEINLINE size_type bucket_count() const
{ return buckets_len_; }
private:
@@ -160,11 +161,11 @@ class hashtable_iterator
typedef iiterator< value_traits, IsConst
, std::forward_iterator_tag> types_t;
public:
- typedef typename types_t::iterator_traits::difference_type difference_type;
- typedef typename types_t::iterator_traits::value_type value_type;
- typedef typename types_t::iterator_traits::pointer pointer;
- typedef typename types_t::iterator_traits::reference reference;
- typedef typename types_t::iterator_traits::iterator_category iterator_category;
+ typedef typename types_t::iterator_type::difference_type difference_type;
+ typedef typename types_t::iterator_type::value_type value_type;
+ typedef typename types_t::iterator_type::pointer pointer;
+ typedef typename types_t::iterator_type::reference reference;
+ typedef typename types_t::iterator_type::iterator_category iterator_category;
private:
typedef typename value_traits::node_traits node_traits;
@@ -189,7 +190,7 @@ class hashtable_iterator
public:
- hashtable_iterator ()
+ BOOST_INTRUSIVE_FORCEINLINE hashtable_iterator ()
: slist_it_() //Value initialization to achieve "null iterators" (N3644)
{}
@@ -202,7 +203,7 @@ class hashtable_iterator
: slist_it_(other.slist_it()), traitsptr_(other.get_bucket_value_traits())
{}
- const siterator &slist_it() const
+ BOOST_INTRUSIVE_FORCEINLINE const siterator &slist_it() const
{ return slist_it_; }
hashtable_iterator<BucketValueTraits, false> unconst() const
@@ -218,28 +219,28 @@ class hashtable_iterator
return result;
}
- friend bool operator== (const hashtable_iterator& i, const hashtable_iterator& i2)
+ BOOST_INTRUSIVE_FORCEINLINE friend bool operator== (const hashtable_iterator& i, const hashtable_iterator& i2)
{ return i.slist_it_ == i2.slist_it_; }
- friend bool operator!= (const hashtable_iterator& i, const hashtable_iterator& i2)
+ BOOST_INTRUSIVE_FORCEINLINE friend bool operator!= (const hashtable_iterator& i, const hashtable_iterator& i2)
{ return !(i == i2); }
- reference operator*() const
+ BOOST_INTRUSIVE_FORCEINLINE reference operator*() const
{ return *this->operator ->(); }
- pointer operator->() const
+ BOOST_INTRUSIVE_FORCEINLINE pointer operator->() const
{
return this->priv_value_traits().to_value_ptr
(downcast_bucket(slist_it_.pointed_node()));
}
- const const_bucketvaltraits_ptr &get_bucket_value_traits() const
+ BOOST_INTRUSIVE_FORCEINLINE const const_bucketvaltraits_ptr &get_bucket_value_traits() const
{ return traitsptr_; }
- const value_traits &priv_value_traits() const
+ BOOST_INTRUSIVE_FORCEINLINE const value_traits &priv_value_traits() const
{ return traitsptr_->priv_value_traits(); }
- const bucket_traits &priv_bucket_traits() const
+ BOOST_INTRUSIVE_FORCEINLINE const bucket_traits &priv_bucket_traits() const
{ return traitsptr_->priv_bucket_traits(); }
private:
diff --git a/boost/intrusive/detail/hook_traits.hpp b/boost/intrusive/detail/hook_traits.hpp
index 71f342af06..2a16061a54 100644
--- a/boost/intrusive/detail/hook_traits.hpp
+++ b/boost/intrusive/detail/hook_traits.hpp
@@ -21,6 +21,7 @@
# pragma once
#endif
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/detail/parent_from_member.hpp>
#include <boost/intrusive/link_mode.hpp>
@@ -54,25 +55,25 @@ struct bhtraits_base
typedef node& node_reference;
typedef const node & const_node_reference;
- static pointer to_value_ptr(const node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static pointer to_value_ptr(const node_ptr & n)
{
return pointer_traits<pointer>::pointer_to
(static_cast<reference>(static_cast<node_holder_reference>(*n)));
}
- static const_pointer to_value_ptr(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static const_pointer to_value_ptr(const const_node_ptr & n)
{
return pointer_traits<const_pointer>::pointer_to
(static_cast<const_reference>(static_cast<const_node_holder_reference>(*n)));
}
- static node_ptr to_node_ptr(reference value)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr to_node_ptr(reference value)
{
return pointer_traits<node_ptr>::pointer_to
(static_cast<node_reference>(static_cast<node_holder_reference>(value)));
}
- static const_node_ptr to_node_ptr(const_reference value)
+ BOOST_INTRUSIVE_FORCEINLINE static const_node_ptr to_node_ptr(const_reference value)
{
return pointer_traits<const_node_ptr>::pointer_to
(static_cast<const_node_reference>(static_cast<const_node_holder_reference>(value)));
@@ -111,26 +112,26 @@ struct mhtraits
static const link_mode_type link_mode = Hook::hooktags::link_mode;
- static node_ptr to_node_ptr(reference value)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr to_node_ptr(reference value)
{
return pointer_traits<node_ptr>::pointer_to
(static_cast<node_reference>(static_cast<hook_reference>(value.*P)));
}
- static const_node_ptr to_node_ptr(const_reference value)
+ BOOST_INTRUSIVE_FORCEINLINE static const_node_ptr to_node_ptr(const_reference value)
{
return pointer_traits<const_node_ptr>::pointer_to
(static_cast<const_node_reference>(static_cast<const_hook_reference>(value.*P)));
}
- static pointer to_value_ptr(const node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static pointer to_value_ptr(const node_ptr & n)
{
return pointer_traits<pointer>::pointer_to
(*detail::parent_from_member<T, Hook>
(static_cast<Hook*>(boost::intrusive::detail::to_raw_pointer(n)), P));
}
- static const_pointer to_value_ptr(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static const_pointer to_value_ptr(const const_node_ptr & n)
{
return pointer_traits<const_pointer>::pointer_to
(*detail::parent_from_member<T, Hook>
diff --git a/boost/intrusive/detail/iiterator.hpp b/boost/intrusive/detail/iiterator.hpp
index 5c6721bd0e..5ab1de2bb1 100644
--- a/boost/intrusive/detail/iiterator.hpp
+++ b/boost/intrusive/detail/iiterator.hpp
@@ -21,6 +21,7 @@
# pragma once
#endif
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/detail/iterator.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/detail/mpl.hpp>
@@ -70,7 +71,7 @@ struct iiterator
, difference_type
, pointer
, reference
- > iterator_traits;
+ > iterator_type;
typedef typename value_traits_pointers
<ValueTraits>::value_traits_ptr value_traits_ptr;
typedef typename value_traits_pointers
@@ -83,15 +84,15 @@ template<class NodePtr, class StoredPointer, bool StatefulValueTraits = true>
struct iiterator_members
{
- iiterator_members()
+ BOOST_INTRUSIVE_FORCEINLINE iiterator_members()
: nodeptr_()//Value initialization to achieve "null iterators" (N3644)
{}
- iiterator_members(const NodePtr &n_ptr, const StoredPointer &data)
+ BOOST_INTRUSIVE_FORCEINLINE iiterator_members(const NodePtr &n_ptr, const StoredPointer &data)
: nodeptr_(n_ptr), ptr_(data)
{}
- StoredPointer get_ptr() const
+ BOOST_INTRUSIVE_FORCEINLINE StoredPointer get_ptr() const
{ return ptr_; }
NodePtr nodeptr_;
@@ -101,15 +102,15 @@ struct iiterator_members
template<class NodePtr, class StoredPointer>
struct iiterator_members<NodePtr, StoredPointer, false>
{
- iiterator_members()
+ BOOST_INTRUSIVE_FORCEINLINE iiterator_members()
: nodeptr_()//Value initialization to achieve "null iterators" (N3644)
{}
- iiterator_members(const NodePtr &n_ptr, const StoredPointer &)
+ BOOST_INTRUSIVE_FORCEINLINE iiterator_members(const NodePtr &n_ptr, const StoredPointer &)
: nodeptr_(n_ptr)
{}
- StoredPointer get_ptr() const
+ BOOST_INTRUSIVE_FORCEINLINE StoredPointer get_ptr() const
{ return StoredPointer(); }
NodePtr nodeptr_;
diff --git a/boost/intrusive/detail/iterator.hpp b/boost/intrusive/detail/iterator.hpp
index 9f0fe606f4..2ae6abb7d0 100644
--- a/boost/intrusive/detail/iterator.hpp
+++ b/boost/intrusive/detail/iterator.hpp
@@ -23,6 +23,7 @@
#include <cstddef>
#include <boost/intrusive/detail/std_fwd.hpp>
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/move/detail/iterator_traits.hpp>
#include <boost/move/detail/meta_utils_core.hpp>
@@ -34,14 +35,14 @@ using boost::movelib::iterator_traits;
////////////////////
// iterator
////////////////////
-template<class Category, class T, class Distance, class Pointer = T*, class Reference = T&>
+template<class Category, class T, class Difference, class Pointer, class Reference>
struct iterator
{
- typedef Category iterator_category;
- typedef T value_type;
- typedef Distance difference_type;
- typedef Pointer pointer;
- typedef Reference reference;
+ typedef Category iterator_category;
+ typedef T value_type;
+ typedef Difference difference_type;
+ typedef Pointer pointer;
+ typedef Reference reference;
};
////////////////////////////////////////
@@ -83,7 +84,7 @@ struct iterator_disable_if_tag_difference_type
////////////////////
// advance
////////////////////
-template<class InputIt, class Distance> inline
+template<class InputIt, class Distance>
typename iterator_enable_if_tag<InputIt, std::input_iterator_tag>::type
iterator_advance(InputIt& it, Distance n)
{
@@ -91,7 +92,7 @@ typename iterator_enable_if_tag<InputIt, std::input_iterator_tag>::type
++it;
}
-template<class InputIt, class Distance> inline
+template<class InputIt, class Distance>
typename iterator_enable_if_tag<InputIt, std::forward_iterator_tag>::type
iterator_advance(InputIt& it, Distance n)
{
@@ -99,7 +100,7 @@ typename iterator_enable_if_tag<InputIt, std::forward_iterator_tag>::type
++it;
}
-template<class InputIt, class Distance> inline
+template<class InputIt, class Distance>
typename iterator_enable_if_tag<InputIt, std::bidirectional_iterator_tag>::type
iterator_advance(InputIt& it, Distance n)
{
@@ -109,8 +110,8 @@ typename iterator_enable_if_tag<InputIt, std::bidirectional_iterator_tag>::type
--it;
}
-template<class InputIt, class Distance> inline
-typename iterator_enable_if_tag<InputIt, std::random_access_iterator_tag>::type
+template<class InputIt, class Distance>
+BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_tag<InputIt, std::random_access_iterator_tag>::type
iterator_advance(InputIt& it, Distance n)
{
it += n;
@@ -132,8 +133,8 @@ typename iterator_disable_if_tag_difference_type
return off;
}
-template<class InputIt> inline
-typename iterator_enable_if_tag_difference_type
+template<class InputIt>
+BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_tag_difference_type
<InputIt, std::random_access_iterator_tag>::type
iterator_distance(InputIt first, InputIt last)
{
@@ -142,11 +143,11 @@ typename iterator_enable_if_tag_difference_type
}
template<class I>
-typename iterator_traits<I>::pointer iterator_arrow_result(const I &i)
+BOOST_INTRUSIVE_FORCEINLINE typename iterator_traits<I>::pointer iterator_arrow_result(const I &i)
{ return i.operator->(); }
template<class T>
-T * iterator_arrow_result(T *p)
+BOOST_INTRUSIVE_FORCEINLINE T * iterator_arrow_result(T *p)
{ return p; }
} //namespace intrusive
diff --git a/boost/intrusive/detail/list_iterator.hpp b/boost/intrusive/detail/list_iterator.hpp
index 6af4841c3e..6c5f161675 100644
--- a/boost/intrusive/detail/list_iterator.hpp
+++ b/boost/intrusive/detail/list_iterator.hpp
@@ -22,6 +22,7 @@
# pragma once
#endif
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/detail/std_fwd.hpp>
#include <boost/intrusive/detail/iiterator.hpp>
#include <boost/intrusive/detail/mpl.hpp>
@@ -48,80 +49,80 @@ class list_iterator
typedef typename types_t::const_value_traits_ptr const_value_traits_ptr;
public:
- typedef typename types_t::iterator_traits::difference_type difference_type;
- typedef typename types_t::iterator_traits::value_type value_type;
- typedef typename types_t::iterator_traits::pointer pointer;
- typedef typename types_t::iterator_traits::reference reference;
- typedef typename types_t::iterator_traits::iterator_category iterator_category;
+ typedef typename types_t::iterator_type::difference_type difference_type;
+ typedef typename types_t::iterator_type::value_type value_type;
+ typedef typename types_t::iterator_type::pointer pointer;
+ typedef typename types_t::iterator_type::reference reference;
+ typedef typename types_t::iterator_type::iterator_category iterator_category;
- list_iterator()
+ BOOST_INTRUSIVE_FORCEINLINE list_iterator()
{}
- explicit list_iterator(const node_ptr & nodeptr, const const_value_traits_ptr &traits_ptr)
+ BOOST_INTRUSIVE_FORCEINLINE explicit list_iterator(const node_ptr & nodeptr, const const_value_traits_ptr &traits_ptr)
: members_(nodeptr, traits_ptr)
{}
- list_iterator(list_iterator<ValueTraits, false> const& other)
+ BOOST_INTRUSIVE_FORCEINLINE list_iterator(list_iterator<ValueTraits, false> const& other)
: members_(other.pointed_node(), other.get_value_traits())
{}
- const node_ptr &pointed_node() const
+ BOOST_INTRUSIVE_FORCEINLINE const node_ptr &pointed_node() const
{ return members_.nodeptr_; }
- list_iterator &operator=(const node_ptr &node)
+ BOOST_INTRUSIVE_FORCEINLINE list_iterator &operator=(const node_ptr &node)
{ members_.nodeptr_ = node; return static_cast<list_iterator&>(*this); }
- const_value_traits_ptr get_value_traits() const
+ BOOST_INTRUSIVE_FORCEINLINE const_value_traits_ptr get_value_traits() const
{ return members_.get_ptr(); }
public:
- list_iterator& operator++()
+ BOOST_INTRUSIVE_FORCEINLINE list_iterator& operator++()
{
node_ptr p = node_traits::get_next(members_.nodeptr_);
members_.nodeptr_ = p;
return static_cast<list_iterator&> (*this);
}
- list_iterator operator++(int)
+ BOOST_INTRUSIVE_FORCEINLINE list_iterator operator++(int)
{
list_iterator result (*this);
members_.nodeptr_ = node_traits::get_next(members_.nodeptr_);
return result;
}
- list_iterator& operator--()
+ BOOST_INTRUSIVE_FORCEINLINE list_iterator& operator--()
{
members_.nodeptr_ = node_traits::get_previous(members_.nodeptr_);
return static_cast<list_iterator&> (*this);
}
- list_iterator operator--(int)
+ BOOST_INTRUSIVE_FORCEINLINE list_iterator operator--(int)
{
list_iterator result (*this);
members_.nodeptr_ = node_traits::get_previous(members_.nodeptr_);
return result;
}
- friend bool operator== (const list_iterator& l, const list_iterator& r)
+ BOOST_INTRUSIVE_FORCEINLINE friend bool operator== (const list_iterator& l, const list_iterator& r)
{ return l.pointed_node() == r.pointed_node(); }
- friend bool operator!= (const list_iterator& l, const list_iterator& r)
+ BOOST_INTRUSIVE_FORCEINLINE friend bool operator!= (const list_iterator& l, const list_iterator& r)
{ return !(l == r); }
- reference operator*() const
+ BOOST_INTRUSIVE_FORCEINLINE reference operator*() const
{ return *operator->(); }
- pointer operator->() const
+ BOOST_INTRUSIVE_FORCEINLINE pointer operator->() const
{ return this->operator_arrow(detail::bool_<stateful_value_traits>()); }
list_iterator<ValueTraits, false> unconst() const
{ return list_iterator<ValueTraits, false>(this->pointed_node(), this->get_value_traits()); }
private:
- pointer operator_arrow(detail::false_) const
+ BOOST_INTRUSIVE_FORCEINLINE pointer operator_arrow(detail::false_) const
{ return ValueTraits::to_value_ptr(members_.nodeptr_); }
- pointer operator_arrow(detail::true_) const
+ BOOST_INTRUSIVE_FORCEINLINE pointer operator_arrow(detail::true_) const
{ return this->get_value_traits()->to_value_ptr(members_.nodeptr_); }
iiterator_members<node_ptr, const_value_traits_ptr, stateful_value_traits> members_;
diff --git a/boost/intrusive/detail/list_node.hpp b/boost/intrusive/detail/list_node.hpp
index f740e545e8..c3b4847011 100644
--- a/boost/intrusive/detail/list_node.hpp
+++ b/boost/intrusive/detail/list_node.hpp
@@ -22,6 +22,7 @@
# pragma once
#endif
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/pointer_rebind.hpp>
namespace boost {
@@ -46,22 +47,22 @@ struct list_node_traits
typedef typename node::node_ptr node_ptr;
typedef typename pointer_rebind<VoidPointer, const node>::type const_node_ptr;
- static node_ptr get_previous(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_previous(const const_node_ptr & n)
{ return n->prev_; }
- static node_ptr get_previous(const node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_previous(const node_ptr & n)
{ return n->prev_; }
- static void set_previous(const node_ptr & n, const node_ptr & prev)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_previous(const node_ptr & n, const node_ptr & prev)
{ n->prev_ = prev; }
- static node_ptr get_next(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_next(const const_node_ptr & n)
{ return n->next_; }
- static node_ptr get_next(const node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_next(const node_ptr & n)
{ return n->next_; }
- static void set_next(const node_ptr & n, const node_ptr & next)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_next(const node_ptr & n, const node_ptr & next)
{ n->next_ = next; }
};
diff --git a/boost/intrusive/detail/parent_from_member.hpp b/boost/intrusive/detail/parent_from_member.hpp
index 8701c3f269..275229ab47 100644
--- a/boost/intrusive/detail/parent_from_member.hpp
+++ b/boost/intrusive/detail/parent_from_member.hpp
@@ -21,9 +21,10 @@
#endif
#include <boost/intrusive/detail/config_begin.hpp>
+#include <boost/intrusive/detail/workaround.hpp>
#include <cstddef>
-#if defined(BOOST_MSVC) || ((defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && defined(BOOST_INTEL))
+#if defined(_MSC_VER)
#define BOOST_INTRUSIVE_MSVC_ABI_PTR_TO_MEMBER
#include <boost/static_assert.hpp>
#endif
@@ -33,7 +34,7 @@ namespace intrusive {
namespace detail {
template<class Parent, class Member>
-inline std::ptrdiff_t offset_from_pointer_to_member(const Member Parent::* ptr_to_member)
+BOOST_INTRUSIVE_FORCEINLINE std::ptrdiff_t offset_from_pointer_to_member(const Member Parent::* ptr_to_member)
{
//The implementation of a pointer to member is compiler dependent.
#if defined(BOOST_INTRUSIVE_MSVC_ABI_PTR_TO_MEMBER)
@@ -88,7 +89,7 @@ inline std::ptrdiff_t offset_from_pointer_to_member(const Member Parent::* ptr_t
}
template<class Parent, class Member>
-inline Parent *parent_from_member(Member *member, const Member Parent::* ptr_to_member)
+BOOST_INTRUSIVE_FORCEINLINE Parent *parent_from_member(Member *member, const Member Parent::* ptr_to_member)
{
return static_cast<Parent*>
(
@@ -100,7 +101,7 @@ inline Parent *parent_from_member(Member *member, const Member Parent::* ptr_to_
}
template<class Parent, class Member>
-inline const Parent *parent_from_member(const Member *member, const Member Parent::* ptr_to_member)
+BOOST_INTRUSIVE_FORCEINLINE const Parent *parent_from_member(const Member *member, const Member Parent::* ptr_to_member)
{
return static_cast<const Parent*>
(
diff --git a/boost/intrusive/detail/rbtree_node.hpp b/boost/intrusive/detail/rbtree_node.hpp
index c4364399d8..68f4bdf8e2 100644
--- a/boost/intrusive/detail/rbtree_node.hpp
+++ b/boost/intrusive/detail/rbtree_node.hpp
@@ -23,6 +23,7 @@
#endif
#include <boost/intrusive/detail/config_begin.hpp>
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/pointer_rebind.hpp>
#include <boost/intrusive/rbtree_algorithms.hpp>
#include <boost/intrusive/pointer_plus_bits.hpp>
@@ -73,46 +74,46 @@ struct default_rbtree_node_traits_impl
typedef typename node::color color;
- static node_ptr get_parent(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_parent(const const_node_ptr & n)
{ return n->parent_; }
- static node_ptr get_parent(const node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_parent(const node_ptr & n)
{ return n->parent_; }
- static void set_parent(const node_ptr & n, const node_ptr & p)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_parent(const node_ptr & n, const node_ptr & p)
{ n->parent_ = p; }
- static node_ptr get_left(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_left(const const_node_ptr & n)
{ return n->left_; }
- static node_ptr get_left(const node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_left(const node_ptr & n)
{ return n->left_; }
- static void set_left(const node_ptr & n, const node_ptr & l)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_left(const node_ptr & n, const node_ptr & l)
{ n->left_ = l; }
- static node_ptr get_right(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_right(const const_node_ptr & n)
{ return n->right_; }
- static node_ptr get_right(const node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_right(const node_ptr & n)
{ return n->right_; }
- static void set_right(const node_ptr & n, const node_ptr & r)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_right(const node_ptr & n, const node_ptr & r)
{ n->right_ = r; }
- static color get_color(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static color get_color(const const_node_ptr & n)
{ return n->color_; }
- static color get_color(const node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static color get_color(const node_ptr & n)
{ return n->color_; }
- static void set_color(const node_ptr & n, color c)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_color(const node_ptr & n, color c)
{ n->color_ = c; }
- static color black()
+ BOOST_INTRUSIVE_FORCEINLINE static color black()
{ return node::black_t; }
- static color red()
+ BOOST_INTRUSIVE_FORCEINLINE static color red()
{ return node::red_t; }
};
@@ -129,46 +130,46 @@ struct compact_rbtree_node_traits_impl
typedef typename node::color color;
- static node_ptr get_parent(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_parent(const const_node_ptr & n)
{ return ptr_bit::get_pointer(n->parent_); }
- static node_ptr get_parent(const node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_parent(const node_ptr & n)
{ return ptr_bit::get_pointer(n->parent_); }
- static void set_parent(const node_ptr & n, const node_ptr & p)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_parent(const node_ptr & n, const node_ptr & p)
{ ptr_bit::set_pointer(n->parent_, p); }
- static node_ptr get_left(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_left(const const_node_ptr & n)
{ return n->left_; }
- static node_ptr get_left(const node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_left(const node_ptr & n)
{ return n->left_; }
- static void set_left(const node_ptr & n, const node_ptr & l)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_left(const node_ptr & n, const node_ptr & l)
{ n->left_ = l; }
- static node_ptr get_right(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_right(const const_node_ptr & n)
{ return n->right_; }
- static node_ptr get_right(const node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_right(const node_ptr & n)
{ return n->right_; }
- static void set_right(const node_ptr & n, const node_ptr & r)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_right(const node_ptr & n, const node_ptr & r)
{ n->right_ = r; }
- static color get_color(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static color get_color(const const_node_ptr & n)
{ return (color)ptr_bit::get_bits(n->parent_); }
- static color get_color(const node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static color get_color(const node_ptr & n)
{ return (color)ptr_bit::get_bits(n->parent_); }
- static void set_color(const node_ptr & n, color c)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_color(const node_ptr & n, color c)
{ ptr_bit::set_bits(n->parent_, c != 0); }
- static color black()
+ BOOST_INTRUSIVE_FORCEINLINE static color black()
{ return node::black_t; }
- static color red()
+ BOOST_INTRUSIVE_FORCEINLINE static color red()
{ return node::red_t; }
};
diff --git a/boost/intrusive/detail/reverse_iterator.hpp b/boost/intrusive/detail/reverse_iterator.hpp
index 552e8f4d71..57631feb5d 100644
--- a/boost/intrusive/detail/reverse_iterator.hpp
+++ b/boost/intrusive/detail/reverse_iterator.hpp
@@ -43,12 +43,16 @@ class reverse_iterator
reverse_iterator()
: m_current() //Value initialization to achieve "null iterators" (N3644)
- {}
+ {}
explicit reverse_iterator(It r)
: m_current(r)
{}
+ reverse_iterator(const reverse_iterator& r)
+ : m_current(r.base())
+ {}
+
template<class OtherIt>
reverse_iterator( const reverse_iterator<OtherIt>& r
, typename boost::intrusive::detail::enable_if_convertible<OtherIt, It>::type* =0
@@ -56,6 +60,9 @@ class reverse_iterator
: m_current(r.base())
{}
+ reverse_iterator & operator=( const reverse_iterator& r)
+ { m_current = r.base(); return *this; }
+
template<class OtherIt>
typename boost::intrusive::detail::enable_if_convertible<OtherIt, It, reverse_iterator &>::type
operator=( const reverse_iterator<OtherIt>& r)
@@ -65,20 +72,34 @@ class reverse_iterator
{ return m_current; }
reference operator*() const
- { It temp(m_current); --temp; return *temp; }
+ {
+ It temp(m_current);
+ --temp;
+ reference r = *temp;
+ return r;
+ }
pointer operator->() const
- { It temp(m_current); --temp; return iterator_arrow_result(temp); }
+ {
+ It temp(m_current);
+ --temp;
+ return iterator_arrow_result(temp);
+ }
reference operator[](difference_type off) const
- { return this->m_current[-off - 1]; }
+ {
+ return this->m_current[-off - 1];
+ }
reverse_iterator& operator++()
- { --m_current; return *this; }
+ {
+ --m_current;
+ return *this;
+ }
reverse_iterator operator++(int)
{
- reverse_iterator temp = *this;
+ reverse_iterator temp((*this));
--m_current;
return temp;
}
@@ -91,7 +112,7 @@ class reverse_iterator
reverse_iterator operator--(int)
{
- reverse_iterator temp(*this);
+ reverse_iterator temp((*this));
++m_current;
return temp;
}
@@ -117,17 +138,17 @@ class reverse_iterator
reverse_iterator& operator+=(difference_type off)
{ m_current -= off; return *this; }
+ reverse_iterator& operator-=(difference_type off)
+ { m_current += off; return *this; }
+
friend reverse_iterator operator+(reverse_iterator l, difference_type off)
- { l.m_current -= off; return l; }
+ { return (l += off); }
friend reverse_iterator operator+(difference_type off, reverse_iterator r)
{ return (r += off); }
- reverse_iterator& operator-=(difference_type off)
- { m_current += off; return *this; }
-
friend reverse_iterator operator-(reverse_iterator l, difference_type off)
- { l.m_current += off; return l; }
+ { return (l-= off); }
friend difference_type operator-(const reverse_iterator& l, const reverse_iterator& r)
{ return r.m_current - l.m_current; }
diff --git a/boost/intrusive/detail/size_holder.hpp b/boost/intrusive/detail/size_holder.hpp
index de1933ed50..9802ac32f1 100644
--- a/boost/intrusive/detail/size_holder.hpp
+++ b/boost/intrusive/detail/size_holder.hpp
@@ -21,6 +21,8 @@
# pragma once
#endif
+#include <boost/intrusive/detail/workaround.hpp>
+
namespace boost {
namespace intrusive {
namespace detail {
@@ -31,22 +33,22 @@ struct size_holder
static const bool constant_time_size = ConstantSize;
typedef SizeType size_type;
- SizeType get_size() const
+ BOOST_INTRUSIVE_FORCEINLINE SizeType get_size() const
{ return size_; }
- void set_size(SizeType size)
+ BOOST_INTRUSIVE_FORCEINLINE void set_size(SizeType size)
{ size_ = size; }
- void decrement()
+ BOOST_INTRUSIVE_FORCEINLINE void decrement()
{ --size_; }
- void increment()
+ BOOST_INTRUSIVE_FORCEINLINE void increment()
{ ++size_; }
- void increase(SizeType n)
+ BOOST_INTRUSIVE_FORCEINLINE void increase(SizeType n)
{ size_ += n; }
- void decrease(SizeType n)
+ BOOST_INTRUSIVE_FORCEINLINE void decrease(SizeType n)
{ size_ -= n; }
SizeType size_;
@@ -58,22 +60,22 @@ struct size_holder<false, SizeType, Tag>
static const bool constant_time_size = false;
typedef SizeType size_type;
- size_type get_size() const
+ BOOST_INTRUSIVE_FORCEINLINE size_type get_size() const
{ return 0; }
- void set_size(size_type)
+ BOOST_INTRUSIVE_FORCEINLINE void set_size(size_type)
{}
- void decrement()
+ BOOST_INTRUSIVE_FORCEINLINE void decrement()
{}
- void increment()
+ BOOST_INTRUSIVE_FORCEINLINE void increment()
{}
- void increase(SizeType)
+ BOOST_INTRUSIVE_FORCEINLINE void increase(SizeType)
{}
- void decrease(SizeType)
+ BOOST_INTRUSIVE_FORCEINLINE void decrease(SizeType)
{}
};
diff --git a/boost/intrusive/detail/slist_iterator.hpp b/boost/intrusive/detail/slist_iterator.hpp
index 1699064ec1..63ce5c3fef 100644
--- a/boost/intrusive/detail/slist_iterator.hpp
+++ b/boost/intrusive/detail/slist_iterator.hpp
@@ -23,6 +23,7 @@
#endif
#include <boost/intrusive/detail/config_begin.hpp>
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/detail/std_fwd.hpp>
#include <boost/intrusive/detail/iiterator.hpp>
#include <boost/intrusive/detail/mpl.hpp>
@@ -50,67 +51,67 @@ class slist_iterator
typedef typename types_t::const_value_traits_ptr const_value_traits_ptr;
public:
- typedef typename types_t::iterator_traits::difference_type difference_type;
- typedef typename types_t::iterator_traits::value_type value_type;
- typedef typename types_t::iterator_traits::pointer pointer;
- typedef typename types_t::iterator_traits::reference reference;
- typedef typename types_t::iterator_traits::iterator_category iterator_category;
+ typedef typename types_t::iterator_type::difference_type difference_type;
+ typedef typename types_t::iterator_type::value_type value_type;
+ typedef typename types_t::iterator_type::pointer pointer;
+ typedef typename types_t::iterator_type::reference reference;
+ typedef typename types_t::iterator_type::iterator_category iterator_category;
- slist_iterator()
+ BOOST_INTRUSIVE_FORCEINLINE slist_iterator()
{}
- explicit slist_iterator(const node_ptr & nodeptr, const const_value_traits_ptr &traits_ptr)
+ BOOST_INTRUSIVE_FORCEINLINE explicit slist_iterator(const node_ptr & nodeptr, const const_value_traits_ptr &traits_ptr)
: members_(nodeptr, traits_ptr)
{}
- slist_iterator(slist_iterator<ValueTraits, false> const& other)
+ BOOST_INTRUSIVE_FORCEINLINE slist_iterator(slist_iterator<ValueTraits, false> const& other)
: members_(other.pointed_node(), other.get_value_traits())
{}
- const node_ptr &pointed_node() const
+ BOOST_INTRUSIVE_FORCEINLINE const node_ptr &pointed_node() const
{ return members_.nodeptr_; }
- slist_iterator &operator=(const node_ptr &node)
+ BOOST_INTRUSIVE_FORCEINLINE slist_iterator &operator=(const node_ptr &node)
{ members_.nodeptr_ = node; return static_cast<slist_iterator&>(*this); }
- const_value_traits_ptr get_value_traits() const
+ BOOST_INTRUSIVE_FORCEINLINE const_value_traits_ptr get_value_traits() const
{ return members_.get_ptr(); }
public:
- slist_iterator& operator++()
+ BOOST_INTRUSIVE_FORCEINLINE slist_iterator& operator++()
{
members_.nodeptr_ = node_traits::get_next(members_.nodeptr_);
return static_cast<slist_iterator&> (*this);
}
- slist_iterator operator++(int)
+ BOOST_INTRUSIVE_FORCEINLINE slist_iterator operator++(int)
{
slist_iterator result (*this);
members_.nodeptr_ = node_traits::get_next(members_.nodeptr_);
return result;
}
- friend bool operator== (const slist_iterator& l, const slist_iterator& r)
+ BOOST_INTRUSIVE_FORCEINLINE friend bool operator== (const slist_iterator& l, const slist_iterator& r)
{ return l.pointed_node() == r.pointed_node(); }
- friend bool operator!= (const slist_iterator& l, const slist_iterator& r)
+ BOOST_INTRUSIVE_FORCEINLINE friend bool operator!= (const slist_iterator& l, const slist_iterator& r)
{ return !(l == r); }
- reference operator*() const
+ BOOST_INTRUSIVE_FORCEINLINE reference operator*() const
{ return *operator->(); }
- pointer operator->() const
+ BOOST_INTRUSIVE_FORCEINLINE pointer operator->() const
{ return this->operator_arrow(detail::bool_<stateful_value_traits>()); }
- slist_iterator<ValueTraits, false> unconst() const
+ BOOST_INTRUSIVE_FORCEINLINE slist_iterator<ValueTraits, false> unconst() const
{ return slist_iterator<ValueTraits, false>(this->pointed_node(), this->get_value_traits()); }
private:
- pointer operator_arrow(detail::false_) const
+ BOOST_INTRUSIVE_FORCEINLINE pointer operator_arrow(detail::false_) const
{ return ValueTraits::to_value_ptr(members_.nodeptr_); }
- pointer operator_arrow(detail::true_) const
+ BOOST_INTRUSIVE_FORCEINLINE pointer operator_arrow(detail::true_) const
{ return this->get_value_traits()->to_value_ptr(members_.nodeptr_); }
iiterator_members<node_ptr, const_value_traits_ptr, stateful_value_traits> members_;
diff --git a/boost/intrusive/detail/slist_node.hpp b/boost/intrusive/detail/slist_node.hpp
index 3d5fbfb6e5..848764e571 100644
--- a/boost/intrusive/detail/slist_node.hpp
+++ b/boost/intrusive/detail/slist_node.hpp
@@ -23,6 +23,7 @@
#endif
#include <boost/intrusive/detail/config_begin.hpp>
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/pointer_rebind.hpp>
namespace boost {
@@ -45,13 +46,13 @@ struct slist_node_traits
typedef typename node::node_ptr node_ptr;
typedef typename pointer_rebind<VoidPointer, const node>::type const_node_ptr;
- static node_ptr get_next(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_next(const const_node_ptr & n)
{ return n->next_; }
- static node_ptr get_next(const node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_next(const node_ptr & n)
{ return n->next_; }
- static void set_next(const node_ptr & n, const node_ptr & next)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_next(const node_ptr & n, const node_ptr & next)
{ n->next_ = next; }
};
diff --git a/boost/intrusive/detail/to_raw_pointer.hpp b/boost/intrusive/detail/to_raw_pointer.hpp
index 387f63f2a4..8ea884959d 100644
--- a/boost/intrusive/detail/to_raw_pointer.hpp
+++ b/boost/intrusive/detail/to_raw_pointer.hpp
@@ -22,6 +22,7 @@
#endif
#include <boost/intrusive/detail/config_begin.hpp>
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/detail/pointer_element.hpp>
namespace boost {
@@ -29,11 +30,11 @@ namespace intrusive {
namespace detail {
template <class T>
-inline T* to_raw_pointer(T* p)
+BOOST_INTRUSIVE_FORCEINLINE T* to_raw_pointer(T* p)
{ return p; }
template <class Pointer>
-inline typename boost::intrusive::pointer_element<Pointer>::type*
+BOOST_INTRUSIVE_FORCEINLINE typename boost::intrusive::pointer_element<Pointer>::type*
to_raw_pointer(const Pointer &p)
{ return boost::intrusive::detail::to_raw_pointer(p.operator->()); }
diff --git a/boost/intrusive/detail/transform_iterator.hpp b/boost/intrusive/detail/transform_iterator.hpp
index 5e3b1a7652..0a715754d7 100644
--- a/boost/intrusive/detail/transform_iterator.hpp
+++ b/boost/intrusive/detail/transform_iterator.hpp
@@ -22,6 +22,7 @@
#endif
#include <boost/intrusive/detail/config_begin.hpp>
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/detail/iterator.hpp>
@@ -32,11 +33,11 @@ namespace detail {
template <class PseudoReference>
struct operator_arrow_proxy
{
- operator_arrow_proxy(const PseudoReference &px)
+ BOOST_INTRUSIVE_FORCEINLINE operator_arrow_proxy(const PseudoReference &px)
: m_value(px)
{}
- PseudoReference* operator->() const { return &m_value; }
+ BOOST_INTRUSIVE_FORCEINLINE PseudoReference* operator->() const { return &m_value; }
// This function is needed for MWCW and BCC, which won't call operator->
// again automatically per 13.3.1.2 para 8
// operator T*() const { return &m_value; }
@@ -46,11 +47,11 @@ struct operator_arrow_proxy
template <class T>
struct operator_arrow_proxy<T&>
{
- operator_arrow_proxy(T &px)
+ BOOST_INTRUSIVE_FORCEINLINE operator_arrow_proxy(T &px)
: m_value(px)
{}
- T* operator->() const { return &m_value; }
+ BOOST_INTRUSIVE_FORCEINLINE T* operator->() const { return &m_value; }
// This function is needed for MWCW and BCC, which won't call operator->
// again automatically per 13.3.1.2 para 8
// operator T*() const { return &m_value; }
@@ -75,53 +76,53 @@ class transform_iterator
: members_()
{}
- Iterator get_it() const
+ BOOST_INTRUSIVE_FORCEINLINE Iterator get_it() const
{ return members_.m_it; }
//Constructors
- transform_iterator& operator++()
+ BOOST_INTRUSIVE_FORCEINLINE transform_iterator& operator++()
{ increment(); return *this; }
- transform_iterator operator++(int)
+ BOOST_INTRUSIVE_FORCEINLINE transform_iterator operator++(int)
{
transform_iterator result (*this);
increment();
return result;
}
- friend bool operator== (const transform_iterator& i, const transform_iterator& i2)
+ BOOST_INTRUSIVE_FORCEINLINE friend bool operator== (const transform_iterator& i, const transform_iterator& i2)
{ return i.equal(i2); }
- friend bool operator!= (const transform_iterator& i, const transform_iterator& i2)
+ BOOST_INTRUSIVE_FORCEINLINE friend bool operator!= (const transform_iterator& i, const transform_iterator& i2)
{ return !(i == i2); }
- friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2)
+ BOOST_INTRUSIVE_FORCEINLINE friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2)
{ return i2.distance_to(i); }
//Arithmetic
transform_iterator& operator+=(typename Iterator::difference_type off)
{ this->advance(off); return *this; }
- transform_iterator operator+(typename Iterator::difference_type off) const
+ BOOST_INTRUSIVE_FORCEINLINE transform_iterator operator+(typename Iterator::difference_type off) const
{
transform_iterator other(*this);
other.advance(off);
return other;
}
- friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right)
+ BOOST_INTRUSIVE_FORCEINLINE friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right)
{ return right + off; }
- transform_iterator& operator-=(typename Iterator::difference_type off)
+ BOOST_INTRUSIVE_FORCEINLINE transform_iterator& operator-=(typename Iterator::difference_type off)
{ this->advance(-off); return *this; }
- transform_iterator operator-(typename Iterator::difference_type off) const
+ BOOST_INTRUSIVE_FORCEINLINE transform_iterator operator-(typename Iterator::difference_type off) const
{ return *this + (-off); }
- typename UnaryFunction::result_type operator*() const
+ BOOST_INTRUSIVE_FORCEINLINE typename UnaryFunction::result_type operator*() const
{ return dereference(); }
- operator_arrow_proxy<typename UnaryFunction::result_type>
+ BOOST_INTRUSIVE_FORCEINLINE operator_arrow_proxy<typename UnaryFunction::result_type>
operator->() const
{ return operator_arrow_proxy<typename UnaryFunction::result_type>(dereference()); }
@@ -129,27 +130,27 @@ class transform_iterator
struct members
: UnaryFunction
{
- members(const Iterator &it, const UnaryFunction &f)
+ BOOST_INTRUSIVE_FORCEINLINE members(const Iterator &it, const UnaryFunction &f)
: UnaryFunction(f), m_it(it)
{}
- members()
+ BOOST_INTRUSIVE_FORCEINLINE members()
{}
Iterator m_it;
} members_;
- void increment()
+ BOOST_INTRUSIVE_FORCEINLINE void increment()
{ ++members_.m_it; }
- void decrement()
+ BOOST_INTRUSIVE_FORCEINLINE void decrement()
{ --members_.m_it; }
- bool equal(const transform_iterator &other) const
+ BOOST_INTRUSIVE_FORCEINLINE bool equal(const transform_iterator &other) const
{ return members_.m_it == other.members_.m_it; }
- bool less(const transform_iterator &other) const
+ BOOST_INTRUSIVE_FORCEINLINE bool less(const transform_iterator &other) const
{ return other.members_.m_it < members_.m_it; }
typename UnaryFunction::result_type dereference() const
diff --git a/boost/intrusive/detail/tree_iterator.hpp b/boost/intrusive/detail/tree_iterator.hpp
index 4985c6ce7b..f36a1f244b 100644
--- a/boost/intrusive/detail/tree_iterator.hpp
+++ b/boost/intrusive/detail/tree_iterator.hpp
@@ -22,6 +22,7 @@
#endif
#include <boost/intrusive/detail/config_begin.hpp>
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/detail/std_fwd.hpp>
#include <boost/intrusive/detail/iiterator.hpp>
#include <boost/intrusive/detail/bstree_algorithms_base.hpp>
@@ -56,27 +57,27 @@ class tree_iterator
typedef void (tree_iterator::*unspecified_bool_type)() const;
public:
- typedef typename types_t::iterator_traits::difference_type difference_type;
- typedef typename types_t::iterator_traits::value_type value_type;
- typedef typename types_t::iterator_traits::pointer pointer;
- typedef typename types_t::iterator_traits::reference reference;
- typedef typename types_t::iterator_traits::iterator_category iterator_category;
+ typedef typename types_t::iterator_type::difference_type difference_type;
+ typedef typename types_t::iterator_type::value_type value_type;
+ typedef typename types_t::iterator_type::pointer pointer;
+ typedef typename types_t::iterator_type::reference reference;
+ typedef typename types_t::iterator_type::iterator_category iterator_category;
- tree_iterator()
+ BOOST_INTRUSIVE_FORCEINLINE tree_iterator()
{}
- explicit tree_iterator(const node_ptr & nodeptr, const const_value_traits_ptr &traits_ptr)
+ BOOST_INTRUSIVE_FORCEINLINE explicit tree_iterator(const node_ptr & nodeptr, const const_value_traits_ptr &traits_ptr)
: members_(nodeptr, traits_ptr)
{}
- tree_iterator(tree_iterator<value_traits, false> const& other)
+ BOOST_INTRUSIVE_FORCEINLINE tree_iterator(tree_iterator<value_traits, false> const& other)
: members_(other.pointed_node(), other.get_value_traits())
{}
- const node_ptr &pointed_node() const
+ BOOST_INTRUSIVE_FORCEINLINE const node_ptr &pointed_node() const
{ return members_.nodeptr_; }
- tree_iterator &operator=(const node_ptr &nodeptr)
+ BOOST_INTRUSIVE_FORCEINLINE tree_iterator &operator=(const node_ptr &nodeptr)
{ members_.nodeptr_ = nodeptr; return static_cast<tree_iterator&>(*this); }
public:
@@ -106,43 +107,43 @@ class tree_iterator
return result;
}
- tree_iterator& go_left()
+ BOOST_INTRUSIVE_FORCEINLINE tree_iterator& go_left()
{
members_.nodeptr_ = node_traits::get_left(members_.nodeptr_);
return static_cast<tree_iterator&> (*this);
}
- tree_iterator& go_right()
+ BOOST_INTRUSIVE_FORCEINLINE tree_iterator& go_right()
{
members_.nodeptr_ = node_traits::get_right(members_.nodeptr_);
return static_cast<tree_iterator&> (*this);
}
- tree_iterator& go_parent()
+ BOOST_INTRUSIVE_FORCEINLINE tree_iterator& go_parent()
{
members_.nodeptr_ = node_traits::get_parent(members_.nodeptr_);
return static_cast<tree_iterator&> (*this);
}
- operator unspecified_bool_type() const
+ BOOST_INTRUSIVE_FORCEINLINE operator unspecified_bool_type() const
{ return members_.nodeptr_ ? &tree_iterator::unspecified_bool_type_func : 0; }
- bool operator! () const
+ BOOST_INTRUSIVE_FORCEINLINE bool operator! () const
{ return !members_.nodeptr_; }
- friend bool operator== (const tree_iterator& l, const tree_iterator& r)
+ BOOST_INTRUSIVE_FORCEINLINE friend bool operator== (const tree_iterator& l, const tree_iterator& r)
{ return l.pointed_node() == r.pointed_node(); }
- friend bool operator!= (const tree_iterator& l, const tree_iterator& r)
+ BOOST_INTRUSIVE_FORCEINLINE friend bool operator!= (const tree_iterator& l, const tree_iterator& r)
{ return !(l == r); }
- reference operator*() const
+ BOOST_INTRUSIVE_FORCEINLINE reference operator*() const
{ return *operator->(); }
- pointer operator->() const
+ BOOST_INTRUSIVE_FORCEINLINE pointer operator->() const
{ return this->operator_arrow(detail::bool_<stateful_value_traits>()); }
- const_value_traits_ptr get_value_traits() const
+ BOOST_INTRUSIVE_FORCEINLINE const_value_traits_ptr get_value_traits() const
{ return members_.get_ptr(); }
tree_iterator end_iterator_from_it() const
@@ -154,10 +155,10 @@ class tree_iterator
{ return tree_iterator<value_traits, false>(this->pointed_node(), this->get_value_traits()); }
private:
- pointer operator_arrow(detail::false_) const
+ BOOST_INTRUSIVE_FORCEINLINE pointer operator_arrow(detail::false_) const
{ return ValueTraits::to_value_ptr(members_.nodeptr_); }
- pointer operator_arrow(detail::true_) const
+ BOOST_INTRUSIVE_FORCEINLINE pointer operator_arrow(detail::true_) const
{ return this->get_value_traits()->to_value_ptr(members_.nodeptr_); }
iiterator_members<node_ptr, const_value_traits_ptr, stateful_value_traits> members_;
diff --git a/boost/intrusive/detail/tree_node.hpp b/boost/intrusive/detail/tree_node.hpp
index e36a82a6d6..606fbc865e 100644
--- a/boost/intrusive/detail/tree_node.hpp
+++ b/boost/intrusive/detail/tree_node.hpp
@@ -22,6 +22,7 @@
#endif
#include <boost/intrusive/detail/config_begin.hpp>
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/pointer_rebind.hpp>
namespace boost {
@@ -43,31 +44,31 @@ struct tree_node_traits
typedef typename node::node_ptr node_ptr;
typedef typename pointer_rebind<VoidPointer, const node>::type const_node_ptr;
- static node_ptr get_parent(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_parent(const const_node_ptr & n)
{ return n->parent_; }
- static node_ptr get_parent(const node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_parent(const node_ptr & n)
{ return n->parent_; }
- static void set_parent(const node_ptr & n, const node_ptr & p)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_parent(const node_ptr & n, const node_ptr & p)
{ n->parent_ = p; }
- static node_ptr get_left(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_left(const const_node_ptr & n)
{ return n->left_; }
- static node_ptr get_left(const node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_left(const node_ptr & n)
{ return n->left_; }
- static void set_left(const node_ptr & n, const node_ptr & l)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_left(const node_ptr & n, const node_ptr & l)
{ n->left_ = l; }
- static node_ptr get_right(const const_node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_right(const const_node_ptr & n)
{ return n->right_; }
- static node_ptr get_right(const node_ptr & n)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr get_right(const node_ptr & n)
{ return n->right_; }
- static void set_right(const node_ptr & n, const node_ptr & r)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_right(const node_ptr & n, const node_ptr & r)
{ n->right_ = r; }
};
diff --git a/boost/intrusive/detail/tree_value_compare.hpp b/boost/intrusive/detail/tree_value_compare.hpp
index dc554442fe..810d894066 100644
--- a/boost/intrusive/detail/tree_value_compare.hpp
+++ b/boost/intrusive/detail/tree_value_compare.hpp
@@ -18,6 +18,7 @@
# pragma once
#endif
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/detail/ebo_functor_holder.hpp>
@@ -53,10 +54,10 @@ struct tree_value_compare
tree_value_compare &operator=(const key_compare &x)
{ this->base_t::get() = x; return *this; }
- const key_compare &key_comp() const
+ BOOST_INTRUSIVE_FORCEINLINE const key_compare &key_comp() const
{ return static_cast<const key_compare &>(*this); }
- key_compare &key_comp()
+ BOOST_INTRUSIVE_FORCEINLINE key_compare &key_comp()
{ return static_cast<key_compare &>(*this); }
template<class U>
@@ -70,16 +71,16 @@ struct tree_value_compare
{ return key; }
template<class U>
- const key_type & key_forward
+ BOOST_INTRUSIVE_FORCEINLINE const key_type & key_forward
(const U &key, typename boost::intrusive::detail::disable_if<is_key<U> >::type* = 0) const
{ return KeyOfValue()(key); }
template<class KeyType, class KeyType2>
- bool operator()(const KeyType &key1, const KeyType2 &key2) const
+ BOOST_INTRUSIVE_FORCEINLINE bool operator()(const KeyType &key1, const KeyType2 &key2) const
{ return key_compare::operator()(this->key_forward(key1), this->key_forward(key2)); }
template<class KeyType, class KeyType2>
- bool operator()(const KeyType &key1, const KeyType2 &key2)
+ BOOST_INTRUSIVE_FORCEINLINE bool operator()(const KeyType &key1, const KeyType2 &key2)
{ return key_compare::operator()(this->key_forward(key1), this->key_forward(key2)); }
};
diff --git a/boost/intrusive/detail/workaround.hpp b/boost/intrusive/detail/workaround.hpp
index b73f4ef8bf..7a9ac48e0b 100644
--- a/boost/intrusive/detail/workaround.hpp
+++ b/boost/intrusive/detail/workaround.hpp
@@ -34,5 +34,17 @@
#define BOOST_INTRUSIVE_I ,
#define BOOST_INTRUSIVE_DOCIGN(T1) T1
+#define BOOST_INTRUSIVE_DISABLE_FORCEINLINE
+
+#if defined(BOOST_INTRUSIVE_DISABLE_FORCEINLINE)
+ #define BOOST_INTRUSIVE_FORCEINLINE inline
+#elif defined(BOOST_INTRUSIVE_FORCEINLINE_IS_BOOST_FORCELINE)
+ #define BOOST_INTRUSIVE_FORCEINLINE BOOST_FORCEINLINE
+#elif defined(BOOST_MSVC) && defined(_DEBUG)
+ //"__forceinline" and MSVC seems to have some bugs in debug mode
+ #define BOOST_INTRUSIVE_FORCEINLINE inline
+#else
+ #define BOOST_INTRUSIVE_FORCEINLINE BOOST_FORCEINLINE
+#endif
#endif //#ifndef BOOST_INTRUSIVE_DETAIL_WORKAROUND_HPP
diff --git a/boost/intrusive/hashtable.hpp b/boost/intrusive/hashtable.hpp
index 125330ff6e..f9074c0141 100644
--- a/boost/intrusive/hashtable.hpp
+++ b/boost/intrusive/hashtable.hpp
@@ -2057,8 +2057,7 @@ class hashtable_impl
std::pair<iterator, bool> insert_unique(reference value)
{
insert_commit_data commit_data;
- std::pair<iterator, bool> ret = this->insert_unique_check
- (key_of_value()(value), this->priv_hasher(), this->priv_equal(), commit_data);
+ std::pair<iterator, bool> ret = this->insert_unique_check(key_of_value()(value), commit_data);
if(ret.second){
ret.first = this->insert_unique_commit(value, commit_data);
}
@@ -2134,6 +2133,37 @@ class hashtable_impl
, pos == this->priv_invalid_local_it());
}
+ //! <b>Effects</b>: Checks if a value can be inserted in the unordered_set, using
+ //! a user provided key instead of the value itself.
+ //!
+ //! <b>Returns</b>: If there is an equivalent value
+ //! returns a pair containing an iterator to the already present value
+ //! and false. If the value can be inserted returns true in the returned
+ //! pair boolean and fills "commit_data" that is meant to be used with
+ //! the "insert_commit" function.
+ //!
+ //! <b>Complexity</b>: Average case O(1), worst case O(this->size()).
+ //!
+ //! <b>Throws</b>: If hasher or key_compare throw. Strong guarantee.
+ //!
+ //! <b>Notes</b>: This function is used to improve performance when constructing
+ //! a value_type is expensive: if there is an equivalent value
+ //! the constructed object must be discarded. Many times, the part of the
+ //! node that is used to impose the hash or the equality is much cheaper to
+ //! construct than the value_type and this function offers the possibility to
+ //! use that the part to check if the insertion will be successful.
+ //!
+ //! If the check is successful, the user can construct the value_type and use
+ //! "insert_commit" to insert the object in constant-time.
+ //!
+ //! "commit_data" remains valid for a subsequent "insert_commit" only if no more
+ //! objects are inserted or erased from the unordered_set.
+ //!
+ //! After a successful rehashing insert_commit_data remains valid.
+ std::pair<iterator, bool> insert_unique_check
+ ( const key_type &key, insert_commit_data &commit_data)
+ { return this->insert_unique_check(key, this->priv_hasher(), this->priv_equal(), commit_data); }
+
//! <b>Requires</b>: value must be an lvalue of type value_type. commit_data
//! must have been obtained from a previous call to "insert_check".
//! No objects should have been inserted or erased from the unordered_set between
diff --git a/boost/intrusive/list.hpp b/boost/intrusive/list.hpp
index cc6d73bb43..a59734a7de 100644
--- a/boost/intrusive/list.hpp
+++ b/boost/intrusive/list.hpp
@@ -176,7 +176,20 @@ class list_impl
//!
//! <b>Throws</b>: If value_traits::node_traits::node
//! constructor throws (this does not happen with predefined Boost.Intrusive hooks).
- explicit list_impl(const value_traits &v_traits = value_traits())
+ list_impl()
+ : data_(value_traits())
+ {
+ this->priv_size_traits().set_size(size_type(0));
+ node_algorithms::init_header(this->get_root_node());
+ }
+
+ //! <b>Effects</b>: constructs an empty list.
+ //!
+ //! <b>Complexity</b>: Constant
+ //!
+ //! <b>Throws</b>: If value_traits::node_traits::node
+ //! constructor throws (this does not happen with predefined Boost.Intrusive hooks).
+ explicit list_impl(const value_traits &v_traits)
: data_(v_traits)
{
this->priv_size_traits().set_size(size_type(0));
@@ -1455,7 +1468,11 @@ class list
typedef typename Base::iterator iterator;
typedef typename Base::const_iterator const_iterator;
- explicit list(const value_traits &v_traits = value_traits())
+ list()
+ : Base()
+ {}
+
+ explicit list(const value_traits &v_traits)
: Base(v_traits)
{}
diff --git a/boost/intrusive/member_value_traits.hpp b/boost/intrusive/member_value_traits.hpp
index b540178d5a..01ccf4e38f 100644
--- a/boost/intrusive/member_value_traits.hpp
+++ b/boost/intrusive/member_value_traits.hpp
@@ -56,19 +56,19 @@ struct member_value_traits
typedef const value_type & const_reference;
static const link_mode_type link_mode = LinkMode;
- static node_ptr to_node_ptr(reference value)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr to_node_ptr(reference value)
{ return pointer_traits<node_ptr>::pointer_to(value.*PtrToMember); }
- static const_node_ptr to_node_ptr(const_reference value)
+ BOOST_INTRUSIVE_FORCEINLINE static const_node_ptr to_node_ptr(const_reference value)
{ return pointer_traits<const_node_ptr>::pointer_to(value.*PtrToMember); }
- static pointer to_value_ptr(const node_ptr &n)
+ BOOST_INTRUSIVE_FORCEINLINE static pointer to_value_ptr(const node_ptr &n)
{
return pointer_traits<pointer>::pointer_to(*detail::parent_from_member<value_type, node>
(boost::intrusive::detail::to_raw_pointer(n), PtrToMember));
}
- static const_pointer to_value_ptr(const const_node_ptr &n)
+ BOOST_INTRUSIVE_FORCEINLINE static const_pointer to_value_ptr(const const_node_ptr &n)
{
return pointer_traits<const_pointer>::pointer_to(*detail::parent_from_member<value_type, node>
(boost::intrusive::detail::to_raw_pointer(n), PtrToMember));
diff --git a/boost/intrusive/parent_from_member.hpp b/boost/intrusive/parent_from_member.hpp
index af3aa1f808..a9a9293c7c 100644
--- a/boost/intrusive/parent_from_member.hpp
+++ b/boost/intrusive/parent_from_member.hpp
@@ -13,6 +13,7 @@
#define BOOST_INTRUSIVE_PARENT_FROM_MEMBER_HPP
#include <boost/intrusive/detail/config_begin.hpp>
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/parent_from_member.hpp>
@@ -29,7 +30,7 @@ namespace intrusive {
//! Note: this function does not work with pointer to members that rely on
//! virtual inheritance.
template<class Parent, class Member>
-inline Parent *get_parent_from_member(Member *member, const Member Parent::* ptr_to_member)
+BOOST_INTRUSIVE_FORCEINLINE Parent *get_parent_from_member(Member *member, const Member Parent::* ptr_to_member)
{ return ::boost::intrusive::detail::parent_from_member(member, ptr_to_member); }
//! Given a const pointer to a member and its corresponding const pointer to data member,
@@ -37,7 +38,7 @@ inline Parent *get_parent_from_member(Member *member, const Member Parent::* ptr
//! Note: this function does not work with pointer to members that rely on
//! virtual inheritance.
template<class Parent, class Member>
-inline const Parent *get_parent_from_member(const Member *member, const Member Parent::* ptr_to_member)
+BOOST_INTRUSIVE_FORCEINLINE const Parent *get_parent_from_member(const Member *member, const Member Parent::* ptr_to_member)
{ return ::boost::intrusive::detail::parent_from_member(member, ptr_to_member); }
} //namespace intrusive {
diff --git a/boost/intrusive/pointer_plus_bits.hpp b/boost/intrusive/pointer_plus_bits.hpp
index 6168ea8ea4..dfde66b712 100644
--- a/boost/intrusive/pointer_plus_bits.hpp
+++ b/boost/intrusive/pointer_plus_bits.hpp
@@ -67,19 +67,19 @@ struct pointer_plus_bits<T*, NumBits>
static const uintptr_t Mask = uintptr_t((uintptr_t(1u) << NumBits) - 1);
typedef T* pointer;
- static pointer get_pointer(pointer n)
+ BOOST_INTRUSIVE_FORCEINLINE static pointer get_pointer(pointer n)
{ return pointer(uintptr_t(n) & uintptr_t(~Mask)); }
- static void set_pointer(pointer &n, pointer p)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_pointer(pointer &n, pointer p)
{
BOOST_INTRUSIVE_INVARIANT_ASSERT(0 == (uintptr_t(p) & Mask));
n = pointer(uintptr_t(p) | (uintptr_t(n) & Mask));
}
- static std::size_t get_bits(pointer n)
+ BOOST_INTRUSIVE_FORCEINLINE static std::size_t get_bits(pointer n)
{ return std::size_t(uintptr_t(n) & Mask); }
- static void set_bits(pointer &n, std::size_t c)
+ BOOST_INTRUSIVE_FORCEINLINE static void set_bits(pointer &n, std::size_t c)
{
BOOST_INTRUSIVE_INVARIANT_ASSERT(uintptr_t(c) <= Mask);
n = pointer(uintptr_t((get_pointer)(n)) | uintptr_t(c));
diff --git a/boost/intrusive/pointer_traits.hpp b/boost/intrusive/pointer_traits.hpp
index 731432b01f..5baf5e807c 100644
--- a/boost/intrusive/pointer_traits.hpp
+++ b/boost/intrusive/pointer_traits.hpp
@@ -288,25 +288,25 @@ struct pointer_traits<T*>
//! <b>Returns</b>: addressof(r)
//!
- static pointer pointer_to(reference r)
+ BOOST_INTRUSIVE_FORCEINLINE static pointer pointer_to(reference r)
{ return boost::intrusive::detail::addressof(r); }
//! <b>Returns</b>: static_cast<pointer>(uptr)
//!
template<class U>
- static pointer static_cast_from(U *uptr)
+ BOOST_INTRUSIVE_FORCEINLINE static pointer static_cast_from(U *uptr)
{ return static_cast<pointer>(uptr); }
//! <b>Returns</b>: const_cast<pointer>(uptr)
//!
template<class U>
- static pointer const_cast_from(U *uptr)
+ BOOST_INTRUSIVE_FORCEINLINE static pointer const_cast_from(U *uptr)
{ return const_cast<pointer>(uptr); }
//! <b>Returns</b>: dynamic_cast<pointer>(uptr)
//!
template<class U>
- static pointer dynamic_cast_from(U *uptr)
+ BOOST_INTRUSIVE_FORCEINLINE static pointer dynamic_cast_from(U *uptr)
{ return dynamic_cast<pointer>(uptr); }
};
diff --git a/boost/intrusive/priority_compare.hpp b/boost/intrusive/priority_compare.hpp
index 2ff851f475..ffade48b7c 100644
--- a/boost/intrusive/priority_compare.hpp
+++ b/boost/intrusive/priority_compare.hpp
@@ -14,6 +14,7 @@
#define BOOST_INTRUSIVE_PRIORITY_COMPARE_HPP
#include <boost/intrusive/detail/config_begin.hpp>
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/minimal_less_equal_header.hpp>
@@ -33,7 +34,7 @@ struct priority_compare
typedef T second_argument_type;
typedef bool result_type;
- bool operator()(const T &val, const T &val2) const
+ BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T &val, const T &val2) const
{
return priority_order(val, val2);
}
@@ -41,10 +42,10 @@ struct priority_compare
/// @cond
-template<class Less, class T>
+template<class PrioComp, class T>
struct get_prio
{
- typedef Less type;
+ typedef PrioComp type;
};
diff --git a/boost/intrusive/rbtree.hpp b/boost/intrusive/rbtree.hpp
index f3afd017c8..276362d2fc 100644
--- a/boost/intrusive/rbtree.hpp
+++ b/boost/intrusive/rbtree.hpp
@@ -121,9 +121,13 @@ class rbtree_impl
typedef typename implementation_defined::insert_commit_data insert_commit_data;
+ //! @copydoc ::boost::intrusive::bstree::bstree()
+ rbtree_impl()
+ : tree_type()
+ {}
+
//! @copydoc ::boost::intrusive::bstree::bstree(const key_compare &,const value_traits &)
- explicit rbtree_impl( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ explicit rbtree_impl( const key_compare &cmp, const value_traits &v_traits = value_traits())
: tree_type(cmp, v_traits)
{}
@@ -259,6 +263,14 @@ class rbtree_impl
(const_iterator hint, const KeyType &key
,KeyTypeKeyCompare comp, insert_commit_data &commit_data);
+ //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const key_type&,insert_commit_data&)
+ std::pair<iterator, bool> insert_unique_check
+ (const key_type &key, insert_commit_data &commit_data);
+
+ //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const key_type&,insert_commit_data&)
+ std::pair<iterator, bool> insert_unique_check
+ (const_iterator hint, const key_type &key, insert_commit_data &commit_data);
+
//! @copydoc ::boost::intrusive::bstree::insert_unique_commit
iterator insert_unique_commit(reference value, const insert_commit_data &commit_data);
@@ -509,8 +521,11 @@ class rbtree
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
- explicit rbtree( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ rbtree()
+ : Base()
+ {}
+
+ explicit rbtree( const key_compare &cmp, const value_traits &v_traits = value_traits())
: Base(cmp, v_traits)
{}
diff --git a/boost/intrusive/set.hpp b/boost/intrusive/set.hpp
index f0072eab20..36c46c7e6e 100644
--- a/boost/intrusive/set.hpp
+++ b/boost/intrusive/set.hpp
@@ -83,9 +83,13 @@ class set_impl
static const bool constant_time_size = tree_type::constant_time_size;
public:
+ //! @copydoc ::boost::intrusive::rbtree::rbtree()
+ set_impl()
+ : tree_type()
+ {}
+
//! @copydoc ::boost::intrusive::rbtree::rbtree(const key_compare &,const value_traits &)
- explicit set_impl( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ explicit set_impl( const key_compare &cmp, const value_traits &v_traits = value_traits())
: tree_type(cmp, v_traits)
{}
@@ -196,6 +200,17 @@ class set_impl
iterator insert(const_iterator hint, reference value)
{ return tree_type::insert_unique(hint, value); }
+ //! @copydoc ::boost::intrusive::rbtree::insert_unique_check(const key_type&,insert_commit_data&)
+ std::pair<iterator, bool> insert_check
+ (const key_type &key, insert_commit_data &commit_data)
+ { return tree_type::insert_unique_check(key, commit_data); }
+
+ //! @copydoc ::boost::intrusive::rbtree::insert_unique_check(const_iterator,const key_type&,insert_commit_data&)
+ std::pair<iterator, bool> insert_check
+ (const_iterator hint, const key_type &key
+ ,insert_commit_data &commit_data)
+ { return tree_type::insert_unique_check(hint, key, commit_data); }
+
//! @copydoc ::boost::intrusive::rbtree::insert_unique_check(const KeyType&,KeyTypeKeyCompare,insert_commit_data&)
template<class KeyType, class KeyTypeKeyCompare>
std::pair<iterator, bool> insert_check
@@ -476,8 +491,11 @@ class set
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
- explicit set( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ set()
+ : Base()
+ {}
+
+ explicit set( const key_compare &cmp, const value_traits &v_traits = value_traits())
: Base(cmp, v_traits)
{}
@@ -573,9 +591,13 @@ class multiset_impl
static const bool constant_time_size = tree_type::constant_time_size;
public:
+ //! @copydoc ::boost::intrusive::rbtree::rbtree()
+ multiset_impl()
+ : tree_type()
+ {}
+
//! @copydoc ::boost::intrusive::rbtree::rbtree(const key_compare &,const value_traits &)
- explicit multiset_impl( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ explicit multiset_impl( const key_compare &cmp, const value_traits &v_traits = value_traits())
: tree_type(cmp, v_traits)
{}
@@ -936,8 +958,11 @@ class multiset
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
- multiset( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ multiset()
+ : Base()
+ {}
+
+ explicit multiset( const key_compare &cmp, const value_traits &v_traits = value_traits())
: Base(cmp, v_traits)
{}
diff --git a/boost/intrusive/sg_set.hpp b/boost/intrusive/sg_set.hpp
index e6d4e377d3..171bd59ed1 100644
--- a/boost/intrusive/sg_set.hpp
+++ b/boost/intrusive/sg_set.hpp
@@ -81,9 +81,13 @@ class sg_set_impl
static const bool constant_time_size = tree_type::constant_time_size;
public:
+ //! @copydoc ::boost::intrusive::sgtree::sgtree()
+ sg_set_impl()
+ : tree_type()
+ {}
+
//! @copydoc ::boost::intrusive::sgtree::sgtree(const key_compare &,const value_traits &)
- explicit sg_set_impl( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ explicit sg_set_impl( const key_compare &cmp, const value_traits &v_traits = value_traits())
: tree_type(cmp, v_traits)
{}
@@ -194,6 +198,17 @@ class sg_set_impl
iterator insert(const_iterator hint, reference value)
{ return tree_type::insert_unique(hint, value); }
+ //! @copydoc ::boost::intrusive::sgtree::insert_unique_check(const key_type&,insert_commit_data&)
+ std::pair<iterator, bool> insert_check
+ (const key_type &key, insert_commit_data &commit_data)
+ { return tree_type::insert_unique_check(key, commit_data); }
+
+ //! @copydoc ::boost::intrusive::sgtree::insert_unique_check(const_iterator,const key_type&,insert_commit_data&)
+ std::pair<iterator, bool> insert_check
+ (const_iterator hint, const key_type &key
+ ,insert_commit_data &commit_data)
+ { return tree_type::insert_unique_check(hint, key, commit_data); }
+
//! @copydoc ::boost::intrusive::sgtree::insert_unique_check(const KeyType&,KeyTypeKeyCompare,insert_commit_data&)
template<class KeyType, class KeyTypeKeyCompare>
std::pair<iterator, bool> insert_check
@@ -319,21 +334,21 @@ class sg_set_impl
#endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
- //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &)
+ //! @copydoc ::boost::intrusive::sgtree::equal_range(const key_type &)
std::pair<iterator,iterator> equal_range(const key_type &key)
{ return this->tree_type::lower_bound_range(key); }
- //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyTypeKeyCompare)
+ //! @copydoc ::boost::intrusive::sgtree::equal_range(const KeyType&,KeyTypeKeyCompare)
template<class KeyType, class KeyTypeKeyCompare>
std::pair<iterator,iterator> equal_range(const KeyType& key, KeyTypeKeyCompare comp)
{ return this->tree_type::equal_range(key, comp); }
- //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &)const
+ //! @copydoc ::boost::intrusive::sgtree::equal_range(const key_type &)const
std::pair<const_iterator, const_iterator>
equal_range(const key_type &key) const
{ return this->tree_type::lower_bound_range(key); }
- //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyTypeKeyCompare)const
+ //! @copydoc ::boost::intrusive::sgtree::equal_range(const KeyType&,KeyTypeKeyCompare)const
template<class KeyType, class KeyTypeKeyCompare>
std::pair<const_iterator, const_iterator>
equal_range(const KeyType& key, KeyTypeKeyCompare comp) const
@@ -487,8 +502,11 @@ class sg_set
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
- explicit sg_set( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ sg_set()
+ : Base()
+ {}
+
+ explicit sg_set( const key_compare &cmp, const value_traits &v_traits = value_traits())
: Base(cmp, v_traits)
{}
@@ -584,9 +602,13 @@ class sg_multiset_impl
static const bool constant_time_size = tree_type::constant_time_size;
public:
+ //! @copydoc ::boost::intrusive::sgtree::sgtree()
+ sg_multiset_impl()
+ : tree_type()
+ {}
+
//! @copydoc ::boost::intrusive::sgtree::sgtree(const key_compare &,const value_traits &)
- explicit sg_multiset_impl( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ explicit sg_multiset_impl( const key_compare &cmp, const value_traits &v_traits = value_traits())
: tree_type(cmp, v_traits)
{}
@@ -960,8 +982,11 @@ class sg_multiset
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
- sg_multiset( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ sg_multiset()
+ : Base()
+ {}
+
+ explicit sg_multiset( const key_compare &cmp, const value_traits &v_traits = value_traits())
: Base(cmp, v_traits)
{}
diff --git a/boost/intrusive/sgtree.hpp b/boost/intrusive/sgtree.hpp
index b4c4cdec1a..6e7af7dfd3 100644
--- a/boost/intrusive/sgtree.hpp
+++ b/boost/intrusive/sgtree.hpp
@@ -281,9 +281,13 @@ class sgtree_impl
typedef BOOST_INTRUSIVE_IMPDEF(typename node_algorithms::insert_commit_data) insert_commit_data;
+ //! @copydoc ::boost::intrusive::bstree::bstree()
+ sgtree_impl()
+ : tree_type()
+ {}
+
//! @copydoc ::boost::intrusive::bstree::bstree(const key_compare &,const value_traits &)
- explicit sgtree_impl( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ explicit sgtree_impl( const key_compare &cmp, const value_traits &v_traits = value_traits())
: tree_type(cmp, v_traits)
{}
@@ -486,7 +490,11 @@ class sgtree_impl
//! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyTypeKeyCompare,insert_commit_data&)
template<class KeyType, class KeyTypeKeyCompare>
- std::pair<iterator, bool> insert_unique_check
+ BOOST_INTRUSIVE_DOC1ST(std::pair<iterator BOOST_INTRUSIVE_I bool>
+ , typename detail::disable_if_convertible
+ <KeyType BOOST_INTRUSIVE_I const_iterator BOOST_INTRUSIVE_I
+ std::pair<iterator BOOST_INTRUSIVE_I bool> >::type)
+ insert_unique_check
(const KeyType &key, KeyTypeKeyCompare comp, insert_commit_data &commit_data)
{
std::pair<node_ptr, bool> ret =
@@ -507,6 +515,16 @@ class sgtree_impl
return std::pair<iterator, bool>(iterator(ret.first, this->priv_value_traits_ptr()), ret.second);
}
+ //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const key_type&,insert_commit_data&)
+ std::pair<iterator, bool> insert_unique_check
+ (const key_type &key, insert_commit_data &commit_data)
+ { return this->insert_unique_check(key, this->key_comp(), commit_data); }
+
+ //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const key_type&,insert_commit_data&)
+ std::pair<iterator, bool> insert_unique_check
+ (const_iterator hint, const key_type &key, insert_commit_data &commit_data)
+ { return this->insert_unique_check(hint, key, this->key_comp(), commit_data); }
+
//! @copydoc ::boost::intrusive::bstree::insert_unique_commit
iterator insert_unique_commit(reference value, const insert_commit_data &commit_data)
{
@@ -934,8 +952,11 @@ class sgtree
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
- explicit sgtree( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ sgtree()
+ : Base()
+ {}
+
+ explicit sgtree(const key_compare &cmp, const value_traits &v_traits = value_traits())
: Base(cmp, v_traits)
{}
diff --git a/boost/intrusive/slist.hpp b/boost/intrusive/slist.hpp
index dd3a05f2f8..d64bf49d18 100644
--- a/boost/intrusive/slist.hpp
+++ b/boost/intrusive/slist.hpp
@@ -307,7 +307,17 @@ class slist_impl
//!
//! <b>Throws</b>: If value_traits::node_traits::node
//! constructor throws (this does not happen with predefined Boost.Intrusive hooks).
- explicit slist_impl(const value_traits &v_traits = value_traits())
+ slist_impl()
+ : data_(value_traits())
+ { this->set_default_constructed_state(); }
+
+ //! <b>Effects</b>: constructs an empty list.
+ //!
+ //! <b>Complexity</b>: Constant
+ //!
+ //! <b>Throws</b>: If value_traits::node_traits::node
+ //! constructor throws (this does not happen with predefined Boost.Intrusive hooks).
+ explicit slist_impl(const value_traits &v_traits)
: data_(v_traits)
{ this->set_default_constructed_state(); }
@@ -2190,7 +2200,11 @@ class slist
typedef typename Base::size_type size_type;
typedef typename Base::node_ptr node_ptr;
- explicit slist(const value_traits &v_traits = value_traits())
+ slist()
+ : Base()
+ {}
+
+ explicit slist(const value_traits &v_traits)
: Base(v_traits)
{}
diff --git a/boost/intrusive/splay_set.hpp b/boost/intrusive/splay_set.hpp
index 3d43215023..893b580812 100644
--- a/boost/intrusive/splay_set.hpp
+++ b/boost/intrusive/splay_set.hpp
@@ -81,9 +81,13 @@ class splay_set_impl
static const bool constant_time_size = tree_type::constant_time_size;
public:
+ //! @copydoc ::boost::intrusive::splaytree::splaytree()
+ splay_set_impl()
+ : tree_type()
+ {}
+
//! @copydoc ::boost::intrusive::splaytree::splaytree(const key_compare &,const value_traits &)
- explicit splay_set_impl( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ explicit splay_set_impl( const key_compare &cmp, const value_traits &v_traits = value_traits())
: tree_type(cmp, v_traits)
{}
@@ -194,6 +198,17 @@ class splay_set_impl
iterator insert(const_iterator hint, reference value)
{ return tree_type::insert_unique(hint, value); }
+ //! @copydoc ::boost::intrusive::rbtree::insert_unique_check(const key_type&,insert_commit_data&)
+ std::pair<iterator, bool> insert_check
+ (const key_type &key, insert_commit_data &commit_data)
+ { return tree_type::insert_unique_check(key, commit_data); }
+
+ //! @copydoc ::boost::intrusive::rbtree::insert_unique_check(const_iterator,const key_type&,insert_commit_data&)
+ std::pair<iterator, bool> insert_check
+ (const_iterator hint, const key_type &key
+ ,insert_commit_data &commit_data)
+ { return tree_type::insert_unique_check(hint, key, commit_data); }
+
//! @copydoc ::boost::intrusive::splaytree::insert_unique_check(const KeyType&,KeyTypeKeyCompare,insert_commit_data&)
template<class KeyType, class KeyTypeKeyCompare>
std::pair<iterator, bool> insert_check
@@ -497,8 +512,11 @@ class splay_set
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
- explicit splay_set( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ splay_set()
+ : Base()
+ {}
+
+ explicit splay_set( const key_compare &cmp, const value_traits &v_traits = value_traits())
: Base(cmp, v_traits)
{}
@@ -594,9 +612,13 @@ class splay_multiset_impl
static const bool constant_time_size = tree_type::constant_time_size;
public:
+ //! @copydoc ::boost::intrusive::splaytree::splaytree()
+ splay_multiset_impl()
+ : tree_type()
+ {}
+
//! @copydoc ::boost::intrusive::splaytree::splaytree(const key_compare &,const value_traits &)
- explicit splay_multiset_impl( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ explicit splay_multiset_impl(const key_compare &cmp, const value_traits &v_traits = value_traits())
: tree_type(cmp, v_traits)
{}
@@ -973,8 +995,11 @@ class splay_multiset
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
- explicit splay_multiset( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ splay_multiset()
+ : Base()
+ {}
+
+ explicit splay_multiset( const key_compare &cmp, const value_traits &v_traits = value_traits())
: Base(cmp, v_traits)
{}
diff --git a/boost/intrusive/splaytree.hpp b/boost/intrusive/splaytree.hpp
index 27d75df70f..afc10819a3 100644
--- a/boost/intrusive/splaytree.hpp
+++ b/boost/intrusive/splaytree.hpp
@@ -111,9 +111,13 @@ class splaytree_impl
typedef typename implementation_defined::insert_commit_data insert_commit_data;
+ //! @copydoc ::boost::intrusive::bstree::bstree()
+ splaytree_impl()
+ : tree_type()
+ {}
+
//! @copydoc ::boost::intrusive::bstree::bstree(const key_compare &,const value_traits &)
- explicit splaytree_impl( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ explicit splaytree_impl( const key_compare &cmp, const value_traits &v_traits = value_traits())
: tree_type(cmp, v_traits)
{}
@@ -240,6 +244,14 @@ class splaytree_impl
//! @copydoc ::boost::intrusive::bstree::insert_unique(const_iterator,reference)
iterator insert_unique(const_iterator hint, reference value);
+ //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const key_type&,insert_commit_data&)
+ std::pair<iterator, bool> insert_unique_check
+ (const key_type &key, insert_commit_data &commit_data);
+
+ //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const key_type&,insert_commit_data&)
+ std::pair<iterator, bool> insert_unique_check
+ (const_iterator hint, const key_type &key, insert_commit_data &commit_data);
+
//! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyTypeKeyCompare,insert_commit_data&)
template<class KeyType, class KeyTypeKeyCompare>
std::pair<iterator, bool> insert_unique_check
@@ -584,8 +596,11 @@ class splaytree
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
- explicit splaytree( const key_compare &cmp = key_compare()
- , const value_traits &v_traits = value_traits())
+ splaytree()
+ : Base()
+ {}
+
+ explicit splaytree( const key_compare &cmp, const value_traits &v_traits = value_traits())
: Base(cmp, v_traits)
{}
diff --git a/boost/intrusive/treap.hpp b/boost/intrusive/treap.hpp
index 52785dafb0..385271943e 100644
--- a/boost/intrusive/treap.hpp
+++ b/boost/intrusive/treap.hpp
@@ -80,7 +80,7 @@ class treap_impl
< typename get_prio
< VoidOrPrioComp
, typename bstree_impl
- <ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType, ConstantTimeSize, BsTreeAlgorithms, HeaderHolder>::value_type>::type
+ <ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType, ConstantTimeSize, BsTreeAlgorithms, HeaderHolder>::key_type>::type
>
/// @endcond
{
@@ -93,7 +93,7 @@ class treap_impl
typedef tree_type implementation_defined;
typedef get_prio
< VoidOrPrioComp
- , typename tree_type::value_type> get_prio_type;
+ , typename tree_type::key_type> get_prio_type;
typedef detail::ebo_functor_holder
<typename get_prio_type::type> prio_base;
@@ -126,14 +126,11 @@ class treap_impl
static const bool stateful_value_traits = implementation_defined::stateful_value_traits;
static const bool safemode_or_autounlink = is_safe_autounlink<value_traits::link_mode>::value;
- typedef detail::key_nodeptr_comp<priority_compare, value_traits> value_node_prio_comp_t;
+ typedef detail::key_nodeptr_comp<priority_compare, value_traits, key_of_value> key_node_prio_comp_t;
template<class KeyPrioComp>
- detail::key_nodeptr_comp<KeyPrioComp, value_traits> key_node_prio_comp(KeyPrioComp keypriocomp) const
- { return detail::key_nodeptr_comp<KeyPrioComp, value_traits>(keypriocomp, &this->get_value_traits()); }
-
- value_node_prio_comp_t value_node_prio_comp() const
- { return this->key_node_prio_comp(this->priv_pcomp()); }
+ detail::key_nodeptr_comp<KeyPrioComp, value_traits, key_of_value> key_node_prio_comp(KeyPrioComp keypriocomp) const
+ { return detail::key_nodeptr_comp<KeyPrioComp, value_traits, key_of_value>(keypriocomp, &this->get_value_traits()); }
/// @cond
private:
@@ -159,7 +156,18 @@ class treap_impl
//! <b>Throws</b>: If value_traits::node_traits::node
//! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
//! or the copy constructor of the value_compare/priority_compare objects throw. Basic guarantee.
- explicit treap_impl( const key_compare &cmp = key_compare()
+ treap_impl()
+ : tree_type(), prio_base(priority_compare())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container.
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Throws</b>: If value_traits::node_traits::node
+ //! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
+ //! or the copy constructor of the value_compare/priority_compare objects throw. Basic guarantee.
+ explicit treap_impl( const key_compare &cmp
, const priority_compare &pcmp = priority_compare()
, const value_traits &v_traits = value_traits())
: tree_type(cmp, v_traits), prio_base(pcmp)
@@ -403,7 +411,7 @@ class treap_impl
( this->tree_type::header_ptr()
, to_insert
, this->key_node_comp(this->key_comp())
- , this->value_node_prio_comp())
+ , this->key_node_prio_comp(this->priv_pcomp()))
, this->priv_value_traits_ptr());
this->tree_type::sz_traits().increment();
return ret;
@@ -433,7 +441,7 @@ class treap_impl
, hint.pointed_node()
, to_insert
, this->key_node_comp(this->key_comp())
- , this->value_node_prio_comp())
+ , this->key_node_prio_comp(this->priv_pcomp()))
, this->priv_value_traits_ptr());
this->tree_type::sz_traits().increment();
return ret;
@@ -478,8 +486,7 @@ class treap_impl
std::pair<iterator, bool> insert_unique(reference value)
{
insert_commit_data commit_data;
- std::pair<iterator, bool> ret = this->insert_unique_check
- (value, this->comp(), this->priv_pcomp(), commit_data);
+ std::pair<iterator, bool> ret = this->insert_unique_check(key_of_value()(value), commit_data);
if(!ret.second)
return ret;
return std::pair<iterator, bool> (this->insert_unique_commit(value, commit_data), true);
@@ -503,8 +510,7 @@ class treap_impl
iterator insert_unique(const_iterator hint, reference value)
{
insert_commit_data commit_data;
- std::pair<iterator, bool> ret = this->insert_unique_check
- (hint, value, this->comp(), this->priv_pcomp(), commit_data);
+ std::pair<iterator, bool> ret = this->insert_unique_check(hint, key_of_value()(value), commit_data);
if(!ret.second)
return ret.first;
return this->insert_unique_commit(value, commit_data);
@@ -538,6 +544,68 @@ class treap_impl
}
}
+ //! <b>Effects</b>: Checks if a value can be inserted in the container, using
+ //! a user provided key instead of the value itself.
+ //!
+ //! <b>Returns</b>: If there is an equivalent value
+ //! returns a pair containing an iterator to the already present value
+ //! and false. If the value can be inserted returns true in the returned
+ //! pair boolean and fills "commit_data" that is meant to be used with
+ //! the "insert_commit" function.
+ //!
+ //! <b>Complexity</b>: Average complexity is at most logarithmic.
+ //!
+ //! <b>Throws</b>: If the comparison or predicate functions throw. Strong guarantee.
+ //!
+ //! <b>Notes</b>: This function is used to improve performance when constructing
+ //! a value_type is expensive: if there is an equivalent value
+ //! the constructed object must be discarded. Many times, the part of the
+ //! node that is used to impose the order is much cheaper to construct
+ //! than the value_type and this function offers the possibility to use that
+ //! part to check if the insertion will be successful.
+ //!
+ //! If the check is successful, the user can construct the value_type and use
+ //! "insert_commit" to insert the object in constant-time. This gives a total
+ //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)).
+ //!
+ //! "commit_data" remains valid for a subsequent "insert_commit" only if no more
+ //! objects are inserted or erased from the container.
+ std::pair<iterator, bool> insert_unique_check
+ ( const key_type &key, insert_commit_data &commit_data)
+ { return this->insert_unique_check(key, this->key_comp(), this->priv_pcomp(), commit_data); }
+
+ //! <b>Effects</b>: Checks if a value can be inserted in the container, using
+ //! a user provided key instead of the value itself, using "hint"
+ //! as a hint to where it will be inserted.
+ //!
+ //! <b>Returns</b>: If there is an equivalent value
+ //! returns a pair containing an iterator to the already present value
+ //! and false. If the value can be inserted returns true in the returned
+ //! pair boolean and fills "commit_data" that is meant to be used with
+ //! the "insert_commit" function.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but it's amortized
+ //! constant time if t is inserted immediately before hint.
+ //!
+ //! <b>Throws</b>: If the comparison or predicate functions throw. Strong guarantee.
+ //!
+ //! <b>Notes</b>: This function is used to improve performance when constructing
+ //! a value_type is expensive: if there is an equivalent value
+ //! the constructed object must be discarded. Many times, the part of the
+ //! constructing that is used to impose the order is much cheaper to construct
+ //! than the value_type and this function offers the possibility to use that key
+ //! to check if the insertion will be successful.
+ //!
+ //! If the check is successful, the user can construct the value_type and use
+ //! "insert_commit" to insert the object in constant-time. This can give a total
+ //! constant-time complexity to the insertion: check(O(1)) + commit(O(1)).
+ //!
+ //! "commit_data" remains valid for a subsequent "insert_commit" only if no more
+ //! objects are inserted or erased from the container.
+ std::pair<iterator, bool> insert_unique_check
+ ( const_iterator hint, const key_type &key, insert_commit_data &commit_data)
+ { return this->insert_unique_check(hint, key, this->key_comp(), this->priv_pcomp(), commit_data); }
+
//! <b>Requires</b>: comp must be a comparison function that induces
//! the same strict weak ordering as key_compare.
//! key_value_pcomp must be a comparison function that induces
@@ -572,7 +640,11 @@ class treap_impl
//! "commit_data" remains valid for a subsequent "insert_commit" only if no more
//! objects are inserted or erased from the container.
template<class KeyType, class KeyTypeKeyCompare, class KeyValuePrioCompare>
- std::pair<iterator, bool> insert_unique_check
+ BOOST_INTRUSIVE_DOC1ST(std::pair<iterator BOOST_INTRUSIVE_I bool>
+ , typename detail::disable_if_convertible
+ <KeyType BOOST_INTRUSIVE_I const_iterator BOOST_INTRUSIVE_I
+ std::pair<iterator BOOST_INTRUSIVE_I bool> >::type)
+ insert_unique_check
( const KeyType &key, KeyTypeKeyCompare comp
, KeyValuePrioCompare key_value_pcomp, insert_commit_data &commit_data)
{
@@ -678,7 +750,11 @@ class treap_impl
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::unique(to_insert));
iterator ret
( node_algorithms::insert_before
- ( this->tree_type::header_ptr(), pos.pointed_node(), to_insert, this->value_node_prio_comp())
+ ( this->tree_type::header_ptr()
+ , pos.pointed_node()
+ , to_insert
+ , this->key_node_prio_comp(this->priv_pcomp())
+ )
, this->priv_value_traits_ptr());
this->tree_type::sz_traits().increment();
return ret;
@@ -702,7 +778,8 @@ class treap_impl
{
node_ptr to_insert(this->get_value_traits().to_node_ptr(value));
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::unique(to_insert));
- node_algorithms::push_back(this->tree_type::header_ptr(), to_insert, this->value_node_prio_comp());
+ node_algorithms::push_back
+ (this->tree_type::header_ptr(), to_insert, this->key_node_prio_comp(this->priv_pcomp()));
this->tree_type::sz_traits().increment();
}
@@ -724,7 +801,8 @@ class treap_impl
{
node_ptr to_insert(this->get_value_traits().to_node_ptr(value));
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || node_algorithms::unique(to_insert));
- node_algorithms::push_front(this->tree_type::header_ptr(), to_insert, this->value_node_prio_comp());
+ node_algorithms::push_front
+ (this->tree_type::header_ptr(), to_insert, this->key_node_prio_comp(this->priv_pcomp()));
this->tree_type::sz_traits().increment();
}
@@ -742,7 +820,8 @@ class treap_impl
++ret;
node_ptr to_erase(i.pointed_node());
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!safemode_or_autounlink || !node_algorithms::unique(to_erase));
- node_algorithms::erase(this->tree_type::header_ptr(), to_erase, this->value_node_prio_comp());
+ node_algorithms::erase
+ (this->tree_type::header_ptr(), to_erase, this->key_node_prio_comp(this->priv_pcomp()));
this->tree_type::sz_traits().decrement();
if(safemode_or_autounlink)
node_algorithms::init(to_erase);
@@ -922,8 +1001,10 @@ class treap_impl
template <class ExtraChecker>
void check(ExtraChecker extra_checker) const
{
+ typedef detail::key_nodeptr_comp<priority_compare, value_traits, key_of_value> nodeptr_prio_comp_t;
tree_type::check(detail::treap_node_extra_checker
- <ValueTraits, value_node_prio_comp_t, ExtraChecker>(this->value_node_prio_comp(), extra_checker));
+ <ValueTraits, nodeptr_prio_comp_t, ExtraChecker>
+ (this->key_node_prio_comp(this->priv_pcomp()), extra_checker));
}
//! @copydoc ::boost::intrusive::bstree::check()const
@@ -1147,8 +1228,11 @@ class treap
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
+ treap()
+ : Base()
+ {}
- explicit treap( const key_compare &cmp = key_compare()
+ explicit treap( const key_compare &cmp
, const priority_compare &pcmp = priority_compare()
, const value_traits &v_traits = value_traits())
: Base(cmp, pcmp, v_traits)
diff --git a/boost/intrusive/treap_set.hpp b/boost/intrusive/treap_set.hpp
index 60cf449147..f97b3760c2 100644
--- a/boost/intrusive/treap_set.hpp
+++ b/boost/intrusive/treap_set.hpp
@@ -83,31 +83,19 @@ class treap_set_impl
static const bool constant_time_size = implementation_defined::constant_time_size;
public:
- //! <b>Effects</b>: Constructs an empty treap_set.
- //!
- //! <b>Complexity</b>: Constant.
- //!
- //! <b>Throws</b>: If value_traits::node_traits::node
- //! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
- //! or the copy constructor of the key_compare object throws.
- explicit treap_set_impl( const key_compare &cmp = key_compare()
+ //! @copydoc ::boost::intrusive::treap::treap()
+ treap_set_impl()
+ : tree_type()
+ {}
+
+ //! @copydoc ::boost::intrusive::treap::treap(const key_compare &,const priority_compare &,const value_traits &)
+ explicit treap_set_impl( const key_compare &cmp
, const priority_compare &pcmp = priority_compare()
, const value_traits &v_traits = value_traits())
: tree_type(cmp, pcmp, v_traits)
{}
- //! <b>Requires</b>: Dereferencing iterator must yield an lvalue of type value_type.
- //! cmp must be a comparison function that induces a strict weak ordering.
- //!
- //! <b>Effects</b>: Constructs an empty treap_set and inserts elements from
- //! [b, e).
- //!
- //! <b>Complexity</b>: Linear in N if [b, e) is already sorted using
- //! comp and otherwise N * log N, where N is distance(last, first).
- //!
- //! <b>Throws</b>: If value_traits::node_traits::node
- //! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
- //! or the copy constructor/operator() of the key_compare object throws.
+ //! @copydoc ::boost::intrusive::treap::treap(bool,Iterator,Iterator,const key_compare &,const priority_compare &,const value_traits &)
template<class Iterator>
treap_set_impl( Iterator b, Iterator e
, const key_compare &cmp = key_compare()
@@ -241,6 +229,15 @@ class treap_set_impl
iterator insert(const_iterator hint, reference value)
{ return tree_type::insert_unique(hint, value); }
+ //! @copydoc ::boost::intrusive::treap::insert_unique_check(const key_type,insert_commit_data&)
+ std::pair<iterator, bool> insert_check( const key_type &key, insert_commit_data &commit_data)
+ { return tree_type::insert_unique_check(key, commit_data); }
+
+ //! @copydoc ::boost::intrusive::treap::insert_unique_check(const_iterator,const key_type&,insert_commit_data&)
+ std::pair<iterator, bool> insert_check
+ ( const_iterator hint, const key_type &key, insert_commit_data &commit_data)
+ { return tree_type::insert_unique_check(hint, key, commit_data); }
+
//! @copydoc ::boost::intrusive::treap::insert_unique_check(const KeyType&,KeyTypeKeyCompare,KeyValuePrioCompare,insert_commit_data&)
template<class KeyType, class KeyTypeKeyCompare, class KeyValuePrioCompare>
std::pair<iterator, bool> insert_check
@@ -368,21 +365,21 @@ class treap_set_impl
#endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
- //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &)
+ //! @copydoc ::boost::intrusive::treap::equal_range(const key_type &)
std::pair<iterator,iterator> equal_range(const key_type &key)
{ return this->tree_type::lower_bound_range(key); }
- //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyTypeKeyCompare)
+ //! @copydoc ::boost::intrusive::treap::equal_range(const KeyType&,KeyTypeKeyCompare)
template<class KeyType, class KeyTypeKeyCompare>
std::pair<iterator,iterator> equal_range(const KeyType& key, KeyTypeKeyCompare comp)
{ return this->tree_type::equal_range(key, comp); }
- //! @copydoc ::boost::intrusive::rbtree::equal_range(const key_type &)const
+ //! @copydoc ::boost::intrusive::treap::equal_range(const key_type &)const
std::pair<const_iterator, const_iterator>
equal_range(const key_type &key) const
{ return this->tree_type::lower_bound_range(key); }
- //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyTypeKeyCompare)const
+ //! @copydoc ::boost::intrusive::treap::equal_range(const KeyType&,KeyTypeKeyCompare)const
template<class KeyType, class KeyTypeKeyCompare>
std::pair<const_iterator, const_iterator>
equal_range(const KeyType& key, KeyTypeKeyCompare comp) const
@@ -508,7 +505,11 @@ class treap_set
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
- explicit treap_set( const key_compare &cmp = key_compare()
+ treap_set()
+ : Base()
+ {}
+
+ explicit treap_set( const key_compare &cmp
, const priority_compare &pcmp = priority_compare()
, const value_traits &v_traits = value_traits())
: Base(cmp, pcmp, v_traits)
@@ -608,31 +609,20 @@ class treap_multiset_impl
static const bool constant_time_size = implementation_defined::constant_time_size;
public:
- //! <b>Effects</b>: Constructs an empty treap_multiset.
- //!
- //! <b>Complexity</b>: Constant.
- //!
- //! <b>Throws</b>: If value_traits::node_traits::node
- //! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
- //! or the copy constructor of the key_compare object throws.
- explicit treap_multiset_impl( const key_compare &cmp = key_compare()
+
+ //! @copydoc ::boost::intrusive::treap::treap()
+ treap_multiset_impl()
+ : tree_type()
+ {}
+
+ //! @copydoc ::boost::intrusive::treap::treap(const key_compare &,const priority_compare &,const value_traits &)
+ explicit treap_multiset_impl( const key_compare &cmp
, const priority_compare &pcmp = priority_compare()
, const value_traits &v_traits = value_traits())
: tree_type(cmp, pcmp, v_traits)
{}
- //! <b>Requires</b>: Dereferencing iterator must yield an lvalue of type value_type.
- //! cmp must be a comparison function that induces a strict weak ordering.
- //!
- //! <b>Effects</b>: Constructs an empty treap_multiset and inserts elements from
- //! [b, e).
- //!
- //! <b>Complexity</b>: Linear in N if [b, e) is already sorted using
- //! comp and otherwise N * log N, where N is distance(last, first).
- //!
- //! <b>Throws</b>: If value_traits::node_traits::node
- //! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
- //! or the copy constructor/operator() of the key_compare object throws.
+ //! @copydoc ::boost::intrusive::treap::treap(bool,Iterator,Iterator,const key_compare &,const priority_compare &,const value_traits &)
template<class Iterator>
treap_multiset_impl( Iterator b, Iterator e
, const key_compare &cmp = key_compare()
@@ -1000,7 +990,11 @@ class treap_multiset
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
- explicit treap_multiset( const key_compare &cmp = key_compare()
+ treap_multiset()
+ : Base()
+ {}
+
+ explicit treap_multiset( const key_compare &cmp
, const priority_compare &pcmp = priority_compare()
, const value_traits &v_traits = value_traits())
: Base(cmp, pcmp, v_traits)
diff --git a/boost/intrusive/trivial_value_traits.hpp b/boost/intrusive/trivial_value_traits.hpp
index 03deb162d6..84fac665d1 100644
--- a/boost/intrusive/trivial_value_traits.hpp
+++ b/boost/intrusive/trivial_value_traits.hpp
@@ -14,6 +14,7 @@
#define BOOST_INTRUSIVE_TRIVIAL_VALUE_TRAITS_HPP
#include <boost/intrusive/detail/config_begin.hpp>
+#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/link_mode.hpp>
#include <boost/intrusive/pointer_traits.hpp>
@@ -42,12 +43,12 @@ struct trivial_value_traits
typedef node_ptr pointer;
typedef const_node_ptr const_pointer;
static const link_mode_type link_mode = LinkMode;
- static node_ptr to_node_ptr (value_type &value)
+ BOOST_INTRUSIVE_FORCEINLINE static node_ptr to_node_ptr (value_type &value)
{ return pointer_traits<node_ptr>::pointer_to(value); }
- static const_node_ptr to_node_ptr (const value_type &value)
+ BOOST_INTRUSIVE_FORCEINLINE static const_node_ptr to_node_ptr (const value_type &value)
{ return pointer_traits<const_node_ptr>::pointer_to(value); }
- static const pointer & to_value_ptr(const node_ptr &n) { return n; }
- static const const_pointer &to_value_ptr(const const_node_ptr &n) { return n; }
+ BOOST_INTRUSIVE_FORCEINLINE static const pointer & to_value_ptr(const node_ptr &n) { return n; }
+ BOOST_INTRUSIVE_FORCEINLINE static const const_pointer &to_value_ptr(const const_node_ptr &n) { return n; }
};
} //namespace intrusive
diff --git a/boost/intrusive/unordered_set.hpp b/boost/intrusive/unordered_set.hpp
index 5148f02f8c..1174dff26f 100644
--- a/boost/intrusive/unordered_set.hpp
+++ b/boost/intrusive/unordered_set.hpp
@@ -208,6 +208,10 @@ class unordered_set_impl
void insert(Iterator b, Iterator e)
{ table_type::insert_unique(b, e); }
+ //! @copydoc ::boost::intrusive::hashtable::insert_unique_check(const key_type&,insert_commit_data&)
+ std::pair<iterator, bool> insert_check(const key_type &key, insert_commit_data &commit_data)
+ { return table_type::insert_unique_check(key, commit_data); }
+
//! @copydoc ::boost::intrusive::hashtable::insert_unique_check(const KeyType&,KeyHasher,KeyEqual,insert_commit_data&)
template<class KeyType, class KeyHasher, class KeyEqual>
std::pair<iterator, bool> insert_check
diff --git a/boost/lexical_cast.hpp b/boost/lexical_cast.hpp
index dc3d7e3fb7..3dc21f88a4 100644
--- a/boost/lexical_cast.hpp
+++ b/boost/lexical_cast.hpp
@@ -36,7 +36,7 @@ namespace boost
template <typename Target, typename Source>
inline Target lexical_cast(const Source &arg)
{
- Target result;
+ Target result = Target();
if (!boost::conversion::detail::try_lexical_convert(arg, result)) {
boost::conversion::detail::throw_bad_cast<Source, Target>();
diff --git a/boost/lexical_cast/lexical_cast_old.hpp b/boost/lexical_cast/lexical_cast_old.hpp
index 748960f05c..b48bf1f55c 100644
--- a/boost/lexical_cast/lexical_cast_old.hpp
+++ b/boost/lexical_cast/lexical_cast_old.hpp
@@ -34,7 +34,6 @@
#include <cstdio>
#include <boost/limits.hpp>
#include <boost/mpl/if.hpp>
-#include <boost/type_traits/ice.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/static_assert.hpp>
#include <boost/detail/lcast_precision.hpp>
diff --git a/boost/lexical_cast/try_lexical_convert.hpp b/boost/lexical_cast/try_lexical_convert.hpp
index 1881cdf371..b079fd42ae 100644
--- a/boost/lexical_cast/try_lexical_convert.hpp
+++ b/boost/lexical_cast/try_lexical_convert.hpp
@@ -1,6 +1,6 @@
// Copyright Kevlin Henney, 2000-2005.
// Copyright Alexander Nasonov, 2006-2010.
-// Copyright Antony Polukhin, 2011-2014.
+// Copyright Antony Polukhin, 2011-2016.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -57,8 +57,15 @@ namespace boost {
: boost::true_type
{};
+ // Sun Studio has problem with partial specialization of templates differing only in namespace.
+ // We workaround that by making `is_booststring` trait, instead of specializing `is_stdstring` for `boost::container::basic_string`.
+ template<typename T>
+ struct is_booststring
+ : boost::false_type
+ {};
+
template<typename CharT, typename Traits, typename Alloc>
- struct is_stdstring< boost::container::basic_string<CharT, Traits, Alloc> >
+ struct is_booststring< boost::container::basic_string<CharT, Traits, Alloc> >
: boost::true_type
{};
@@ -111,13 +118,20 @@ namespace boost {
: boost::true_type
{};
+ // Sun Studio has problem with partial specialization of templates differing only in namespace.
+ // We workaround that by making `is_char_array_to_booststring` trait, instead of specializing `is_char_array_to_stdstring` for `boost::container::basic_string`.
+ template<typename Target, typename Source>
+ struct is_char_array_to_booststring
+ : boost::false_type
+ {};
+
template<typename CharT, typename Traits, typename Alloc>
- struct is_char_array_to_stdstring< boost::container::basic_string<CharT, Traits, Alloc>, CharT* >
+ struct is_char_array_to_booststring< boost::container::basic_string<CharT, Traits, Alloc>, CharT* >
: boost::true_type
{};
template<typename CharT, typename Traits, typename Alloc>
- struct is_char_array_to_stdstring< boost::container::basic_string<CharT, Traits, Alloc>, const CharT* >
+ struct is_char_array_to_booststring< boost::container::basic_string<CharT, Traits, Alloc>, const CharT* >
: boost::true_type
{};
@@ -151,9 +165,10 @@ namespace boost {
typedef boost::mpl::bool_<
boost::detail::is_xchar_to_xchar<Target, src >::value ||
boost::detail::is_char_array_to_stdstring<Target, src >::value ||
+ boost::detail::is_char_array_to_booststring<Target, src >::value ||
(
boost::is_same<Target, src >::value &&
- boost::detail::is_stdstring<Target >::value
+ (boost::detail::is_stdstring<Target >::value || boost::detail::is_booststring<Target >::value)
) ||
(
boost::is_same<Target, src >::value &&
diff --git a/boost/lockfree/detail/atomic.hpp b/boost/lockfree/detail/atomic.hpp
index 47dcd8c504..d15474ada9 100644
--- a/boost/lockfree/detail/atomic.hpp
+++ b/boost/lockfree/detail/atomic.hpp
@@ -42,6 +42,12 @@
#endif // BOOST_CLANG
+// Stdlib should also be checked
+#include <boost/config.hpp>
+#if defined(BOOST_NO_CXX11_HDR_ATOMIC) && !defined(BOOST_LOCKFREE_NO_HDR_ATOMIC)
+# define BOOST_LOCKFREE_NO_HDR_ATOMIC
+#endif
+
#endif // BOOST_LOCKFREE_FORCE_STD_ATOMIC
diff --git a/boost/lockfree/detail/freelist.hpp b/boost/lockfree/detail/freelist.hpp
index 6b84e6c974..3a134e29b9 100644
--- a/boost/lockfree/detail/freelist.hpp
+++ b/boost/lockfree/detail/freelist.hpp
@@ -1,6 +1,6 @@
// lock-free freelist
//
-// Copyright (C) 2008-2013 Tim Blechmann
+// Copyright (C) 2008-2016 Tim Blechmann
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -18,6 +18,9 @@
#include <boost/noncopyable.hpp>
#include <boost/static_assert.hpp>
+#include <boost/align/align_up.hpp>
+#include <boost/align/aligned_allocator_adaptor.hpp>
+
#include <boost/lockfree/detail/atomic.hpp>
#include <boost/lockfree/detail/parameter.hpp>
#include <boost/lockfree/detail/tagged_ptr.hpp>
@@ -328,7 +331,7 @@ struct compiletime_sized_freelist_storage
// array-based freelists only support a 16bit address space.
BOOST_STATIC_ASSERT(size < 65536);
- boost::array<char, size * sizeof(T)> data;
+ boost::array<char, size * sizeof(T) + 64> data;
// unused ... only for API purposes
template <typename Allocator>
@@ -337,7 +340,8 @@ struct compiletime_sized_freelist_storage
T * nodes(void) const
{
- return reinterpret_cast<T*>(const_cast<char*>(data.data()));
+ char * data_pointer = const_cast<char*>(data.data());
+ return reinterpret_cast<T*>( boost::alignment::align_up( data_pointer, BOOST_LOCKFREE_CACHELINE_BYTES ) );
}
std::size_t node_count(void) const
@@ -349,23 +353,24 @@ struct compiletime_sized_freelist_storage
template <typename T,
typename Alloc = std::allocator<T> >
struct runtime_sized_freelist_storage:
- Alloc
+ boost::alignment::aligned_allocator_adaptor<Alloc, BOOST_LOCKFREE_CACHELINE_BYTES >
{
+ typedef boost::alignment::aligned_allocator_adaptor<Alloc, BOOST_LOCKFREE_CACHELINE_BYTES > allocator_type;
T * nodes_;
std::size_t node_count_;
template <typename Allocator>
runtime_sized_freelist_storage(Allocator const & alloc, std::size_t count):
- Alloc(alloc), node_count_(count)
+ allocator_type(alloc), node_count_(count)
{
if (count > 65535)
boost::throw_exception(std::runtime_error("boost.lockfree: freelist size is limited to a maximum of 65535 objects"));
- nodes_ = Alloc::allocate(count);
+ nodes_ = allocator_type::allocate(count);
}
~runtime_sized_freelist_storage(void)
{
- Alloc::deallocate(nodes_, node_count_);
+ allocator_type::deallocate(nodes_, node_count_);
}
T * nodes(void) const
diff --git a/boost/lockfree/spsc_queue.hpp b/boost/lockfree/spsc_queue.hpp
index b877cde4db..5ecfb2a21e 100644
--- a/boost/lockfree/spsc_queue.hpp
+++ b/boost/lockfree/spsc_queue.hpp
@@ -601,28 +601,28 @@ public:
template <typename ConstIterator>
ConstIterator push(ConstIterator begin, ConstIterator end)
{
- return ringbuffer_base<T>::push(begin, end, array_, max_elements_);
+ return ringbuffer_base<T>::push(begin, end, &*array_, max_elements_);
}
size_type pop(T * ret, size_type size)
{
- return ringbuffer_base<T>::pop(ret, size, array_, max_elements_);
+ return ringbuffer_base<T>::pop(ret, size, &*array_, max_elements_);
}
template <typename OutputIterator>
size_type pop_to_output_iterator(OutputIterator it)
{
- return ringbuffer_base<T>::pop_to_output_iterator(it, array_, max_elements_);
+ return ringbuffer_base<T>::pop_to_output_iterator(it, &*array_, max_elements_);
}
const T& front(void) const
{
- return ringbuffer_base<T>::front(array_);
+ return ringbuffer_base<T>::front(&*array_);
}
T& front(void)
{
- return ringbuffer_base<T>::front(array_);
+ return ringbuffer_base<T>::front(&*array_);
}
};
diff --git a/boost/log/attributes/attribute_value_impl.hpp b/boost/log/attributes/attribute_value_impl.hpp
index 50ba812271..b21091e58b 100644
--- a/boost/log/attributes/attribute_value_impl.hpp
+++ b/boost/log/attributes/attribute_value_impl.hpp
@@ -64,7 +64,7 @@ public:
/*!
* Constructor with initialization of the stored value
*/
- explicit attribute_value_impl(BOOST_RV_REF(value_type) v) : m_value(v) {}
+ explicit attribute_value_impl(BOOST_RV_REF(value_type) v) : m_value(boost::move(v)) {}
/*!
* Attribute value dispatching method.
diff --git a/boost/log/detail/config.hpp b/boost/log/detail/config.hpp
index 5ddfd403b6..ce9aeb2dc1 100644
--- a/boost/log/detail/config.hpp
+++ b/boost/log/detail/config.hpp
@@ -23,6 +23,13 @@
#define __MSVCRT_VERSION__ 0x0700
#endif
+#include <boost/predef/os.h>
+
+// Try including WinAPI config as soon as possible so that any other headers don't include Windows SDK headers
+#if defined(BOOST_OS_WINDOWS_AVAILABLE)
+#include <boost/detail/winapi/config.hpp>
+#endif
+
#include <limits.h> // To bring in libc macros
#include <boost/config.hpp>
@@ -31,10 +38,6 @@
# error Boost.Log: RTTI is required by the library
#endif
-#if defined(BOOST_WINDOWS)
-#include <boost/detail/winapi/config.hpp>
-#endif
-
#if defined(_MSC_VER) && _MSC_VER >= 1600
# define BOOST_LOG_HAS_PRAGMA_DETECT_MISMATCH
#endif
@@ -178,6 +181,13 @@
# define BOOST_LOG_NORETURN
#endif
+// GCC and compatible compilers may require marking types that may alias other types
+#if defined(__GNUC__)
+# define BOOST_LOG_MAY_ALIAS __attribute__ ((__may_alias__))
+#else
+# define BOOST_LOG_MAY_ALIAS
+#endif
+
#if !defined(BOOST_LOG_BUILDING_THE_LIB)
// Detect if we're dealing with dll
diff --git a/boost/log/detail/light_rw_mutex.hpp b/boost/log/detail/light_rw_mutex.hpp
index 1ecf700047..39762b3ed2 100644
--- a/boost/log/detail/light_rw_mutex.hpp
+++ b/boost/log/detail/light_rw_mutex.hpp
@@ -145,7 +145,7 @@ namespace aux {
//! A light read/write mutex
class light_rw_mutex
{
- struct { void* p; } m_Mutex;
+ struct BOOST_LOG_MAY_ALIAS mutex_state { void* p; } m_Mutex;
public:
BOOST_LOG_API light_rw_mutex();
diff --git a/boost/log/detail/threadsafe_queue.hpp b/boost/log/detail/threadsafe_queue.hpp
index b94fa4fe8e..2ab2172b13 100644
--- a/boost/log/detail/threadsafe_queue.hpp
+++ b/boost/log/detail/threadsafe_queue.hpp
@@ -43,12 +43,7 @@ namespace aux {
//! Base class for the thread-safe queue implementation
struct threadsafe_queue_impl
{
- struct
-#if defined(__GNUC__)
- // Explicitly mark the type so that it may alias other types
- __attribute__ ((__may_alias__))
-#endif
- pointer_storage
+ struct BOOST_LOG_MAY_ALIAS pointer_storage
{
union
{
diff --git a/boost/log/detail/timestamp.hpp b/boost/log/detail/timestamp.hpp
index 3f55ac238e..95c1f0a945 100644
--- a/boost/log/detail/timestamp.hpp
+++ b/boost/log/detail/timestamp.hpp
@@ -18,6 +18,9 @@
#include <boost/cstdint.hpp>
#include <boost/log/detail/config.hpp>
+#if defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#include <boost/detail/winapi/basic_types.hpp>
+#endif
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
@@ -73,7 +76,7 @@ public:
*/
#if defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-typedef uint64_t (__stdcall* get_tick_count_t)();
+typedef uint64_t (WINAPI* get_tick_count_t)();
extern BOOST_LOG_API get_tick_count_t get_tick_count;
inline timestamp get_timestamp()
diff --git a/boost/log/expressions/formatter.hpp b/boost/log/expressions/formatter.hpp
index 5dc6a5b132..bdbabb504e 100644
--- a/boost/log/expressions/formatter.hpp
+++ b/boost/log/expressions/formatter.hpp
@@ -128,6 +128,16 @@ public:
strm << static_cast< T&& >(val);
return strm;
}
+#if defined(BOOST_MSVC) && BOOST_MSVC < 1800
+ // MSVC 10 and 11 generate broken code for the perfect forwarding version above if T is an array type (e.g. a string literal)
+ template< typename T, unsigned int N >
+ BOOST_FORCEINLINE StreamT& operator<< (T (&val)[N]) const
+ {
+ StreamT& strm = this->get();
+ strm << val;
+ return strm;
+ }
+#endif
#else
template< typename T >
BOOST_FORCEINLINE StreamT& operator<< (T& val) const
@@ -364,13 +374,13 @@ public:
basic_formatter(FunT&& fun) : m_Formatter(boost::forward< FunT >(fun))
{
}
-#elif !defined(BOOST_MSVC) || BOOST_MSVC > 1400
+#elif !defined(BOOST_MSVC) || BOOST_MSVC >= 1600
template< typename FunT >
basic_formatter(FunT const& fun, typename disable_if_c< move_detail::is_rv< FunT >::value, int >::type = 0) : m_Formatter(fun)
{
}
#else
- // MSVC 8 blows up in unexpected ways if we use SFINAE to disable constructor instantiation
+ // MSVC 9 blows up in unexpected ways if we use SFINAE to disable constructor instantiation
template< typename FunT >
basic_formatter(FunT const& fun) : m_Formatter(fun)
{
diff --git a/boost/log/keywords/max_files.hpp b/boost/log/keywords/max_files.hpp
new file mode 100644
index 0000000000..5d898e31e8
--- /dev/null
+++ b/boost/log/keywords/max_files.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2015.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file keywords/max_files.hpp
+ * \author Erich Keane
+ * \date 29.12.2015
+ *
+ * The header contains the \c max_files keyword declaration.
+ */
+
+#ifndef BOOST_LOG_KEYWORDS_MAX_FILES_HPP_INCLUDED_
+#define BOOST_LOG_KEYWORDS_MAX_FILES_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 allows to specify maximum total number of log files
+BOOST_PARAMETER_KEYWORD(tag, max_files)
+
+} // namespace keywords
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#endif // BOOST_LOG_KEYWORDS_MAX_FILES_HPP_INCLUDED_
diff --git a/boost/log/sinks/text_file_backend.hpp b/boost/log/sinks/text_file_backend.hpp
index 7fe6df80ad..68f698848f 100644
--- a/boost/log/sinks/text_file_backend.hpp
+++ b/boost/log/sinks/text_file_backend.hpp
@@ -27,6 +27,7 @@
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/log/keywords/max_size.hpp>
+#include <boost/log/keywords/max_files.hpp>
#include <boost/log/keywords/min_free_space.hpp>
#include <boost/log/keywords/target.hpp>
#include <boost/log/keywords/file_name.hpp>
@@ -129,7 +130,8 @@ namespace aux {
BOOST_LOG_API shared_ptr< collector > make_collector(
filesystem::path const& target_dir,
uintmax_t max_size,
- uintmax_t min_free_space
+ uintmax_t min_free_space,
+ uintmax_t max_files = (std::numeric_limits< uintmax_t >::max)()
);
template< typename ArgsT >
inline shared_ptr< collector > make_collector(ArgsT const& args)
@@ -137,7 +139,8 @@ namespace aux {
return aux::make_collector(
filesystem::path(args[keywords::target]),
args[keywords::max_size | (std::numeric_limits< uintmax_t >::max)()],
- args[keywords::min_free_space | static_cast< uintmax_t >(0)]);
+ args[keywords::min_free_space | static_cast< uintmax_t >(0)],
+ args[keywords::max_files | (std::numeric_limits< uintmax_t >::max)()]);
}
} // namespace aux
@@ -159,6 +162,11 @@ inline shared_ptr< collector > make_collector(T1 const& a1, T2 const& a2, T3 con
{
return aux::make_collector((a1, a2, a3));
}
+template< typename T1, typename T2, typename T3, typename T4 >
+inline shared_ptr< collector > make_collector(T1 const& a1, T2 const& a2, T3 const& a3, T4 const& a4)
+{
+ return aux::make_collector((a1, a2, a3, a4));
+}
#else
@@ -190,6 +198,9 @@ inline shared_ptr< collector > make_collector(T1 const& a1, T2 const& a2, T3 con
* the collector tries to maintain. If the threshold is exceeded, the oldest
* file(s) is deleted to free space. The threshold is not maintained, if not
* specified.
+ * \li \c max_files - Specifies the maximum number of log files stored. If the number of files exceeds
+ * this threshold, the oldest file(s) is deleted to free space. The threshhold is
+ * not maintained if not specified.
*
* \return The file collector.
*/
diff --git a/boost/log/utility/formatting_ostream.hpp b/boost/log/utility/formatting_ostream.hpp
index 4d57ac4e32..d3732d36f4 100644
--- a/boost/log/utility/formatting_ostream.hpp
+++ b/boost/log/utility/formatting_ostream.hpp
@@ -21,6 +21,7 @@
#include <locale>
#include <boost/core/explicit_operator_bool.hpp>
#include <boost/utility/string_ref_fwd.hpp>
+#include <boost/utility/string_view_fwd.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/attachable_sstream_buf.hpp>
@@ -404,7 +405,7 @@ public:
}
// When no native character type is supported, the following overloads are disabled as they have ambiguous meaning.
- // Use basic_string_ref, basic_string_view or basic_string to explicitly indicate that the data is a string.
+ // Use basic_string_view or basic_string to explicitly indicate that the data is a string.
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
basic_formatting_ostream& operator<< (wchar_t c)
{
@@ -540,6 +541,14 @@ public:
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_view< OtherCharT, OtherTraitsT > const& str)
+ {
+ return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
+ }
+
+ // Deprecated overload
+ 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_ref< OtherCharT, OtherTraitsT > const& str)
{
return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
@@ -561,6 +570,14 @@ public:
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_view< OtherCharT, OtherTraitsT >& str)
+ {
+ return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
+ }
+
+ // Deprecated overload
+ 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_ref< OtherCharT, OtherTraitsT >& str)
{
return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
@@ -583,6 +600,14 @@ public:
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_view< OtherCharT, OtherTraitsT > const& str)
+ {
+ return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
+ }
+
+ // Deprecated overload
+ 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_ref< OtherCharT, OtherTraitsT > const& str)
{
return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
@@ -604,6 +629,14 @@ public:
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_view< OtherCharT, OtherTraitsT >& str)
+ {
+ return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
+ }
+
+ // Deprecated overload
+ 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_ref< OtherCharT, OtherTraitsT >& str)
{
return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
diff --git a/boost/log/utility/once_block.hpp b/boost/log/utility/once_block.hpp
index 99bb5db082..40f2fff8c1 100644
--- a/boost/log/utility/once_block.hpp
+++ b/boost/log/utility/once_block.hpp
@@ -82,7 +82,7 @@ public:
~once_block_sentry() BOOST_NOEXCEPT
{
- if (m_flag.status != once_block_flag::initialized)
+ if (BOOST_UNLIKELY(m_flag.status != once_block_flag::initialized))
rollback();
}
diff --git a/boost/log/utility/setup/file.hpp b/boost/log/utility/setup/file.hpp
index 89c30c4607..e1b4280e9c 100644
--- a/boost/log/utility/setup/file.hpp
+++ b/boost/log/utility/setup/file.hpp
@@ -143,6 +143,7 @@ BOOST_PP_REPEAT_FROM_TO(1, BOOST_LOG_MAX_PARAMETER_ARGS, BOOST_LOG_INIT_LOG_TO_F
* \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>.
+ * \li \c max_files The maximum total number of rotated files in the target directory. See <tt>sinks::file::make_collector</tt>.
* \li \c scan_method The method of scanning the target directory for log files. See <tt>sinks::file::scan_method</tt>.
* \li \c filter Specifies a filter to install into the sink. May be a string that represents a filter,
* or a filter lambda expression.
diff --git a/boost/make_unique.hpp b/boost/make_unique.hpp
index c163673c6d..4dc82c3c7a 100644
--- a/boost/make_unique.hpp
+++ b/boost/make_unique.hpp
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2014 Glen Joseph Fernandes
- * glenfe at live dot com
- *
- * Distributed under the Boost Software License,
- * Version 1.0. (See accompanying file LICENSE_1_0.txt
- * or copy at http://boost.org/LICENSE_1_0.txt)
- */
+(c) 2014 Glen Joseph Fernandes
+<glenjofe -at- gmail.com>
+
+Distributed under the Boost Software
+License, Version 1.0.
+http://boost.org/LICENSE_1_0.txt
+*/
#ifndef BOOST_MAKE_UNIQUE_HPP_INCLUDED
#define BOOST_MAKE_UNIQUE_HPP_INCLUDED
diff --git a/boost/math/bindings/mpfr.hpp b/boost/math/bindings/mpfr.hpp
index 5edc0ae44c..4e4ebcfe53 100644
--- a/boost/math/bindings/mpfr.hpp
+++ b/boost/math/bindings/mpfr.hpp
@@ -297,7 +297,7 @@ struct promote_arg<__gmp_expr<T,U> >
};
template<>
-inline int digits<mpfr_class>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr_class))
+inline int digits<mpfr_class>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr_class)) BOOST_NOEXCEPT
{
return mpfr_class::get_dprec();
}
diff --git a/boost/math/cstdfloat/cstdfloat_complex_std.hpp b/boost/math/cstdfloat/cstdfloat_complex_std.hpp
index f949a9aa46..affd92d2da 100644
--- a/boost/math/cstdfloat/cstdfloat_complex_std.hpp
+++ b/boost/math/cstdfloat/cstdfloat_complex_std.hpp
@@ -201,13 +201,13 @@
};
// Constructors from built-in complex representation of floating-point types.
- complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::complex(const complex<float>& f) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( f.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( f.imag())) { }
- complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::complex(const complex<double>& d) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( d.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( d.imag())) { }
- complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::complex(const complex<long double>& ld) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(ld.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(ld.imag())) { }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::complex(const complex<float>& f) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( f.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( f.imag())) { }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::complex(const complex<double>& d) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( d.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( d.imag())) { }
+ inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::complex(const complex<long double>& ld) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(ld.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(ld.imag())) { }
} // namespace std
namespace boost { namespace math { namespace cstdfloat { namespace detail {
- template<class float_type> std::complex<float_type> multiply_by_i(const std::complex<float_type>& x)
+ template<class float_type> inline std::complex<float_type> multiply_by_i(const std::complex<float_type>& x)
{
// Multiply x (in C) by I (the imaginary component), and return the result.
return std::complex<float_type>(-x.imag(), x.real());
diff --git a/boost/math/special_functions/detail/polygamma.hpp b/boost/math/special_functions/detail/polygamma.hpp
index 0267bd3ac8..20a0292fb4 100644
--- a/boost/math/special_functions/detail/polygamma.hpp
+++ b/boost/math/special_functions/detail/polygamma.hpp
@@ -239,7 +239,7 @@
if(boost::math::tools::max_value<T>() / scale < sum)
return boost::math::policies::raise_overflow_error<T>(function, 0, pol);
sum *= scale;
- return n & 1 ? sum : -sum;
+ return n & 1 ? sum : T(-sum);
}
//
diff --git a/boost/math/special_functions/detail/t_distribution_inv.hpp b/boost/math/special_functions/detail/t_distribution_inv.hpp
index e8bd0db28f..ab5a8fbca6 100644
--- a/boost/math/special_functions/detail/t_distribution_inv.hpp
+++ b/boost/math/special_functions/detail/t_distribution_inv.hpp
@@ -285,7 +285,7 @@ T inverse_students_t(T df, T u, T v, const Policy& pol, bool* pexact = 0)
//
T a = 4 * (u - u * u);//1 - 4 * (u - 0.5f) * (u - 0.5f);
T b = boost::math::cbrt(a);
- static const T c = static_cast<T>(0.85498797333834849467655443627193L);
+ static const T c = static_cast<T>(0.85498797333834849467655443627193);
T p = 6 * (1 + c * (1 / b - 1));
T p0;
do{
diff --git a/boost/math/special_functions/ellint_2.hpp b/boost/math/special_functions/ellint_2.hpp
index 0d160ecdf1..7c1eab45c2 100644
--- a/boost/math/special_functions/ellint_2.hpp
+++ b/boost/math/special_functions/ellint_2.hpp
@@ -74,7 +74,7 @@ T ellint_e_imp(T phi, T k, const Policy& pol)
}
else if(fabs(k) == 1)
{
- return invert ? T(-sin(phi)) : sin(phi);
+ return invert ? T(-sin(phi)) : T(sin(phi));
}
else
{
diff --git a/boost/math/special_functions/ellint_3.hpp b/boost/math/special_functions/ellint_3.hpp
index 9ab0f8317a..b6670a196f 100644
--- a/boost/math/special_functions/ellint_3.hpp
+++ b/boost/math/special_functions/ellint_3.hpp
@@ -133,7 +133,7 @@ T ellint_pi_imp(T v, T phi, T k, T vc, const Policy& pol)
if((m > 0) && (vc > 0))
result += m * ellint_pi_imp(v, k, vc, pol);
}
- return phi < 0 ? -result : result;
+ return phi < 0 ? T(-result) : result;
}
if(k == 0)
{
diff --git a/boost/math/special_functions/fpclassify.hpp b/boost/math/special_functions/fpclassify.hpp
index 0a4e1ac7aa..d83e111c48 100644
--- a/boost/math/special_functions/fpclassify.hpp
+++ b/boost/math/special_functions/fpclassify.hpp
@@ -81,7 +81,12 @@ is used.
#include <float.h>
#endif
#ifdef BOOST_MATH_USE_FLOAT128
+#ifdef __has_include
+#if __has_include("quadmath.h")
#include "quadmath.h"
+#define BOOST_MATH_HAS_QUADMATH_H
+#endif
+#endif
#endif
#ifdef BOOST_NO_STDC_NAMESPACE
@@ -124,9 +129,18 @@ inline bool is_nan_helper(T, const boost::false_type&)
{
return false;
}
-#ifdef BOOST_MATH_USE_FLOAT128
+#if defined(BOOST_MATH_USE_FLOAT128)
+#if defined(BOOST_MATH_HAS_QUADMATH_H)
inline bool is_nan_helper(__float128 f, const boost::true_type&) { return ::isnanq(f); }
inline bool is_nan_helper(__float128 f, const boost::false_type&) { return ::isnanq(f); }
+#elif defined(BOOST_GNU_STDLIB) && BOOST_GNU_STDLIB && \
+ _GLIBCXX_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
+inline bool is_nan_helper(__float128 f, const boost::true_type&) { return std::isnan(static_cast<double>(f)); }
+inline bool is_nan_helper(__float128 f, const boost::false_type&) { return std::isnan(static_cast<double>(f)); }
+#else
+inline bool is_nan_helper(__float128 f, const boost::true_type&) { return ::isnan(static_cast<double>(f)); }
+inline bool is_nan_helper(__float128 f, const boost::false_type&) { return ::isnan(static_cast<double>(f)); }
+#endif
#endif
}
@@ -519,7 +533,7 @@ inline bool (isinf)(long double x)
return detail::isinf_impl(static_cast<value_type>(x), method());
}
#endif
-#ifdef BOOST_MATH_USE_FLOAT128
+#if defined(BOOST_MATH_USE_FLOAT128) && defined(BOOST_MATH_HAS_QUADMATH_H)
template<>
inline bool (isinf)(__float128 x)
{
@@ -611,7 +625,7 @@ inline bool (isnan)(long double x)
return detail::isnan_impl(x, method());
}
#endif
-#ifdef BOOST_MATH_USE_FLOAT128
+#if defined(BOOST_MATH_USE_FLOAT128) && defined(BOOST_MATH_HAS_QUADMATH_H)
template<>
inline bool (isnan)(__float128 x)
{
diff --git a/boost/math/tools/config.hpp b/boost/math/tools/config.hpp
index ffd0ab43a6..75d29b646e 100644
--- a/boost/math/tools/config.hpp
+++ b/boost/math/tools/config.hpp
@@ -265,18 +265,6 @@
# define BOOST_MATH_INT_VALUE_SUFFIX(RV, SUF) RV##SUF
#endif
//
-// Test whether to support __float128, if we don't have quadmath.h then this can't currently work:
-//
-#ifndef BOOST_MATH_USE_FLOAT128
-#ifdef __has_include
-#if ! __has_include("quadmath.h")
-#define BOOST_MATH_DISABLE_FLOAT128
-#endif
-#elif !defined(BOOST_ARCH_X86)
-#define BOOST_MATH_DISABLE_FLOAT128
-#endif
-#endif
-//
// And then the actual configuration:
//
#if defined(_GLIBCXX_USE_FLOAT128) && defined(BOOST_GCC) && !defined(__STRICT_ANSI__) \
diff --git a/boost/math/tools/polynomial.hpp b/boost/math/tools/polynomial.hpp
index 9858880a4d..73980d6aa8 100644
--- a/boost/math/tools/polynomial.hpp
+++ b/boost/math/tools/polynomial.hpp
@@ -1,4 +1,7 @@
// (C) Copyright John Maddock 2006.
+// (C) Copyright Jeremy William Murphy 2015.
+
+
// 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)
@@ -11,13 +14,20 @@
#endif
#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/function.hpp>
+#include <boost/lambda/lambda.hpp>
#include <boost/math/tools/rational.hpp>
#include <boost/math/tools/real_cast.hpp>
#include <boost/math/special_functions/binomial.hpp>
+#include <boost/operators.hpp>
#include <vector>
#include <ostream>
#include <algorithm>
+#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+#include <initializer_list>
+#endif
namespace boost{ namespace math{ namespace tools{
@@ -98,8 +108,157 @@ T evaluate_chebyshev(const Seq& a, const T& x)
return a[0] / 2 + yk * x - yk1;
}
+
+template <typename T>
+class polynomial;
+
+namespace detail {
+
+/**
+* Knuth, The Art of Computer Programming: Volume 2, Third edition, 1998
+* Chapter 4.6.1, Algorithm D: Division of polynomials over a field.
+*
+* @tparam T Coefficient type, must be not be an integer.
+*
+* Template-parameter T actually must be a field but we don't currently have that
+* subtlety of distinction.
+*/
+template <typename T, typename N>
+BOOST_DEDUCED_TYPENAME disable_if_c<std::numeric_limits<T>::is_integer, void >::type
+division_impl(polynomial<T> &q, polynomial<T> &u, const polynomial<T>& v, N n, N k)
+{
+ q[k] = u[n + k] / v[n];
+ for (N j = n + k; j > k;)
+ {
+ j--;
+ u[j] -= q[k] * v[j - k];
+ }
+}
+
+template <class T, class N>
+T integer_power(T t, N n)
+{
+ switch(n)
+ {
+ case 0:
+ return static_cast<T>(1u);
+ case 1:
+ return t;
+ case 2:
+ return t * t;
+ case 3:
+ return t * t * t;
+ }
+ T result = integer_power(t, n / 2);
+ result *= result;
+ if(n & 1)
+ result *= t;
+ return result;
+}
+
+
+/**
+* Knuth, The Art of Computer Programming: Volume 2, Third edition, 1998
+* Chapter 4.6.1, Algorithm R: Pseudo-division of polynomials.
+*
+* @tparam T Coefficient type, must be an integer.
+*
+* Template-parameter T actually must be a unique factorization domain but we
+* don't currently have that subtlety of distinction.
+*/
+template <typename T, typename N>
+BOOST_DEDUCED_TYPENAME enable_if_c<std::numeric_limits<T>::is_integer, void >::type
+division_impl(polynomial<T> &q, polynomial<T> &u, const polynomial<T>& v, N n, N k)
+{
+ q[k] = u[n + k] * integer_power(v[n], k);
+ for (N j = n + k; j > 0;)
+ {
+ j--;
+ u[j] = v[n] * u[j] - (j < k ? T(0) : u[n + k] * v[j - k]);
+ }
+}
+
+
+/**
+ * Knuth, The Art of Computer Programming: Volume 2, Third edition, 1998
+ * Chapter 4.6.1, Algorithm D and R: Main loop.
+ *
+ * @param u Dividend.
+ * @param v Divisor.
+ */
+template <typename T>
+std::pair< polynomial<T>, polynomial<T> >
+division(polynomial<T> u, const polynomial<T>& v)
+{
+ BOOST_ASSERT(v.size() <= u.size());
+ BOOST_ASSERT(v != zero_element(std::multiplies< polynomial<T> >()));
+ BOOST_ASSERT(u != zero_element(std::multiplies< polynomial<T> >()));
+
+ typedef typename polynomial<T>::size_type N;
+
+ N const m = u.size() - 1, n = v.size() - 1;
+ N k = m - n;
+ polynomial<T> q;
+ q.data().resize(m - n + 1);
+
+ do
+ {
+ division_impl(q, u, v, n, k);
+ }
+ while (k-- != 0);
+ u.data().resize(n);
+ u.normalize(); // Occasionally, the remainder is zeroes.
+ return std::make_pair(q, u);
+}
+
template <class T>
-class polynomial
+struct identity
+{
+ T operator()(T const &x) const
+ {
+ return x;
+ }
+};
+
+} // namespace detail
+
+/**
+ * Returns the zero element for multiplication of polynomials.
+ */
+template <class T>
+polynomial<T> zero_element(std::multiplies< polynomial<T> >)
+{
+ return polynomial<T>();
+}
+
+template <class T>
+polynomial<T> identity_element(std::multiplies< polynomial<T> >)
+{
+ return polynomial<T>(T(1));
+}
+
+/* Calculates a / b and a % b, returning the pair (quotient, remainder) together
+ * because the same amount of computation yields both.
+ * This function is not defined for division by zero: user beware.
+ */
+template <typename T>
+std::pair< polynomial<T>, polynomial<T> >
+quotient_remainder(const polynomial<T>& dividend, const polynomial<T>& divisor)
+{
+ BOOST_ASSERT(divisor != zero_element(std::multiplies< polynomial<T> >()));
+ if (dividend.size() < divisor.size())
+ return std::make_pair(zero_element(std::multiplies< polynomial<T> >()), dividend);
+ return detail::division(dividend, divisor);
+}
+
+
+template <class T>
+class polynomial :
+ equality_comparable< polynomial<T>,
+ dividable< polynomial<T>,
+ dividable2< polynomial<T>, T,
+ modable< polynomial<T>,
+ modable2< polynomial<T>, T > > > > >
{
public:
// typedefs:
@@ -108,15 +267,26 @@ public:
// construct:
polynomial(){}
+
template <class U>
polynomial(const U* data, unsigned order)
: m_data(data, data + order + 1)
{
+ normalize();
}
+
+ template <class I>
+ polynomial(I first, I last)
+ : m_data(first, last)
+ {
+ normalize();
+ }
+
template <class U>
- polynomial(const U& point)
+ explicit polynomial(const U& point)
{
- m_data.push_back(point);
+ if (point != U(0))
+ m_data.push_back(point);
}
// copy:
@@ -131,10 +301,29 @@ public:
m_data.push_back(boost::math::tools::real_cast<T>(p[i]));
}
}
+
+#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+ polynomial(std::initializer_list<T> l) : polynomial(std::begin(l), std::end(l))
+ {
+ }
+
+ polynomial&
+ operator=(std::initializer_list<T> l)
+ {
+ m_data.assign(std::begin(l), std::end(l));
+ return *this;
+ }
+#endif
+
// access:
size_type size()const { return m_data.size(); }
- size_type degree()const { return m_data.size() - 1; }
+ size_type degree()const
+ {
+ if (size() == 0)
+ throw std::logic_error("degree() is undefined for the zero polynomial.");
+ return m_data.size() - 1;
+ }
value_type& operator[](size_type i)
{
return m_data[i];
@@ -152,67 +341,88 @@ public:
return polynomial_to_chebyshev(m_data);
}
+ std::vector<T> const& data() const
+ {
+ return m_data;
+ }
+
+ std::vector<T> & data()
+ {
+ return m_data;
+ }
+
// operators:
template <class U>
polynomial& operator +=(const U& value)
{
- if(m_data.size() == 0)
- m_data.push_back(value);
- else
- {
- m_data[0] += value;
- }
- return *this;
+ addition(value);
+ normalize();
+ return *this;
}
+
template <class U>
polynomial& operator -=(const U& value)
{
- if(m_data.size() == 0)
- m_data.push_back(-value);
- else
- {
- m_data[0] -= value;
- }
- return *this;
+ subtraction(value);
+ normalize();
+ return *this;
}
+
template <class U>
polynomial& operator *=(const U& value)
{
- for(size_type i = 0; i < m_data.size(); ++i)
- m_data[i] *= value;
+ multiplication(value);
+ normalize();
return *this;
}
+
+ template <class U>
+ polynomial& operator /=(const U& value)
+ {
+ division(value);
+ normalize();
+ return *this;
+ }
+
+ template <class U>
+ polynomial& operator %=(const U& /*value*/)
+ {
+ // We can always divide by a scalar, so there is no remainder:
+ *this = zero_element(std::multiplies<polynomial>());
+ return *this;
+ }
+
template <class U>
polynomial& operator +=(const polynomial<U>& value)
{
- size_type s1 = (std::min)(m_data.size(), value.size());
- for(size_type i = 0; i < s1; ++i)
- m_data[i] += value[i];
- for(size_type i = s1; i < value.size(); ++i)
- m_data.push_back(value[i]);
+ addition(value);
+ normalize();
return *this;
}
+
template <class U>
polynomial& operator -=(const polynomial<U>& value)
{
- size_type s1 = (std::min)(m_data.size(), value.size());
- for(size_type i = 0; i < s1; ++i)
- m_data[i] -= value[i];
- for(size_type i = s1; i < value.size(); ++i)
- m_data.push_back(-value[i]);
- return *this;
+ subtraction(value);
+ normalize();
+ return *this;
}
template <class U>
polynomial& operator *=(const polynomial<U>& value)
{
// TODO: FIXME: use O(N log(N)) algorithm!!!
- BOOST_ASSERT(value.size());
+ polynomial const zero = zero_element(std::multiplies<polynomial>());
+ if (value == zero)
+ {
+ *this = zero;
+ return *this;
+ }
polynomial base(*this);
- *this *= value[0];
+ this->multiplication(value[0]);
for(size_type i = 1; i < value.size(); ++i)
{
polynomial t(base);
- t *= value[i];
+ t.multiplication(value[i]);
size_type s = size() - i;
for(size_type j = 0; j < s; ++j)
{
@@ -224,10 +434,94 @@ public:
return *this;
}
+ template <typename U>
+ polynomial& operator /=(const polynomial<U>& value)
+ {
+ *this = quotient_remainder(*this, value).first;
+ return *this;
+ }
+
+ template <typename U>
+ polynomial& operator %=(const polynomial<U>& value)
+ {
+ *this = quotient_remainder(*this, value).second;
+ return *this;
+ }
+
+ /** Remove zero coefficients 'from the top', that is for which there are no
+ * non-zero coefficients of higher degree. */
+ void normalize()
+ {
+ using namespace boost::lambda;
+ m_data.erase(std::find_if(m_data.rbegin(), m_data.rend(), _1 != T(0)).base(), m_data.end());
+ }
+
private:
- std::vector<T> m_data;
+ template <class U, class R1, class R2>
+ polynomial& addition(const U& value, R1 sign, R2 op)
+ {
+ if(m_data.size() == 0)
+ m_data.push_back(sign(value));
+ else
+ m_data[0] = op(m_data[0], value);
+ return *this;
+ }
+
+ template <class U>
+ polynomial& addition(const U& value)
+ {
+ return addition(value, detail::identity<U>(), std::plus<U>());
+ }
+
+ template <class U>
+ polynomial& subtraction(const U& value)
+ {
+ return addition(value, std::negate<U>(), std::minus<U>());
+ }
+
+ template <class U, class R1, class R2>
+ polynomial& addition(const polynomial<U>& value, R1 sign, R2 op)
+ {
+ size_type s1 = (std::min)(m_data.size(), value.size());
+ for(size_type i = 0; i < s1; ++i)
+ m_data[i] = op(m_data[i], value[i]);
+ for(size_type i = s1; i < value.size(); ++i)
+ m_data.push_back(sign(value[i]));
+ return *this;
+ }
+
+ template <class U>
+ polynomial& addition(const polynomial<U>& value)
+ {
+ return addition(value, detail::identity<U>(), std::plus<U>());
+ }
+
+ template <class U>
+ polynomial& subtraction(const polynomial<U>& value)
+ {
+ return addition(value, std::negate<U>(), std::minus<U>());
+ }
+
+ template <class U>
+ polynomial& multiplication(const U& value)
+ {
+ using namespace boost::lambda;
+ std::transform(m_data.begin(), m_data.end(), m_data.begin(), ret<T>(_1 * value));
+ return *this;
+ }
+
+ template <class U>
+ polynomial& division(const U& value)
+ {
+ using namespace boost::lambda;
+ std::transform(m_data.begin(), m_data.end(), m_data.begin(), ret<T>(_1 / value));
+ return *this;
+ }
+
+ std::vector<T> m_data;
};
+
template <class T>
inline polynomial<T> operator + (const polynomial<T>& a, const polynomial<T>& b)
{
@@ -300,6 +594,20 @@ inline polynomial<T> operator * (const U& a, const polynomial<T>& b)
return result;
}
+template <class T>
+bool operator == (const polynomial<T> &a, const polynomial<T> &b)
+{
+ return a.data() == b.data();
+}
+
+// Unary minus (negate).
+template <class T>
+polynomial<T> operator - (polynomial<T> a)
+{
+ std::transform(a.data().begin(), a.data().end(), a.data().begin(), std::negate<T>());
+ return a;
+}
+
template <class charT, class traits, class T>
inline std::basic_ostream<charT, traits>& operator << (std::basic_ostream<charT, traits>& os, const polynomial<T>& poly)
{
diff --git a/boost/metaparse.hpp b/boost/metaparse.hpp
new file mode 100644
index 0000000000..4c050cffe9
--- /dev/null
+++ b/boost/metaparse.hpp
@@ -0,0 +1,123 @@
+#ifndef BOOST_METAPARSE_HPP
+#define BOOST_METAPARSE_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/accept.hpp>
+#include <boost/metaparse/accept_tag.hpp>
+#include <boost/metaparse/accept_when.hpp>
+#include <boost/metaparse/alphanum.hpp>
+#include <boost/metaparse/always_c.hpp>
+#include <boost/metaparse/always.hpp>
+#include <boost/metaparse/repeated.hpp>
+#include <boost/metaparse/repeated1.hpp>
+#include <boost/metaparse/repeated_reject_incomplete1.hpp>
+#include <boost/metaparse/repeated_reject_incomplete.hpp>
+#include <boost/metaparse/repeated_one_of1.hpp>
+#include <boost/metaparse/repeated_one_of.hpp>
+#include <boost/metaparse/build_parser.hpp>
+#include <boost/metaparse/change_error_message.hpp>
+#include <boost/metaparse/config.hpp>
+#include <boost/metaparse/debug_parsing_error.hpp>
+#include <boost/metaparse/define_error.hpp>
+#include <boost/metaparse/digit.hpp>
+#include <boost/metaparse/digit_val.hpp>
+#include <boost/metaparse/empty.hpp>
+#include <boost/metaparse/entire_input.hpp>
+#include <boost/metaparse/error/digit_expected.hpp>
+#include <boost/metaparse/error/end_of_input_expected.hpp>
+#include <boost/metaparse/error/index_out_of_range.hpp>
+#include <boost/metaparse/error/letter_expected.hpp>
+#include <boost/metaparse/error/literal_expected.hpp>
+#include <boost/metaparse/error/none_of_the_expected_cases_found.hpp>
+#include <boost/metaparse/error/unexpected_character.hpp>
+#include <boost/metaparse/error/unexpected_end_of_input.hpp>
+#include <boost/metaparse/error/unpaired.hpp>
+#include <boost/metaparse/error/whitespace_expected.hpp>
+#include <boost/metaparse/except.hpp>
+#include <boost/metaparse/fail_at_first_char_expected.hpp>
+#include <boost/metaparse/fail.hpp>
+#include <boost/metaparse/fail_tag.hpp>
+#include <boost/metaparse/first_of.hpp>
+#include <boost/metaparse/foldl1.hpp>
+#include <boost/metaparse/foldl_reject_incomplete.hpp>
+#include <boost/metaparse/foldl_reject_incomplete1.hpp>
+#include <boost/metaparse/foldl_reject_incomplete_start_with_parser.hpp>
+#include <boost/metaparse/foldl.hpp>
+#include <boost/metaparse/foldl_start_with_parser.hpp>
+#include <boost/metaparse/foldr1.hpp>
+#include <boost/metaparse/foldr_reject_incomplete.hpp>
+#include <boost/metaparse/foldr_reject_incomplete1.hpp>
+#include <boost/metaparse/foldr.hpp>
+#include <boost/metaparse/foldr_start_with_parser.hpp>
+#include <boost/metaparse/get_col.hpp>
+#include <boost/metaparse/get_line.hpp>
+#include <boost/metaparse/get_message.hpp>
+#include <boost/metaparse/get_position.hpp>
+#include <boost/metaparse/get_prev_char.hpp>
+#include <boost/metaparse/get_remaining.hpp>
+#include <boost/metaparse/get_result.hpp>
+#include <boost/metaparse/grammar.hpp>
+#include <boost/metaparse/if_.hpp>
+#include <boost/metaparse/int_.hpp>
+#include <boost/metaparse/is_error.hpp>
+#include <boost/metaparse/iterate_c.hpp>
+#include <boost/metaparse/iterate.hpp>
+#include <boost/metaparse/keyword.hpp>
+#include <boost/metaparse/last_of.hpp>
+#include <boost/metaparse/letter.hpp>
+#include <boost/metaparse/limit_one_char_except_size.hpp>
+#include <boost/metaparse/limit_one_of_size.hpp>
+#include <boost/metaparse/limit_sequence_size.hpp>
+#include <boost/metaparse/limit_string_size.hpp>
+#include <boost/metaparse/lit_c.hpp>
+#include <boost/metaparse/lit.hpp>
+#include <boost/metaparse/look_ahead.hpp>
+#include <boost/metaparse/middle_of.hpp>
+#include <boost/metaparse/next_char.hpp>
+#include <boost/metaparse/next_line.hpp>
+#include <boost/metaparse/nth_of_c.hpp>
+#include <boost/metaparse/nth_of.hpp>
+#include <boost/metaparse/one_char_except_c.hpp>
+#include <boost/metaparse/one_char_except.hpp>
+#include <boost/metaparse/one_char.hpp>
+#include <boost/metaparse/one_of_c.hpp>
+#include <boost/metaparse/one_of.hpp>
+#include <boost/metaparse/optional.hpp>
+#include <boost/metaparse/range_c.hpp>
+#include <boost/metaparse/range.hpp>
+#include <boost/metaparse/reject.hpp>
+#include <boost/metaparse/return_.hpp>
+#include <boost/metaparse/sequence.hpp>
+#include <boost/metaparse/sequence_apply.hpp>
+#include <boost/metaparse/source_position.hpp>
+#include <boost/metaparse/source_position_tag.hpp>
+#include <boost/metaparse/space.hpp>
+#include <boost/metaparse/spaces.hpp>
+#include <boost/metaparse/start.hpp>
+#include <boost/metaparse/string.hpp>
+#include <boost/metaparse/string_tag.hpp>
+#include <boost/metaparse/token.hpp>
+#include <boost/metaparse/transform_error.hpp>
+#include <boost/metaparse/transform_error_message.hpp>
+#include <boost/metaparse/transform.hpp>
+#include <boost/metaparse/unless_error.hpp>
+#include <boost/metaparse/util/digit_to_int_c.hpp>
+#include <boost/metaparse/util/digit_to_int.hpp>
+#include <boost/metaparse/util/in_range_c.hpp>
+#include <boost/metaparse/util/in_range.hpp>
+#include <boost/metaparse/util/int_to_digit_c.hpp>
+#include <boost/metaparse/util/int_to_digit.hpp>
+#include <boost/metaparse/util/is_digit.hpp>
+#include <boost/metaparse/util/is_lcase_letter.hpp>
+#include <boost/metaparse/util/is_letter.hpp>
+#include <boost/metaparse/util/is_ucase_letter.hpp>
+#include <boost/metaparse/util/is_whitespace_c.hpp>
+#include <boost/metaparse/util/is_whitespace.hpp>
+#include <boost/metaparse/version.hpp>
+
+#endif
+
diff --git a/boost/metaparse/accept.hpp b/boost/metaparse/accept.hpp
new file mode 100644
index 0000000000..b5f8848b9d
--- /dev/null
+++ b/boost/metaparse/accept.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_ACCEPT_HPP
+#define BOOST_METAPARSE_ACCEPT_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/accept.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::accept;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/accept_tag.hpp b/boost/metaparse/accept_tag.hpp
new file mode 100644
index 0000000000..13ad04051c
--- /dev/null
+++ b/boost/metaparse/accept_tag.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_ACCEPT_TAG_HPP
+#define BOOST_METAPARSE_ACCEPT_TAG_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/accept_tag.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::accept_tag;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/accept_when.hpp b/boost/metaparse/accept_when.hpp
new file mode 100644
index 0000000000..0a870acacd
--- /dev/null
+++ b/boost/metaparse/accept_when.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_ACCEPT_WHEN_HPP
+#define BOOST_METAPARSE_ACCEPT_WHEN_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/accept_when.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::accept_when;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/alphanum.hpp b/boost/metaparse/alphanum.hpp
new file mode 100644
index 0000000000..1e23b1844d
--- /dev/null
+++ b/boost/metaparse/alphanum.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_ALPHANUM_HPP
+#define BOOST_METAPARSE_ALPHANUM_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/alphanum.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::alphanum;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/always.hpp b/boost/metaparse/always.hpp
new file mode 100644
index 0000000000..2e7f91f719
--- /dev/null
+++ b/boost/metaparse/always.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_ALWAYS_HPP
+#define BOOST_METAPARSE_ALWAYS_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/always.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::always;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/always_c.hpp b/boost/metaparse/always_c.hpp
new file mode 100644
index 0000000000..72ef32a82d
--- /dev/null
+++ b/boost/metaparse/always_c.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_ALWAYS_C_HPP
+#define BOOST_METAPARSE_ALWAYS_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/always_c.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::always_c;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/build_parser.hpp b/boost/metaparse/build_parser.hpp
new file mode 100644
index 0000000000..d21a59b97c
--- /dev/null
+++ b/boost/metaparse/build_parser.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_BUILD_PARSER_HPP
+#define BOOST_METAPARSE_BUILD_PARSER_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/build_parser.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::build_parser;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/change_error_message.hpp b/boost/metaparse/change_error_message.hpp
new file mode 100644
index 0000000000..ffae9845f4
--- /dev/null
+++ b/boost/metaparse/change_error_message.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_CHANGE_ERROR_MESSAGE_HPP
+#define BOOST_METAPARSE_CHANGE_ERROR_MESSAGE_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/change_error_message.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::change_error_message;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/config.hpp b/boost/metaparse/config.hpp
new file mode 100644
index 0000000000..a9a42dbb60
--- /dev/null
+++ b/boost/metaparse/config.hpp
@@ -0,0 +1,40 @@
+#ifndef BOOST_METAPARSE_CONFIG_HPP
+#define BOOST_METAPARSE_CONFIG_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/config.hpp>
+
+/*
+ * Compiler workarounds
+ */
+
+// BOOST_NO_CXX11_CONSTEXPR is not defined in gcc 4.6
+#if \
+ defined BOOST_NO_CXX11_CONSTEXPR || defined BOOST_NO_CONSTEXPR || ( \
+ !defined __clang__ && defined __GNUC__ \
+ && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7)) \
+ )
+
+# define BOOST_NO_CONSTEXPR_C_STR
+
+#endif
+
+/*
+ * Metaparse config
+ */
+
+#if \
+ !defined BOOST_NO_CXX11_VARIADIC_TEMPLATES \
+ && !defined BOOST_NO_VARIADIC_TEMPLATES \
+ && !defined BOOST_METAPARSE_VARIADIC_STRING
+
+# define BOOST_METAPARSE_VARIADIC_STRING
+
+#endif
+
+#endif
+
diff --git a/boost/metaparse/debug_parsing_error.hpp b/boost/metaparse/debug_parsing_error.hpp
new file mode 100644
index 0000000000..f32b29d3e1
--- /dev/null
+++ b/boost/metaparse/debug_parsing_error.hpp
@@ -0,0 +1,21 @@
+#ifndef BOOST_METAPARSE_DEBUG_PARSING_ERROR_HPP
+#define BOOST_METAPARSE_DEBUG_PARSING_ERROR_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/debug_parsing_error.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::debug_parsing_error;
+ }
+}
+
+#endif
+
+
diff --git a/boost/metaparse/define_error.hpp b/boost/metaparse/define_error.hpp
new file mode 100644
index 0000000000..d7356cee25
--- /dev/null
+++ b/boost/metaparse/define_error.hpp
@@ -0,0 +1,17 @@
+#ifndef BOOST_METAPARSE_DEFINE_ERROR_HPP
+#define BOOST_METAPARSE_DEFINE_ERROR_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/define_error.hpp>
+
+#ifdef BOOST_METAPARSE_DEFINE_ERROR
+# error BOOST_METAPARSE_DEFINE_ERROR already defined
+#endif
+#define BOOST_METAPARSE_DEFINE_ERROR BOOST_METAPARSE_V1_DEFINE_ERROR
+
+#endif
+
diff --git a/boost/metaparse/digit.hpp b/boost/metaparse/digit.hpp
new file mode 100644
index 0000000000..1018bc111a
--- /dev/null
+++ b/boost/metaparse/digit.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_DIGIT_HPP
+#define BOOST_METAPARSE_DIGIT_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/digit.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::digit;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/digit_val.hpp b/boost/metaparse/digit_val.hpp
new file mode 100644
index 0000000000..63b2d79dba
--- /dev/null
+++ b/boost/metaparse/digit_val.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_DIGIT_VAL_HPP
+#define BOOST_METAPARSE_DIGIT_VAL_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/digit_val.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::digit_val;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/empty.hpp b/boost/metaparse/empty.hpp
new file mode 100644
index 0000000000..d99c314d3a
--- /dev/null
+++ b/boost/metaparse/empty.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_EMPTY_HPP
+#define BOOST_METAPARSE_EMPTY_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/empty.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::empty;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/entire_input.hpp b/boost/metaparse/entire_input.hpp
new file mode 100644
index 0000000000..702fc47934
--- /dev/null
+++ b/boost/metaparse/entire_input.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_ENTIRE_INPUT_HPP
+#define BOOST_METAPARSE_ENTIRE_INPUT_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/entire_input.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::entire_input;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/error/digit_expected.hpp b/boost/metaparse/error/digit_expected.hpp
new file mode 100644
index 0000000000..b6ed0f4729
--- /dev/null
+++ b/boost/metaparse/error/digit_expected.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_METAPARSE_ERROR_DIGIT_EXPECTED_HPP
+#define BOOST_METAPARSE_ERROR_DIGIT_EXPECTED_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/error/digit_expected.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace error
+ {
+ using v1::error::digit_expected;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/error/end_of_input_expected.hpp b/boost/metaparse/error/end_of_input_expected.hpp
new file mode 100644
index 0000000000..00f556c2e2
--- /dev/null
+++ b/boost/metaparse/error/end_of_input_expected.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_METAPARSE_END_OF_INPUT_EXPECTED_HPP
+#define BOOST_METAPARSE_END_OF_INPUT_EXPECTED_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/error/end_of_input_expected.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace error
+ {
+ using v1::error::end_of_input_expected;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/error/index_out_of_range.hpp b/boost/metaparse/error/index_out_of_range.hpp
new file mode 100644
index 0000000000..74d2622336
--- /dev/null
+++ b/boost/metaparse/error/index_out_of_range.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_METAPARSE_ERROR_INDEX_OUT_OF_RANGE_HPP
+#define BOOST_METAPARSE_ERROR_INDEX_OUT_OF_RANGE_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/error/index_out_of_range.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace error
+ {
+ using v1::error::index_out_of_range;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/error/letter_expected.hpp b/boost/metaparse/error/letter_expected.hpp
new file mode 100644
index 0000000000..ad78b4347d
--- /dev/null
+++ b/boost/metaparse/error/letter_expected.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_METAPARSE_ERROR_LETTER_EXPECTED_HPP
+#define BOOST_METAPARSE_ERROR_LETTER_EXPECTED_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/error/letter_expected.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace error
+ {
+ using v1::error::letter_expected;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/error/literal_expected.hpp b/boost/metaparse/error/literal_expected.hpp
new file mode 100644
index 0000000000..9798c9fe7d
--- /dev/null
+++ b/boost/metaparse/error/literal_expected.hpp
@@ -0,0 +1,24 @@
+#ifndef BOOST_METAPARSE_ERROR_LITERAL_EXPECTED_HPP
+#define BOOST_METAPARSE_ERROR_LITERAL_EXPECTED_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/error/literal_expected.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace error
+ {
+ using v1::error::literal_expected;
+ }
+ }
+}
+
+#endif
+
+
diff --git a/boost/metaparse/error/none_of_the_expected_cases_found.hpp b/boost/metaparse/error/none_of_the_expected_cases_found.hpp
new file mode 100644
index 0000000000..3b71183e8e
--- /dev/null
+++ b/boost/metaparse/error/none_of_the_expected_cases_found.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_METAPARSE_ERROR_NONE_OF_THE_EXPECTED_CASES_FOUND_HPP
+#define BOOST_METAPARSE_ERROR_NONE_OF_THE_EXPECTED_CASES_FOUND_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/error/none_of_the_expected_cases_found.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace error
+ {
+ using v1::error::none_of_the_expected_cases_found;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/error/unexpected_character.hpp b/boost/metaparse/error/unexpected_character.hpp
new file mode 100644
index 0000000000..b55d60a94f
--- /dev/null
+++ b/boost/metaparse/error/unexpected_character.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_METAPARSE_ERROR_UNEXPECTED_CHARACTER_HPP
+#define BOOST_METAPARSE_ERROR_UNEXPECTED_CHARACTER_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/error/unexpected_character.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace error
+ {
+ using v1::error::unexpected_character;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/error/unexpected_end_of_input.hpp b/boost/metaparse/error/unexpected_end_of_input.hpp
new file mode 100644
index 0000000000..01acc6126a
--- /dev/null
+++ b/boost/metaparse/error/unexpected_end_of_input.hpp
@@ -0,0 +1,24 @@
+#ifndef BOOST_METAPARSE_ERROR_UNEXPECTED_END_OF_INPUT_HPP
+#define BOOST_METAPARSE_ERROR_UNEXPECTED_END_OF_INPUT_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/error/unexpected_end_of_input.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace error
+ {
+ using v1::error::unexpected_end_of_input;
+ }
+ }
+}
+
+#endif
+
+
diff --git a/boost/metaparse/error/unpaired.hpp b/boost/metaparse/error/unpaired.hpp
new file mode 100644
index 0000000000..800f03a515
--- /dev/null
+++ b/boost/metaparse/error/unpaired.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_METAPARSE_ERROR_UNPAIRED_HPP
+#define BOOST_METAPARSE_ERROR_UNPAIRED_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/error/unpaired.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace error
+ {
+ using v1::error::unpaired;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/error/whitespace_expected.hpp b/boost/metaparse/error/whitespace_expected.hpp
new file mode 100644
index 0000000000..bf263f8d2b
--- /dev/null
+++ b/boost/metaparse/error/whitespace_expected.hpp
@@ -0,0 +1,24 @@
+#ifndef BOOST_METAPARSE_ERROR_WHITESPACE_EXPECTED_HPP
+#define BOOST_METAPARSE_ERROR_WHITESPACE_EXPECTED_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/error/whitespace_expected.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace error
+ {
+ using v1::error::whitespace_expected;
+ }
+ }
+}
+
+#endif
+
+
diff --git a/boost/metaparse/except.hpp b/boost/metaparse/except.hpp
new file mode 100644
index 0000000000..d51f026d8b
--- /dev/null
+++ b/boost/metaparse/except.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_EXCEPT_HPP
+#define BOOST_METAPARSE_EXCEPT_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/except.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::except;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/fail.hpp b/boost/metaparse/fail.hpp
new file mode 100644
index 0000000000..f9d90bd936
--- /dev/null
+++ b/boost/metaparse/fail.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_FAIL_HPP
+#define BOOST_METAPARSE_FAIL_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/fail.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::fail;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/fail_at_first_char_expected.hpp b/boost/metaparse/fail_at_first_char_expected.hpp
new file mode 100644
index 0000000000..0d94b04ee1
--- /dev/null
+++ b/boost/metaparse/fail_at_first_char_expected.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_FAIL_AT_FIRST_CHAR_EXPECTED_HPP
+#define BOOST_METAPARSE_FAIL_AT_FIRST_CHAR_EXPECTED_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/fail_at_first_char_expected.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::fail_at_first_char_expected;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/fail_tag.hpp b/boost/metaparse/fail_tag.hpp
new file mode 100644
index 0000000000..4cf469884b
--- /dev/null
+++ b/boost/metaparse/fail_tag.hpp
@@ -0,0 +1,21 @@
+#ifndef BOOST_METAPARSE_FAIL_TAG_HPP
+#define BOOST_METAPARSE_FAIL_TAG_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/fail_tag.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::fail_tag;
+ }
+}
+
+#endif
+
+
diff --git a/boost/metaparse/first_of.hpp b/boost/metaparse/first_of.hpp
new file mode 100644
index 0000000000..278fabd809
--- /dev/null
+++ b/boost/metaparse/first_of.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_FIRST_OF_HPP
+#define BOOST_METAPARSE_FIRST_OF_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/first_of.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::first_of;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/foldl.hpp b/boost/metaparse/foldl.hpp
new file mode 100644
index 0000000000..f76ef6e5d7
--- /dev/null
+++ b/boost/metaparse/foldl.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_FOLDL_HPP
+#define BOOST_METAPARSE_FOLDL_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/foldl.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::foldl;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/foldl1.hpp b/boost/metaparse/foldl1.hpp
new file mode 100644
index 0000000000..9120fe75c8
--- /dev/null
+++ b/boost/metaparse/foldl1.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_FOLDL1_HPP
+#define BOOST_METAPARSE_FOLDL1_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/foldl1.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::foldl1;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/foldl_reject_incomplete.hpp b/boost/metaparse/foldl_reject_incomplete.hpp
new file mode 100644
index 0000000000..9ccd95f770
--- /dev/null
+++ b/boost/metaparse/foldl_reject_incomplete.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_FOLDL_REJECT_INCOMPLETE_HPP
+#define BOOST_METAPARSE_FOLDL_REJECT_INCOMPLETE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/foldl_reject_incomplete.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::foldl_reject_incomplete;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/foldl_reject_incomplete1.hpp b/boost/metaparse/foldl_reject_incomplete1.hpp
new file mode 100644
index 0000000000..412382000a
--- /dev/null
+++ b/boost/metaparse/foldl_reject_incomplete1.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_FOLDL_REJECT_INCOMPLETE1_HPP
+#define BOOST_METAPARSE_FOLDL_REJECT_INCOMPLETE1_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/foldl_reject_incomplete1.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::foldl_reject_incomplete1;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/foldl_reject_incomplete_start_with_parser.hpp b/boost/metaparse/foldl_reject_incomplete_start_with_parser.hpp
new file mode 100644
index 0000000000..3a9f02abb6
--- /dev/null
+++ b/boost/metaparse/foldl_reject_incomplete_start_with_parser.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_FOLDL_REJECT_INCOMPLETE_START_WITH_PARSER_HPP
+#define BOOST_METAPARSE_FOLDL_REJECT_INCOMPLETE_START_WITH_PARSER_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/foldl_reject_incomplete_start_with_parser.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::foldl_reject_incomplete_start_with_parser;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/foldl_start_with_parser.hpp b/boost/metaparse/foldl_start_with_parser.hpp
new file mode 100644
index 0000000000..ab17f9f978
--- /dev/null
+++ b/boost/metaparse/foldl_start_with_parser.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_FOLDL_START_WITH_PARSER_HPP
+#define BOOST_METAPARSE_FOLDL_START_WITH_PARSER_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/foldl_start_with_parser.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::foldl_start_with_parser;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/foldr.hpp b/boost/metaparse/foldr.hpp
new file mode 100644
index 0000000000..ef03e25fd7
--- /dev/null
+++ b/boost/metaparse/foldr.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_FOLDR_HPP
+#define BOOST_METAPARSE_FOLDR_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/foldr.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::foldr;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/foldr1.hpp b/boost/metaparse/foldr1.hpp
new file mode 100644
index 0000000000..c133683aea
--- /dev/null
+++ b/boost/metaparse/foldr1.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_FOLDR1_HPP
+#define BOOST_METAPARSE_FOLDR1_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/foldr1.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::foldr1;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/foldr_reject_incomplete.hpp b/boost/metaparse/foldr_reject_incomplete.hpp
new file mode 100644
index 0000000000..c81e1f6c20
--- /dev/null
+++ b/boost/metaparse/foldr_reject_incomplete.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_FOLDR_REJECT_INCOMPLETE_HPP
+#define BOOST_METAPARSE_FOLDR_REJECT_INCOMPLETE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/foldr_reject_incomplete.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::foldr_reject_incomplete;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/foldr_reject_incomplete1.hpp b/boost/metaparse/foldr_reject_incomplete1.hpp
new file mode 100644
index 0000000000..1ca37ee492
--- /dev/null
+++ b/boost/metaparse/foldr_reject_incomplete1.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_FOLDR_REJECT_INCOMPLETE1_HPP
+#define BOOST_METAPARSE_FOLDR_REJECT_INCOMPLETE1_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/foldr_reject_incomplete1.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::foldr_reject_incomplete1;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/foldr_start_with_parser.hpp b/boost/metaparse/foldr_start_with_parser.hpp
new file mode 100644
index 0000000000..1e3c621857
--- /dev/null
+++ b/boost/metaparse/foldr_start_with_parser.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_FOLDR_START_WITH_PARSER_HPP
+#define BOOST_METAPARSE_FOLDR_START_WITH_PARSER_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/foldr_start_with_parser.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::foldr_start_with_parser;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/get_col.hpp b/boost/metaparse/get_col.hpp
new file mode 100644
index 0000000000..d5b21966f2
--- /dev/null
+++ b/boost/metaparse/get_col.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_GET_COL_HPP
+#define BOOST_METAPARSE_GET_COL_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/get_col.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::get_col;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/get_line.hpp b/boost/metaparse/get_line.hpp
new file mode 100644
index 0000000000..619db7ef97
--- /dev/null
+++ b/boost/metaparse/get_line.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_GET_LINE_HPP
+#define BOOST_METAPARSE_GET_LINE_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/get_line.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::get_line;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/get_message.hpp b/boost/metaparse/get_message.hpp
new file mode 100644
index 0000000000..d724f0fafc
--- /dev/null
+++ b/boost/metaparse/get_message.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_GET_MESSAGE_HPP
+#define BOOST_METAPARSE_GET_MESSAGE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/get_message.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::get_message;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/get_position.hpp b/boost/metaparse/get_position.hpp
new file mode 100644
index 0000000000..d8ec62420d
--- /dev/null
+++ b/boost/metaparse/get_position.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_GET_POSITION_HPP
+#define BOOST_METAPARSE_GET_POSITION_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/get_position.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::get_position;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/get_prev_char.hpp b/boost/metaparse/get_prev_char.hpp
new file mode 100644
index 0000000000..14b325c1f5
--- /dev/null
+++ b/boost/metaparse/get_prev_char.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_GET_PREV_CHAR_HPP
+#define BOOST_METAPARSE_GET_PREV_CHAR_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/get_prev_char.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::get_prev_char;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/get_remaining.hpp b/boost/metaparse/get_remaining.hpp
new file mode 100644
index 0000000000..3cf48f1ab6
--- /dev/null
+++ b/boost/metaparse/get_remaining.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_GET_REMAINING_HPP
+#define BOOST_METAPARSE_GET_REMAINING_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/get_remaining.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::get_remaining;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/get_result.hpp b/boost/metaparse/get_result.hpp
new file mode 100644
index 0000000000..cb4f8de961
--- /dev/null
+++ b/boost/metaparse/get_result.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_GET_RESULT_HPP
+#define BOOST_METAPARSE_GET_RESULT_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/get_result.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::get_result;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/grammar.hpp b/boost/metaparse/grammar.hpp
new file mode 100644
index 0000000000..f7b786b549
--- /dev/null
+++ b/boost/metaparse/grammar.hpp
@@ -0,0 +1,19 @@
+#ifndef BOOST_METAPARSE_GRAMMAR_HPP
+#define BOOST_METAPARSE_GRAMMAR_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/grammar.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::grammar;
+ }
+}
+
+#endif
diff --git a/boost/metaparse/if_.hpp b/boost/metaparse/if_.hpp
new file mode 100644
index 0000000000..7f56185e03
--- /dev/null
+++ b/boost/metaparse/if_.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_IF__HPP
+#define BOOST_METAPARSE_IF__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/if_.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::if_;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/int_.hpp b/boost/metaparse/int_.hpp
new file mode 100644
index 0000000000..0314ee01c5
--- /dev/null
+++ b/boost/metaparse/int_.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_INT_HPP
+#define BOOST_METAPARSE_INT_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/int_.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::int_;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/is_error.hpp b/boost/metaparse/is_error.hpp
new file mode 100644
index 0000000000..ff61bca42f
--- /dev/null
+++ b/boost/metaparse/is_error.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_IS_ERROR_HPP
+#define BOOST_METAPARSE_IS_ERROR_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/is_error.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::is_error;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/iterate.hpp b/boost/metaparse/iterate.hpp
new file mode 100644
index 0000000000..0e5450f1ad
--- /dev/null
+++ b/boost/metaparse/iterate.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_ITERATE_HPP
+#define BOOST_METAPARSE_ITERATE_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/iterate.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::iterate;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/iterate_c.hpp b/boost/metaparse/iterate_c.hpp
new file mode 100644
index 0000000000..59f07493a0
--- /dev/null
+++ b/boost/metaparse/iterate_c.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_ITERATE_C_HPP
+#define BOOST_METAPARSE_ITERATE_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/iterate_c.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::iterate_c;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/keyword.hpp b/boost/metaparse/keyword.hpp
new file mode 100644
index 0000000000..223357d5e9
--- /dev/null
+++ b/boost/metaparse/keyword.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_KEYWORD_HPP
+#define BOOST_METAPARSE_KEYWORD_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/keyword.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::keyword;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/last_of.hpp b/boost/metaparse/last_of.hpp
new file mode 100644
index 0000000000..f5e933b27d
--- /dev/null
+++ b/boost/metaparse/last_of.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_LAST_OF_HPP
+#define BOOST_METAPARSE_LAST_OF_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/last_of.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::last_of;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/letter.hpp b/boost/metaparse/letter.hpp
new file mode 100644
index 0000000000..a85ede1f94
--- /dev/null
+++ b/boost/metaparse/letter.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_LETTER_HPP
+#define BOOST_METAPARSE_LETTER_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/letter.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::letter;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/limit_one_char_except_size.hpp b/boost/metaparse/limit_one_char_except_size.hpp
new file mode 100644
index 0000000000..f446f6a158
--- /dev/null
+++ b/boost/metaparse/limit_one_char_except_size.hpp
@@ -0,0 +1,15 @@
+#ifndef BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE_HPP
+#define BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE
+# define BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE 10
+#endif
+
+#endif
+
+
diff --git a/boost/metaparse/limit_one_of_size.hpp b/boost/metaparse/limit_one_of_size.hpp
new file mode 100644
index 0000000000..bff40f0831
--- /dev/null
+++ b/boost/metaparse/limit_one_of_size.hpp
@@ -0,0 +1,14 @@
+#ifndef BOOST_METAPARSE_LIMIT_ONE_OF_SIZE_HPP
+#define BOOST_METAPARSE_LIMIT_ONE_OF_SIZE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_METAPARSE_LIMIT_ONE_OF_SIZE
+# define BOOST_METAPARSE_LIMIT_ONE_OF_SIZE 20
+#endif
+
+#endif
+
diff --git a/boost/metaparse/limit_sequence_size.hpp b/boost/metaparse/limit_sequence_size.hpp
new file mode 100644
index 0000000000..37c693a069
--- /dev/null
+++ b/boost/metaparse/limit_sequence_size.hpp
@@ -0,0 +1,14 @@
+#ifndef BOOST_METAPARSE_LIMIT_SEQUENCE_SIZE_HPP
+#define BOOST_METAPARSE_LIMIT_SEQUENCE_SIZE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_METAPARSE_LIMIT_SEQUENCE_SIZE
+# define BOOST_METAPARSE_LIMIT_SEQUENCE_SIZE 5
+#endif
+
+#endif
+
diff --git a/boost/metaparse/limit_string_size.hpp b/boost/metaparse/limit_string_size.hpp
new file mode 100644
index 0000000000..3b4208b2ee
--- /dev/null
+++ b/boost/metaparse/limit_string_size.hpp
@@ -0,0 +1,14 @@
+#ifndef BOOST_METAPARSE_LIMIT_STRING_SIZE_HPP
+#define BOOST_METAPARSE_LIMIT_STRING_SIZE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_METAPARSE_LIMIT_STRING_SIZE
+# define BOOST_METAPARSE_LIMIT_STRING_SIZE 32
+#endif
+
+#endif
+
diff --git a/boost/metaparse/lit.hpp b/boost/metaparse/lit.hpp
new file mode 100644
index 0000000000..91dada439c
--- /dev/null
+++ b/boost/metaparse/lit.hpp
@@ -0,0 +1,21 @@
+#ifndef BOOST_METAPARSE_LIT_HPP
+#define BOOST_METAPARSE_LIT_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/lit.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::lit;
+ }
+}
+
+#endif
+
+
diff --git a/boost/metaparse/lit_c.hpp b/boost/metaparse/lit_c.hpp
new file mode 100644
index 0000000000..fc0f380643
--- /dev/null
+++ b/boost/metaparse/lit_c.hpp
@@ -0,0 +1,21 @@
+#ifndef BOOST_METAPARSE_LIT_C_HPP
+#define BOOST_METAPARSE_LIT_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/lit_c.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::lit_c;
+ }
+}
+
+#endif
+
+
diff --git a/boost/metaparse/look_ahead.hpp b/boost/metaparse/look_ahead.hpp
new file mode 100644
index 0000000000..db0cce2e57
--- /dev/null
+++ b/boost/metaparse/look_ahead.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_LOOK_AHEAD_HPP
+#define BOOST_METAPARSE_LOOK_AHEAD_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/look_ahead.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::look_ahead;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/middle_of.hpp b/boost/metaparse/middle_of.hpp
new file mode 100644
index 0000000000..335c5502e1
--- /dev/null
+++ b/boost/metaparse/middle_of.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_KEEP_MIDDLE_HPP
+#define BOOST_METAPARSE_KEEP_MIDDLE_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/middle_of.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::middle_of;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/next_char.hpp b/boost/metaparse/next_char.hpp
new file mode 100644
index 0000000000..428c6d11cf
--- /dev/null
+++ b/boost/metaparse/next_char.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_NEXT_CHAR_HPP
+#define BOOST_METAPARSE_NEXT_CHAR_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/next_char.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::next_char;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/next_line.hpp b/boost/metaparse/next_line.hpp
new file mode 100644
index 0000000000..0f2bd36e56
--- /dev/null
+++ b/boost/metaparse/next_line.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_NEXT_LINE_HPP
+#define BOOST_METAPARSE_NEXT_LINE_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/next_line.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::next_line;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/nth_of.hpp b/boost/metaparse/nth_of.hpp
new file mode 100644
index 0000000000..b479e54646
--- /dev/null
+++ b/boost/metaparse/nth_of.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_NTH_OF_HPP
+#define BOOST_METAPARSE_NTH_OF_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/nth_of.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::nth_of;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/nth_of_c.hpp b/boost/metaparse/nth_of_c.hpp
new file mode 100644
index 0000000000..780ff5e090
--- /dev/null
+++ b/boost/metaparse/nth_of_c.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_NTH_OF_C_HPP
+#define BOOST_METAPARSE_NTH_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/nth_of_c.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::nth_of_c;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/one_char.hpp b/boost/metaparse/one_char.hpp
new file mode 100644
index 0000000000..641cd5b893
--- /dev/null
+++ b/boost/metaparse/one_char.hpp
@@ -0,0 +1,21 @@
+#ifndef BOOST_METAPARSE_ONE_CHAR_HPP
+#define BOOST_METAPARSE_ONE_CHAR_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_char.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::one_char;
+ }
+}
+
+#endif
+
+
diff --git a/boost/metaparse/one_char_except.hpp b/boost/metaparse/one_char_except.hpp
new file mode 100644
index 0000000000..56cb10cd1e
--- /dev/null
+++ b/boost/metaparse/one_char_except.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_ONE_CHAR_EXCEPT_HPP
+#define BOOST_METAPARSE_ONE_CHAR_EXCEPT_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_char_except.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::one_char_except;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/one_char_except_c.hpp b/boost/metaparse/one_char_except_c.hpp
new file mode 100644
index 0000000000..5926361ab4
--- /dev/null
+++ b/boost/metaparse/one_char_except_c.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_ONE_CHAR_EXCEPT_C_HPP
+#define BOOST_METAPARSE_ONE_CHAR_EXCEPT_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_char_except_c.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::one_char_except_c;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/one_of.hpp b/boost/metaparse/one_of.hpp
new file mode 100644
index 0000000000..b5054ca641
--- /dev/null
+++ b/boost/metaparse/one_of.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_ONE_OF_HPP
+#define BOOST_METAPARSE_ONE_OF_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>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::one_of;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/one_of_c.hpp b/boost/metaparse/one_of_c.hpp
new file mode 100644
index 0000000000..1358b37b90
--- /dev/null
+++ b/boost/metaparse/one_of_c.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_ONE_OF_C_HPP
+#define BOOST_METAPARSE_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_c.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::one_of_c;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/optional.hpp b/boost/metaparse/optional.hpp
new file mode 100644
index 0000000000..9595b08573
--- /dev/null
+++ b/boost/metaparse/optional.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_OPTIONAL_HPP
+#define BOOST_METAPARSE_OPTIONAL_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/optional.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::optional;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/range.hpp b/boost/metaparse/range.hpp
new file mode 100644
index 0000000000..dea97a6f39
--- /dev/null
+++ b/boost/metaparse/range.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_RANGE_HPP
+#define BOOST_METAPARSE_RANGE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/range.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::range;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/range_c.hpp b/boost/metaparse/range_c.hpp
new file mode 100644
index 0000000000..a91027000e
--- /dev/null
+++ b/boost/metaparse/range_c.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_RANGE_C_HPP
+#define BOOST_METAPARSE_RANGE_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/range_c.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::range_c;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/reject.hpp b/boost/metaparse/reject.hpp
new file mode 100644
index 0000000000..9bb9a0edf9
--- /dev/null
+++ b/boost/metaparse/reject.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_REJECT_HPP
+#define BOOST_METAPARSE_REJECT_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/reject.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::reject;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/repeated.hpp b/boost/metaparse/repeated.hpp
new file mode 100644
index 0000000000..e71ecc37fe
--- /dev/null
+++ b/boost/metaparse/repeated.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_REPEATED_HPP
+#define BOOST_METAPARSE_REPEATED_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/repeated.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::repeated;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/repeated1.hpp b/boost/metaparse/repeated1.hpp
new file mode 100644
index 0000000000..9c31dc4949
--- /dev/null
+++ b/boost/metaparse/repeated1.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_REPEATED1_HPP
+#define BOOST_METAPARSE_REPEATED1_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/repeated1.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::repeated1;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/repeated_one_of.hpp b/boost/metaparse/repeated_one_of.hpp
new file mode 100644
index 0000000000..4cf5e73cfd
--- /dev/null
+++ b/boost/metaparse/repeated_one_of.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_REPEATED_ONE_OF_HPP
+#define BOOST_METAPARSE_REPEATED_ONE_OF_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/repeated_one_of.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::repeated_one_of;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/repeated_one_of1.hpp b/boost/metaparse/repeated_one_of1.hpp
new file mode 100644
index 0000000000..8b92476160
--- /dev/null
+++ b/boost/metaparse/repeated_one_of1.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_REPEATED_ONE_OF1_HPP
+#define BOOST_METAPARSE_REPEATED_ONE_OF1_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/repeated_one_of1.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::repeated_one_of1;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/repeated_reject_incomplete.hpp b/boost/metaparse/repeated_reject_incomplete.hpp
new file mode 100644
index 0000000000..9cc0ccf936
--- /dev/null
+++ b/boost/metaparse/repeated_reject_incomplete.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_REPEATED_REJECT_INCOMPLETE_HPP
+#define BOOST_METAPARSE_REPEATED_REJECT_INCOMPLETE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/repeated_reject_incomplete.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::repeated_reject_incomplete;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/repeated_reject_incomplete1.hpp b/boost/metaparse/repeated_reject_incomplete1.hpp
new file mode 100644
index 0000000000..27109fb0a5
--- /dev/null
+++ b/boost/metaparse/repeated_reject_incomplete1.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_REPEATED_REJECT_INCOMPLETE1_HPP
+#define BOOST_METAPARSE_REPEATED_REJECT_INCOMPLETE1_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/repeated_reject_incomplete1.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::repeated_reject_incomplete1;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/return_.hpp b/boost/metaparse/return_.hpp
new file mode 100644
index 0000000000..ed45447fc4
--- /dev/null
+++ b/boost/metaparse/return_.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_RETURN__HPP
+#define BOOST_METAPARSE_RETURN__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/return_.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::return_;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/sequence.hpp b/boost/metaparse/sequence.hpp
new file mode 100644
index 0000000000..50cfec79eb
--- /dev/null
+++ b/boost/metaparse/sequence.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_SEQUENCE_HPP
+#define BOOST_METAPARSE_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/sequence.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::sequence;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/sequence_apply.hpp b/boost/metaparse/sequence_apply.hpp
new file mode 100644
index 0000000000..1b949e6b9c
--- /dev/null
+++ b/boost/metaparse/sequence_apply.hpp
@@ -0,0 +1,36 @@
+#ifndef BOOST_METAPARSE_SEQUENCE_APPLY_HPP
+#define BOOST_METAPARSE_SEQUENCE_APPLY_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/sequence_apply.hpp>
+
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+#include <boost/preprocessor/cat.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+#ifdef BOOST_METAPARSE_USING
+# error BOOST_METAPARSE_USING already defined
+#endif
+#define BOOST_METAPARSE_USING(z, n, unused) \
+ using BOOST_PP_CAT(v1::sequence_apply, n);
+
+ BOOST_PP_REPEAT_FROM_TO(
+ 1,
+ BOOST_METAPARSE_LIMIT_SEQUENCE_SIZE,
+ BOOST_METAPARSE_USING,
+ ~
+ )
+
+#undef BOOST_METAPARSE_USING
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/source_position.hpp b/boost/metaparse/source_position.hpp
new file mode 100644
index 0000000000..3dbdee0196
--- /dev/null
+++ b/boost/metaparse/source_position.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_SOURCE_POSITION_HPP
+#define BOOST_METAPARSE_SOURCE_POSITION_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/source_position.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::source_position;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/source_position_tag.hpp b/boost/metaparse/source_position_tag.hpp
new file mode 100644
index 0000000000..eed1bb4778
--- /dev/null
+++ b/boost/metaparse/source_position_tag.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_SOURCE_POSITION_TAG_HPP
+#define BOOST_METAPARSE_SOURCE_POSITION_TAG_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/source_position_tag.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::source_position_tag;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/space.hpp b/boost/metaparse/space.hpp
new file mode 100644
index 0000000000..1dcd4f0a3a
--- /dev/null
+++ b/boost/metaparse/space.hpp
@@ -0,0 +1,21 @@
+#ifndef BOOST_METAPARSE_SPACE_HPP
+#define BOOST_METAPARSE_SPACE_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/space.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::space;
+ }
+}
+
+#endif
+
+
diff --git a/boost/metaparse/spaces.hpp b/boost/metaparse/spaces.hpp
new file mode 100644
index 0000000000..8f705334f7
--- /dev/null
+++ b/boost/metaparse/spaces.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_SPACES_HPP
+#define BOOST_METAPARSE_SPACES_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/spaces.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::spaces;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/start.hpp b/boost/metaparse/start.hpp
new file mode 100644
index 0000000000..c149b32235
--- /dev/null
+++ b/boost/metaparse/start.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_START_HPP
+#define BOOST_METAPARSE_START_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/start.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::start;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/string.hpp b/boost/metaparse/string.hpp
new file mode 100644
index 0000000000..821a986f1f
--- /dev/null
+++ b/boost/metaparse/string.hpp
@@ -0,0 +1,26 @@
+#ifndef BOOST_METAPARSE_STRING_HPP
+#define BOOST_METAPARSE_STRING_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/string.hpp>
+#include <boost/metaparse/string_tag.hpp>
+
+#ifdef BOOST_METAPARSE_STRING
+# error BOOST_METAPARSE_STRING already defined
+#endif
+#define BOOST_METAPARSE_STRING BOOST_METAPARSE_V1_STRING
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::string;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/string_tag.hpp b/boost/metaparse/string_tag.hpp
new file mode 100644
index 0000000000..7be1fc5002
--- /dev/null
+++ b/boost/metaparse/string_tag.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_STRING_TAG_HPP
+#define BOOST_METAPARSE_STRING_TAG_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/string_tag.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::string_tag;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/token.hpp b/boost/metaparse/token.hpp
new file mode 100644
index 0000000000..6deac16991
--- /dev/null
+++ b/boost/metaparse/token.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_TOKEN_HPP
+#define BOOST_METAPARSE_TOKEN_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/token.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::token;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/transform.hpp b/boost/metaparse/transform.hpp
new file mode 100644
index 0000000000..f4250850b9
--- /dev/null
+++ b/boost/metaparse/transform.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_TRANSFORM_HPP
+#define BOOST_METAPARSE_TRANSFORM_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/transform.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::transform;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/transform_error.hpp b/boost/metaparse/transform_error.hpp
new file mode 100644
index 0000000000..5b72f05f9c
--- /dev/null
+++ b/boost/metaparse/transform_error.hpp
@@ -0,0 +1,21 @@
+#ifndef BOOST_METAPARSE_TRANSFORM_ERROR_HPP
+#define BOOST_METAPARSE_TRANSFORM_ERROR_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/transform_error.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::transform_error;
+ }
+}
+
+#endif
+
+
diff --git a/boost/metaparse/transform_error_message.hpp b/boost/metaparse/transform_error_message.hpp
new file mode 100644
index 0000000000..51b5df989e
--- /dev/null
+++ b/boost/metaparse/transform_error_message.hpp
@@ -0,0 +1,21 @@
+#ifndef BOOST_METAPARSE_TRANSFORM_ERROR_MESSAGE_HPP
+#define BOOST_METAPARSE_TRANSFORM_ERROR_MESSAGE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/transform_error_message.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::transform_error_message;
+ }
+}
+
+#endif
+
+
diff --git a/boost/metaparse/unless_error.hpp b/boost/metaparse/unless_error.hpp
new file mode 100644
index 0000000000..86481d1af1
--- /dev/null
+++ b/boost/metaparse/unless_error.hpp
@@ -0,0 +1,20 @@
+#ifndef BOOST_METAPARSE_UTIL_UNLESS_ERROR_HPP
+#define BOOST_METAPARSE_UTIL_UNLESS_ERROR_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/unless_error.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ using v1::unless_error;
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/util/digit_to_int.hpp b/boost/metaparse/util/digit_to_int.hpp
new file mode 100644
index 0000000000..8f629b8915
--- /dev/null
+++ b/boost/metaparse/util/digit_to_int.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_METAPARSE_UTIL_DIGIT_TO_INT_HPP
+#define BOOST_METAPARSE_UTIL_DIGIT_TO_INT_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/util/digit_to_int.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace util
+ {
+ using v1::util::digit_to_int;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/util/digit_to_int_c.hpp b/boost/metaparse/util/digit_to_int_c.hpp
new file mode 100644
index 0000000000..428cddabf8
--- /dev/null
+++ b/boost/metaparse/util/digit_to_int_c.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_METAPARSE_UTIL_DIGIT_TO_INT_C_HPP
+#define BOOST_METAPARSE_UTIL_DIGIT_TO_INT_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/util/digit_to_int_c.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace util
+ {
+ using v1::util::digit_to_int_c;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/util/in_range.hpp b/boost/metaparse/util/in_range.hpp
new file mode 100644
index 0000000000..2f0308af58
--- /dev/null
+++ b/boost/metaparse/util/in_range.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_METAPARSE_UTIL_IN_RANGE_HPP
+#define BOOST_METAPARSE_UTIL_IN_RANGE_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/util/in_range.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace util
+ {
+ using v1::util::in_range;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/util/in_range_c.hpp b/boost/metaparse/util/in_range_c.hpp
new file mode 100644
index 0000000000..a090258cfa
--- /dev/null
+++ b/boost/metaparse/util/in_range_c.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_METAPARSE_UTIL_IN_RANGE_C_HPP
+#define BOOST_METAPARSE_UTIL_IN_RANGE_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/util/in_range_c.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace util
+ {
+ using v1::util::in_range_c;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/util/int_to_digit.hpp b/boost/metaparse/util/int_to_digit.hpp
new file mode 100644
index 0000000000..4c581b5a73
--- /dev/null
+++ b/boost/metaparse/util/int_to_digit.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_METAPARSE_UTIL_INT_TO_DIGIT_HPP
+#define BOOST_METAPARSE_UTIL_INT_TO_DIGIT_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/util/int_to_digit.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace util
+ {
+ using v1::util::int_to_digit;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/util/int_to_digit_c.hpp b/boost/metaparse/util/int_to_digit_c.hpp
new file mode 100644
index 0000000000..95ff70e922
--- /dev/null
+++ b/boost/metaparse/util/int_to_digit_c.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_METAPARSE_UTIL_INT_TO_DIGIT_C_HPP
+#define BOOST_METAPARSE_UTIL_INT_TO_DIGIT_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/util/int_to_digit_c.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace util
+ {
+ using v1::util::int_to_digit_c;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/util/is_digit.hpp b/boost/metaparse/util/is_digit.hpp
new file mode 100644
index 0000000000..929cef6f03
--- /dev/null
+++ b/boost/metaparse/util/is_digit.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_METAPARSE_UTIL_IS_DIGIT_HPP
+#define BOOST_METAPARSE_UTIL_IS_DIGIT_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/util/is_digit.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace util
+ {
+ using v1::util::is_digit;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/util/is_lcase_letter.hpp b/boost/metaparse/util/is_lcase_letter.hpp
new file mode 100644
index 0000000000..5a9f31fcea
--- /dev/null
+++ b/boost/metaparse/util/is_lcase_letter.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_METAPARSE_UTIL_IS_LCASE_LETTER_HPP
+#define BOOST_METAPARSE_UTIL_IS_LCASE_LETTER_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/util/is_lcase_letter.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace util
+ {
+ using v1::util::is_lcase_letter;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/util/is_letter.hpp b/boost/metaparse/util/is_letter.hpp
new file mode 100644
index 0000000000..a1fa8bb8e5
--- /dev/null
+++ b/boost/metaparse/util/is_letter.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_METAPARSE_UTIL_IS_LETTER_HPP
+#define BOOST_METAPARSE_UTIL_IS_LETTER_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/util/is_letter.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace util
+ {
+ using v1::util::is_letter;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/util/is_ucase_letter.hpp b/boost/metaparse/util/is_ucase_letter.hpp
new file mode 100644
index 0000000000..884ef9152e
--- /dev/null
+++ b/boost/metaparse/util/is_ucase_letter.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_METAPARSE_UTIL_IS_UCASE_LETTER_HPP
+#define BOOST_METAPARSE_UTIL_IS_UCASE_LETTER_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/util/is_ucase_letter.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace util
+ {
+ using v1::util::is_ucase_letter;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/util/is_whitespace.hpp b/boost/metaparse/util/is_whitespace.hpp
new file mode 100644
index 0000000000..6221dd243a
--- /dev/null
+++ b/boost/metaparse/util/is_whitespace.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_METAPARSE_UTIL_IS_WHITESPACE_HPP
+#define BOOST_METAPARSE_UTIL_IS_WHITESPACE_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/util/is_whitespace.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace util
+ {
+ using v1::util::is_whitespace;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/util/is_whitespace_c.hpp b/boost/metaparse/util/is_whitespace_c.hpp
new file mode 100644
index 0000000000..eccdf59f5d
--- /dev/null
+++ b/boost/metaparse/util/is_whitespace_c.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_METAPARSE_UTIL_IS_WHITESPACE_C_HPP
+#define BOOST_METAPARSE_UTIL_IS_WHITESPACE_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/util/is_whitespace_c.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace util
+ {
+ using v1::util::is_whitespace_c;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/accept.hpp b/boost/metaparse/v1/accept.hpp
new file mode 100644
index 0000000000..075c997d68
--- /dev/null
+++ b/boost/metaparse/v1/accept.hpp
@@ -0,0 +1,36 @@
+#ifndef BOOST_METAPARSE_V1_ACCEPT_HPP
+#define BOOST_METAPARSE_V1_ACCEPT_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/fwd/accept.hpp>
+#include <boost/metaparse/v1/accept_tag.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class Result, class Remaining, class Pos>
+ struct accept
+ {
+ typedef accept_tag tag;
+
+ typedef
+ accept<Result, typename Remaining::type, typename Pos::type>
+ type;
+
+ typedef Result result;
+ typedef Remaining remaining;
+ typedef Pos source_position;
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/accept_tag.hpp b/boost/metaparse/v1/accept_tag.hpp
new file mode 100644
index 0000000000..82d03dd4dd
--- /dev/null
+++ b/boost/metaparse/v1/accept_tag.hpp
@@ -0,0 +1,47 @@
+#ifndef BOOST_METAPARSE_V1_ACCEPT_TAG_HPP
+#define BOOST_METAPARSE_V1_ACCEPT_TAG_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/fwd/get_remaining.hpp>
+#include <boost/metaparse/v1/fwd/get_position.hpp>
+#include <boost/metaparse/v1/fwd/get_result.hpp>
+
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ struct accept_tag { typedef accept_tag type; };
+
+ template <>
+ struct get_position_impl<accept_tag>
+ {
+ template <class A>
+ struct apply : A::source_position {};
+ };
+
+ template <>
+ struct get_remaining_impl<accept_tag>
+ {
+ template <class A>
+ struct apply : A::remaining {};
+ };
+
+ template <>
+ struct get_result_impl<accept_tag>
+ {
+ template <class A>
+ struct apply { typedef typename A::result type; };
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/accept_when.hpp b/boost/metaparse/v1/accept_when.hpp
new file mode 100644
index 0000000000..425064dcd5
--- /dev/null
+++ b/boost/metaparse/v1/accept_when.hpp
@@ -0,0 +1,59 @@
+#ifndef BOOST_METAPARSE_V1_ACCEPT_WHEN_HPP
+#define BOOST_METAPARSE_V1_ACCEPT_WHEN_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/get_result.hpp>
+#include <boost/metaparse/v1/reject.hpp>
+#include <boost/metaparse/v1/is_error.hpp>
+
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/eval_if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class Pred, class Msg>
+ struct accept_when
+ {
+ private:
+ struct unchecked
+ {
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::eval_if<
+ typename Pred::template apply<
+ typename get_result<typename P::template apply<S, Pos> >::type
+ >::type,
+ typename P::template apply<S, Pos>,
+ reject<Msg, Pos>
+ >
+ {};
+ };
+ public:
+ typedef accept_when type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::if_<
+ is_error<typename P::template apply<S, Pos> >,
+ P,
+ unchecked
+ >::type::template apply<
+ S,
+ Pos
+ >
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/alphanum.hpp b/boost/metaparse/v1/alphanum.hpp
new file mode 100644
index 0000000000..e46386344e
--- /dev/null
+++ b/boost/metaparse/v1/alphanum.hpp
@@ -0,0 +1,25 @@
+#ifndef BOOST_METAPARSE_V1_ALPHANUM_HPP
+#define BOOST_METAPARSE_V1_ALPHANUM_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/one_of.hpp>
+#include <boost/metaparse/v1/digit.hpp>
+#include <boost/metaparse/v1/letter.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ typedef one_of<letter, digit> alphanum;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/always.hpp b/boost/metaparse/v1/always.hpp
new file mode 100644
index 0000000000..0a10ff4573
--- /dev/null
+++ b/boost/metaparse/v1/always.hpp
@@ -0,0 +1,51 @@
+#ifndef BOOST_METAPARSE_V1_ALWAYS_HPP
+#define BOOST_METAPARSE_V1_ALWAYS_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/accept.hpp>
+#include <boost/metaparse/v1/is_error.hpp>
+#include <boost/metaparse/v1/get_remaining.hpp>
+#include <boost/metaparse/v1/get_position.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class Result>
+ struct always
+ {
+ private:
+ template <class Res>
+ struct apply_unchecked :
+ accept<
+ Result,
+ typename get_remaining<Res>::type,
+ typename get_position<Res>::type
+ >
+ {};
+ public:
+ typedef always 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/always_c.hpp b/boost/metaparse/v1/always_c.hpp
new file mode 100644
index 0000000000..4cc06e1169
--- /dev/null
+++ b/boost/metaparse/v1/always_c.hpp
@@ -0,0 +1,25 @@
+#ifndef BOOST_METAPARSE_V1_ALWAYS_C_HPP
+#define BOOST_METAPARSE_V1_ALWAYS_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/always.hpp>
+#include <boost/metaparse/v1/lit_c.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <char C, class Result>
+ struct always_c : always<lit_c<C>, Result> {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/build_parser.hpp b/boost/metaparse/v1/build_parser.hpp
new file mode 100644
index 0000000000..692fcf74ad
--- /dev/null
+++ b/boost/metaparse/v1/build_parser.hpp
@@ -0,0 +1,66 @@
+#ifndef BOOST_METAPARSE_V1_BUILD_PARSER_HPP
+#define BOOST_METAPARSE_V1_BUILD_PARSER_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/fwd/build_parser.hpp>
+#include <boost/metaparse/v1/start.hpp>
+#include <boost/metaparse/v1/get_result.hpp>
+#include <boost/metaparse/v1/get_position.hpp>
+#include <boost/metaparse/v1/get_message.hpp>
+#include <boost/metaparse/v1/get_line.hpp>
+#include <boost/metaparse/v1/get_col.hpp>
+#include <boost/metaparse/v1/is_error.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+
+#include <boost/static_assert.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <int Line, int Col, class Msg>
+ struct x__________________PARSING_FAILED__________________x
+ {
+ BOOST_STATIC_ASSERT(Line == Line + 1);
+ };
+
+ template <class P, class S>
+ struct parsing_failed :
+ x__________________PARSING_FAILED__________________x<
+ get_line<
+ get_position<typename P::template apply<S, start> >
+ >::type::value,
+ get_col<
+ get_position<typename P::template apply<S, start> >
+ >::type::value,
+ typename get_message<typename P::template apply<S, start> >::type
+ >
+ {};
+
+ template <class P>
+ struct build_parser
+ {
+ typedef build_parser type;
+
+ template <class S>
+ struct apply :
+ boost::mpl::eval_if<
+ typename is_error<typename P::template apply<S, start> >::type,
+ parsing_failed<P, S>,
+ get_result<typename P::template apply<S, start> >
+ >
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/change_error_message.hpp b/boost/metaparse/v1/change_error_message.hpp
new file mode 100644
index 0000000000..00077c930c
--- /dev/null
+++ b/boost/metaparse/v1/change_error_message.hpp
@@ -0,0 +1,39 @@
+#ifndef BOOST_METAPARSE_V1_CHANGE_ERROR_MESSAGE_HPP
+#define BOOST_METAPARSE_V1_CHANGE_ERROR_MESSAGE_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/is_error.hpp>
+#include <boost/metaparse/v1/reject.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class Msg>
+ struct change_error_message
+ {
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::eval_if<
+ typename is_error<typename P::template apply<S, Pos> >::type,
+ reject<Msg, Pos>,
+ typename P::template apply<S, Pos>
+ >
+ {};
+
+ typedef change_error_message type;
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/debug_parsing_error.hpp b/boost/metaparse/v1/debug_parsing_error.hpp
new file mode 100644
index 0000000000..ea44188838
--- /dev/null
+++ b/boost/metaparse/v1/debug_parsing_error.hpp
@@ -0,0 +1,105 @@
+#ifndef BOOST_METAPARSE_V1_DEBUG_PARSING_ERROR_HPP
+#define BOOST_METAPARSE_V1_DEBUG_PARSING_ERROR_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/fwd/build_parser.hpp>
+#include <boost/metaparse/v1/start.hpp>
+#include <boost/metaparse/v1/is_error.hpp>
+#include <boost/metaparse/v1/get_remaining.hpp>
+
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/string.hpp>
+
+#include <iostream>
+#include <cstdlib>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class S>
+ class debug_parsing_error
+ {
+ public:
+ debug_parsing_error()
+ {
+ using std::cout;
+ using std::endl;
+ using boost::mpl::c_str;
+
+ typedef display<typename P::template apply<S, start>::type> runner;
+
+ cout << "Compile-time parsing results" << endl;
+ cout << "----------------------------" << endl;
+ cout << "Input text:" << endl;
+ cout << c_str<S>::type::value << endl;
+ cout << endl;
+ runner::run();
+
+ std::exit(0);
+ }
+
+ typedef debug_parsing_error type;
+ private:
+ template <class Result>
+ struct display_error
+ {
+ static void run()
+ {
+ typedef typename Result::type R;
+
+ std::cout
+ << "Parsing failed:" << std::endl
+ << "line " << get_line<typename R::source_position>::type::value
+ << ", col " << get_col<typename R::source_position>::type::value
+ << ": "
+ << R::message::type::get_value() << std::endl;
+ }
+ };
+
+ template <class Result>
+ struct display_no_error
+ {
+ static void run()
+ {
+ using std::cout;
+ using std::endl;
+ using boost::mpl::c_str;
+
+ typedef typename get_remaining<Result>::type remaining_string;
+
+ cout
+ << "Parsing was successful. Remaining string is:" << endl
+ << c_str<remaining_string>::type::value << endl;
+ }
+ };
+
+ template <class Result>
+ struct display :
+ boost::mpl::if_<
+ typename is_error<Result>::type,
+ display_error<Result>,
+ display_no_error<Result>
+ >::type
+ {};
+ };
+
+ // Special case to handle when DebugParsingError is used with build_parser
+ // (it shouldn't be)
+ template <class P, class S>
+ class debug_parsing_error<build_parser<P>, S> :
+ debug_parsing_error<P, S>
+ {};
+ }
+ }
+}
+
+#endif
+
+
diff --git a/boost/metaparse/v1/define_error.hpp b/boost/metaparse/v1/define_error.hpp
new file mode 100644
index 0000000000..15a7c671b7
--- /dev/null
+++ b/boost/metaparse/v1/define_error.hpp
@@ -0,0 +1,25 @@
+#ifndef BOOST_METAPARSE_V1_DEFINE_ERROR_HPP
+#define BOOST_METAPARSE_V1_DEFINE_ERROR_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 <string>
+
+#ifdef BOOST_METAPARSE_V1_DEFINE_ERROR
+# error BOOST_METAPARSE_V1_DEFINE_ERROR already defined
+#endif
+#define BOOST_METAPARSE_V1_DEFINE_ERROR(name, msg) \
+ struct name \
+ { \
+ typedef name type; \
+ static std::string get_value() \
+ { \
+ return msg; \
+ } \
+ }
+
+#endif
+
diff --git a/boost/metaparse/v1/digit.hpp b/boost/metaparse/v1/digit.hpp
new file mode 100644
index 0000000000..a2e3da9df4
--- /dev/null
+++ b/boost/metaparse/v1/digit.hpp
@@ -0,0 +1,34 @@
+#ifndef BOOST_METAPARSE_V1_DIGIT_HPP
+#define BOOST_METAPARSE_V1_DIGIT_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/error/digit_expected.hpp>
+#include <boost/metaparse/v1/accept_when.hpp>
+#include <boost/metaparse/v1/one_char.hpp>
+#include <boost/metaparse/v1/change_error_message.hpp>
+
+#include <boost/metaparse/v1/util/is_digit.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ typedef
+ accept_when<
+ change_error_message<one_char, error::digit_expected>,
+ util::is_digit<>,
+ error::digit_expected
+ >
+ digit;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/digit_val.hpp b/boost/metaparse/v1/digit_val.hpp
new file mode 100644
index 0000000000..1f2faae6a8
--- /dev/null
+++ b/boost/metaparse/v1/digit_val.hpp
@@ -0,0 +1,26 @@
+#ifndef BOOST_METAPARSE_V1_DIGIT_VAL_HPP
+#define BOOST_METAPARSE_V1_DIGIT_VAL_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/digit.hpp>
+#include <boost/metaparse/v1/transform.hpp>
+
+#include <boost/metaparse/v1/util/digit_to_int.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ typedef transform<digit, util::digit_to_int<> > digit_val;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/empty.hpp b/boost/metaparse/v1/empty.hpp
new file mode 100644
index 0000000000..7ffe604699
--- /dev/null
+++ b/boost/metaparse/v1/empty.hpp
@@ -0,0 +1,42 @@
+#ifndef BOOST_METAPARSE_V1_EMPTY_HPP
+#define BOOST_METAPARSE_V1_EMPTY_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2010 - 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/error/end_of_input_expected.hpp>
+#include <boost/metaparse/v1/reject.hpp>
+#include <boost/metaparse/v1/accept.hpp>
+#include <boost/metaparse/v1/define_error.hpp>
+
+#include <boost/mpl/empty.hpp>
+#include <boost/mpl/if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class Result>
+ struct empty
+ {
+ typedef empty type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::if_<
+ boost::mpl::empty<S>,
+ accept<Result, S, Pos>,
+ reject<error::end_of_input_expected, Pos>
+ >
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/entire_input.hpp b/boost/metaparse/v1/entire_input.hpp
new file mode 100644
index 0000000000..b7ab885137
--- /dev/null
+++ b/boost/metaparse/v1/entire_input.hpp
@@ -0,0 +1,33 @@
+#ifndef BOOST_METAPARSE_V1_ENTIRE_INPUT_HPP
+#define BOOST_METAPARSE_V1_ENTIRE_INPUT_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/first_of.hpp>
+#include <boost/metaparse/v1/empty.hpp>
+#include <boost/metaparse/v1/change_error_message.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class Msg = error::end_of_input_expected>
+ struct entire_input :
+ first_of<P, change_error_message<empty<void>, Msg> >
+ {};
+
+ template <class P>
+ struct entire_input<P, error::end_of_input_expected> :
+ first_of<P, empty<void> >
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/error/digit_expected.hpp b/boost/metaparse/v1/error/digit_expected.hpp
new file mode 100644
index 0000000000..77c20d3750
--- /dev/null
+++ b/boost/metaparse/v1/error/digit_expected.hpp
@@ -0,0 +1,26 @@
+#ifndef BOOST_METAPARSE_V1_ERROR_DIGIT_EXPECTED_HPP
+#define BOOST_METAPARSE_V1_ERROR_DIGIT_EXPECTED_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/define_error.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace error
+ {
+ BOOST_METAPARSE_V1_DEFINE_ERROR(digit_expected, "Digit expected");
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/error/end_of_input_expected.hpp b/boost/metaparse/v1/error/end_of_input_expected.hpp
new file mode 100644
index 0000000000..01008c7b0e
--- /dev/null
+++ b/boost/metaparse/v1/error/end_of_input_expected.hpp
@@ -0,0 +1,29 @@
+#ifndef BOOST_METAPARSE_V1_END_OF_INPUT_EXPECTED_HPP
+#define BOOST_METAPARSE_V1_END_OF_INPUT_EXPECTED_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/define_error.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace error
+ {
+ BOOST_METAPARSE_V1_DEFINE_ERROR(
+ end_of_input_expected,
+ "End of input expected"
+ );
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/error/expected_to_fail.hpp b/boost/metaparse/v1/error/expected_to_fail.hpp
new file mode 100644
index 0000000000..ecd518ec35
--- /dev/null
+++ b/boost/metaparse/v1/error/expected_to_fail.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_METAPARSE_V1_ERROR_EXPECTED_TO_FAIL_HPP
+#define BOOST_METAPARSE_V1_ERROR_EXPECTED_TO_FAIL_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/define_error.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace error
+ {
+ BOOST_METAPARSE_V1_DEFINE_ERROR(
+ expected_to_fail,
+ "Parser expected to fail"
+ );
+ }
+ }
+ }
+}
+
+#endif
+
+
diff --git a/boost/metaparse/v1/error/index_out_of_range.hpp b/boost/metaparse/v1/error/index_out_of_range.hpp
new file mode 100644
index 0000000000..de87968128
--- /dev/null
+++ b/boost/metaparse/v1/error/index_out_of_range.hpp
@@ -0,0 +1,41 @@
+#ifndef BOOST_METAPARSE_V1_ERROR_INDEX_OUT_OF_RANGE_HPP
+#define BOOST_METAPARSE_V1_ERROR_INDEX_OUT_OF_RANGE_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 <iostream>
+#include <string>
+#include <sstream>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace error
+ {
+ template <int From, int To, int N>
+ struct index_out_of_range
+ {
+ typedef index_out_of_range type;
+
+ static std::string get_value()
+ {
+ std::ostringstream s;
+ s
+ << "index (" << N << ") out of range ["
+ << From << "-" << To << "]";
+ return s.str();
+ }
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/error/letter_expected.hpp b/boost/metaparse/v1/error/letter_expected.hpp
new file mode 100644
index 0000000000..80858c00e7
--- /dev/null
+++ b/boost/metaparse/v1/error/letter_expected.hpp
@@ -0,0 +1,26 @@
+#ifndef BOOST_METAPARSE_V1_ERROR_LETTER_EXPECTED_HPP
+#define BOOST_METAPARSE_V1_ERROR_LETTER_EXPECTED_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/define_error.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace error
+ {
+ BOOST_METAPARSE_V1_DEFINE_ERROR(letter_expected, "Letter expected");
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/error/literal_expected.hpp b/boost/metaparse/v1/error/literal_expected.hpp
new file mode 100644
index 0000000000..2e1bdf8437
--- /dev/null
+++ b/boost/metaparse/v1/error/literal_expected.hpp
@@ -0,0 +1,36 @@
+#ifndef BOOST_METAPARSE_V1_ERROR_LITERAL_EXPECTED_HPP
+#define BOOST_METAPARSE_V1_ERROR_LITERAL_EXPECTED_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 <string>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace error
+ {
+ template <char C>
+ struct literal_expected
+ {
+ typedef literal_expected type;
+
+ static std::string get_value()
+ {
+ return std::string("Expected: ") + C;
+ }
+ };
+ }
+ }
+ }
+}
+
+#endif
+
+
diff --git a/boost/metaparse/v1/error/none_of_the_expected_cases_found.hpp b/boost/metaparse/v1/error/none_of_the_expected_cases_found.hpp
new file mode 100644
index 0000000000..38ddea3f37
--- /dev/null
+++ b/boost/metaparse/v1/error/none_of_the_expected_cases_found.hpp
@@ -0,0 +1,29 @@
+#ifndef BOOST_METAPARSE_V1_ERROR_NONE_OF_THE_EXPECTED_CASES_FOUND_HPP
+#define BOOST_METAPARSE_V1_ERROR_NONE_OF_THE_EXPECTED_CASES_FOUND_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/define_error.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace error
+ {
+ BOOST_METAPARSE_V1_DEFINE_ERROR(
+ none_of_the_expected_cases_found,
+ "None of the expected cases found"
+ );
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/error/unexpected_character.hpp b/boost/metaparse/v1/error/unexpected_character.hpp
new file mode 100644
index 0000000000..040f120158
--- /dev/null
+++ b/boost/metaparse/v1/error/unexpected_character.hpp
@@ -0,0 +1,29 @@
+#ifndef BOOST_METAPARSE_V1_ERROR_UNEXPECTED_CHARACTER_HPP
+#define BOOST_METAPARSE_V1_ERROR_UNEXPECTED_CHARACTER_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/define_error.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace error
+ {
+ BOOST_METAPARSE_V1_DEFINE_ERROR(
+ unexpected_character,
+ "Unexpected character"
+ );
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/error/unexpected_end_of_input.hpp b/boost/metaparse/v1/error/unexpected_end_of_input.hpp
new file mode 100644
index 0000000000..c89933202a
--- /dev/null
+++ b/boost/metaparse/v1/error/unexpected_end_of_input.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_METAPARSE_V1_ERROR_UNEXPECTED_END_OF_INPUT_HPP
+#define BOOST_METAPARSE_V1_ERROR_UNEXPECTED_END_OF_INPUT_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/define_error.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace error
+ {
+ BOOST_METAPARSE_V1_DEFINE_ERROR(
+ unexpected_end_of_input,
+ "Unexpected end of input"
+ );
+ }
+ }
+ }
+}
+
+#endif
+
+
diff --git a/boost/metaparse/v1/error/unpaired.hpp b/boost/metaparse/v1/error/unpaired.hpp
new file mode 100644
index 0000000000..71e8561b1c
--- /dev/null
+++ b/boost/metaparse/v1/error/unpaired.hpp
@@ -0,0 +1,50 @@
+#ifndef BOOST_METAPARSE_V1_ERROR_UNPAIRED_HPP
+#define BOOST_METAPARSE_V1_ERROR_UNPAIRED_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/mpl/vector.hpp>
+
+#include <iostream>
+#include <string>
+#include <sstream>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace error
+ {
+ template <int Line, int Col, class Msg = boost::mpl::na>
+ struct unpaired
+ {
+ typedef unpaired type;
+
+ static std::string get_value()
+ {
+ std::ostringstream s;
+ s << Msg::get_value() << " (see " << Line << ":" << Col << ")";
+ return s.str();
+ }
+ };
+
+ template <int Line, int Col>
+ struct unpaired<Line, Col, boost::mpl::na>
+ {
+ typedef unpaired type;
+
+ template <class Msg = boost::mpl::na>
+ struct apply : unpaired<Line, Col, Msg> {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/error/whitespace_expected.hpp b/boost/metaparse/v1/error/whitespace_expected.hpp
new file mode 100644
index 0000000000..a4a4feed04
--- /dev/null
+++ b/boost/metaparse/v1/error/whitespace_expected.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_METAPARSE_V1_ERROR_WHITESPACE_EXPECTED_HPP
+#define BOOST_METAPARSE_V1_ERROR_WHITESPACE_EXPECTED_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/define_error.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace error
+ {
+ BOOST_METAPARSE_V1_DEFINE_ERROR(
+ whitespace_expected,
+ "Whitespace expected"
+ );
+ }
+ }
+ }
+}
+
+#endif
+
+
diff --git a/boost/metaparse/v1/except.hpp b/boost/metaparse/v1/except.hpp
new file mode 100644
index 0000000000..52fb151d5d
--- /dev/null
+++ b/boost/metaparse/v1/except.hpp
@@ -0,0 +1,40 @@
+#ifndef BOOST_METAPARSE_V1_EXCEPT_HPP
+#define BOOST_METAPARSE_V1_EXCEPT_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2009 - 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/is_error.hpp>
+#include <boost/metaparse/v1/accept.hpp>
+#include <boost/metaparse/v1/reject.hpp>
+
+#include <boost/mpl/if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class Result, class ErrorMsg>
+ struct except
+ {
+ typedef except type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::if_<
+ is_error<typename P::template apply<S, Pos> >,
+ accept<Result, S, Pos>,
+ reject<ErrorMsg, Pos>
+ >
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/fail.hpp b/boost/metaparse/v1/fail.hpp
new file mode 100644
index 0000000000..b8f802698c
--- /dev/null
+++ b/boost/metaparse/v1/fail.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_METAPARSE_V1_FAIL_HPP
+#define BOOST_METAPARSE_V1_FAIL_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/reject.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class Msg>
+ struct fail
+ {
+ typedef fail type;
+
+ template <class S, class Pos>
+ struct apply : reject<Msg, Pos> {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/fail_at_first_char_expected.hpp b/boost/metaparse/v1/fail_at_first_char_expected.hpp
new file mode 100644
index 0000000000..ff7046a831
--- /dev/null
+++ b/boost/metaparse/v1/fail_at_first_char_expected.hpp
@@ -0,0 +1,58 @@
+#ifndef BOOST_METAPARSE_V1_FAIL_AT_FIRST_CHAR_EXPECTED_HPP
+#define BOOST_METAPARSE_V1_FAIL_AT_FIRST_CHAR_EXPECTED_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/impl/void_.hpp>
+#include <boost/metaparse/v1/accept.hpp>
+#include <boost/metaparse/v1/reject.hpp>
+#include <boost/metaparse/v1/is_error.hpp>
+#include <boost/metaparse/v1/get_position.hpp>
+
+#include <boost/metaparse/v1/error/expected_to_fail.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/equal_to.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P>
+ struct fail_at_first_char_expected
+ {
+ private:
+ template <class S, class Pos>
+ struct apply_err :
+ boost::mpl::eval_if<
+ typename boost::mpl::equal_to<
+ Pos,
+ typename get_position<typename P::template apply<S, Pos> >::type
+ >::type,
+ accept<impl::void_, S, Pos>,
+ typename P::template apply<S, Pos>
+ >
+ {};
+ public:
+ typedef fail_at_first_char_expected type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::eval_if<
+ typename is_error<typename P::template apply<S, Pos> >::type,
+ apply_err<S, Pos>,
+ reject<error::expected_to_fail, Pos>
+ >
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/fail_tag.hpp b/boost/metaparse/v1/fail_tag.hpp
new file mode 100644
index 0000000000..3a0c0c17d9
--- /dev/null
+++ b/boost/metaparse/v1/fail_tag.hpp
@@ -0,0 +1,42 @@
+#ifndef BOOST_METAPARSE_V1_FAIL_TAG_HPP
+#define BOOST_METAPARSE_V1_FAIL_TAG_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2009 - 2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#include <boost/metaparse/v1/fwd/get_message.hpp>
+#include <boost/metaparse/v1/fwd/get_position.hpp>
+
+#include <iostream>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ struct fail_tag { typedef fail_tag type; };
+
+ template <>
+ struct get_message_impl<fail_tag>
+ {
+ template <class A>
+ struct apply { typedef typename A::message type; };
+ };
+
+ template <>
+ struct get_position_impl<fail_tag>
+ {
+ template <class A>
+ struct apply : A::source_position {};
+ };
+ }
+ }
+}
+
+#endif
+
+
diff --git a/boost/metaparse/v1/first_of.hpp b/boost/metaparse/v1/first_of.hpp
new file mode 100644
index 0000000000..1456dda459
--- /dev/null
+++ b/boost/metaparse/v1/first_of.hpp
@@ -0,0 +1,35 @@
+#ifndef BOOST_METAPARSE_V1_FIRST_OF_HPP
+#define BOOST_METAPARSE_V1_FIRST_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/nth_of.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 first_of :
+ nth_of_c<
+ 0,
+ BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_SEQUENCE_SIZE, P)
+ >
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/foldl.hpp b/boost/metaparse/v1/foldl.hpp
new file mode 100644
index 0000000000..b3938ee6ff
--- /dev/null
+++ b/boost/metaparse/v1/foldl.hpp
@@ -0,0 +1,65 @@
+#ifndef BOOST_METAPARSE_V1_FOLDL_HPP
+#define BOOST_METAPARSE_V1_FOLDL_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/accept.hpp>
+#include <boost/metaparse/v1/is_error.hpp>
+#include <boost/metaparse/v1/get_position.hpp>
+#include <boost/metaparse/v1/get_result.hpp>
+#include <boost/metaparse/v1/get_remaining.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class State, class ForwardOp>
+ struct foldl
+ {
+ private:
+ template <class Res>
+ struct apply_unchecked :
+ // foldl never returns error
+ // I need to use apply_wrap, and not apply, because apply would
+ // build a metafunction class from foldl<P, State, ForwardOp>
+ // when ForwardOp is a lambda expression.
+ foldl<
+ P,
+ typename ForwardOp::template apply<
+ typename State::type,
+ typename get_result<Res>::type
+ >,
+ ForwardOp
+ >::template apply<
+ typename get_remaining<Res>::type,
+ typename get_position<Res>::type
+ >
+ {};
+
+ template <class S, class Pos>
+ struct next_iteration : accept<typename State::type, S, Pos> {};
+ public:
+ typedef foldl type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::eval_if<
+ typename is_error<typename P::template apply<S, Pos> >::type,
+ next_iteration<S, Pos>,
+ apply_unchecked<typename P::template apply<S, Pos> >
+ >
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/foldl1.hpp b/boost/metaparse/v1/foldl1.hpp
new file mode 100644
index 0000000000..8b48f01c9a
--- /dev/null
+++ b/boost/metaparse/v1/foldl1.hpp
@@ -0,0 +1,38 @@
+#ifndef BOOST_METAPARSE_V1_FOLDL1_HPP
+#define BOOST_METAPARSE_V1_FOLDL1_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/foldl.hpp>
+
+#include <boost/mpl/if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class State, class ForwardOp>
+ struct foldl1
+ {
+ typedef foldl1 type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::if_<
+ is_error<typename P::template apply<S, Pos> >,
+ P,
+ foldl<P, State, ForwardOp>
+ >::type::template apply<S, Pos>
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/foldl_reject_incomplete.hpp b/boost/metaparse/v1/foldl_reject_incomplete.hpp
new file mode 100644
index 0000000000..82e08a7ae6
--- /dev/null
+++ b/boost/metaparse/v1/foldl_reject_incomplete.hpp
@@ -0,0 +1,77 @@
+#ifndef BOOST_METAPARSE_V1_FOLDL_REJECT_INCOMPLETE_HPP
+#define BOOST_METAPARSE_V1_FOLDL_REJECT_INCOMPLETE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/fail_at_first_char_expected.hpp>
+#include <boost/metaparse/v1/is_error.hpp>
+#include <boost/metaparse/v1/get_position.hpp>
+#include <boost/metaparse/v1/get_result.hpp>
+#include <boost/metaparse/v1/get_remaining.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/equal_to.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class State, class ForwardOp>
+ struct foldl_reject_incomplete
+ {
+ private:
+ template <class Res>
+ struct apply_unchecked :
+ // I need to use apply_wrap, and not apply, because apply would
+ // build a metafunction class from foldl<P, State, ForwardOp>
+ // when ForwardOp is a lambda expression.
+ foldl_reject_incomplete<
+ P,
+ typename ForwardOp::template apply<
+ typename State::type,
+ typename get_result<Res>::type
+ >,
+ ForwardOp
+ >::template apply<
+ typename get_remaining<Res>::type,
+ typename get_position<Res>::type
+ >
+ {};
+
+ template <class S, class Pos>
+ struct accept_state : accept<typename State::type, S, Pos> {};
+
+ template <class S, class Pos>
+ struct end_of_folding :
+ boost::mpl::eval_if<
+ typename boost::mpl::equal_to<
+ typename Pos::type,
+ typename get_position<typename P::template apply<S, Pos> >::type
+ >::type,
+ accept_state<S, Pos>,
+ typename P::template apply<S, Pos>
+ >
+ {};
+ public:
+ typedef foldl_reject_incomplete type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::eval_if<
+ typename is_error<typename P::template apply<S, Pos> >::type,
+ end_of_folding<S, Pos>,
+ apply_unchecked<typename P::template apply<S, Pos> >
+ >
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/foldl_reject_incomplete1.hpp b/boost/metaparse/v1/foldl_reject_incomplete1.hpp
new file mode 100644
index 0000000000..f1382cfdf9
--- /dev/null
+++ b/boost/metaparse/v1/foldl_reject_incomplete1.hpp
@@ -0,0 +1,38 @@
+#ifndef BOOST_METAPARSE_V1_FOLDL_REJECT_INCOMPLETE1_HPP
+#define BOOST_METAPARSE_V1_FOLDL_REJECT_INCOMPLETE1_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/foldl_reject_incomplete.hpp>
+
+#include <boost/mpl/if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class State, class ForwardOp>
+ struct foldl_reject_incomplete1
+ {
+ typedef foldl_reject_incomplete1 type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::if_<
+ is_error<typename P::template apply<S, Pos> >,
+ P,
+ foldl_reject_incomplete<P, State, ForwardOp>
+ >::type::template apply<S, Pos>
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/foldl_reject_incomplete_start_with_parser.hpp b/boost/metaparse/v1/foldl_reject_incomplete_start_with_parser.hpp
new file mode 100644
index 0000000000..b9345af872
--- /dev/null
+++ b/boost/metaparse/v1/foldl_reject_incomplete_start_with_parser.hpp
@@ -0,0 +1,55 @@
+#ifndef BOOST_METAPARSE_V1_FOLDL_REJECT_INCOMPLETE_START_WITH_PARSER_HPP
+#define BOOST_METAPARSE_V1_FOLDL_REJECT_INCOMPLETE_START_WITH_PARSER_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/foldl_reject_incomplete.hpp>
+#include <boost/metaparse/v1/get_remaining.hpp>
+#include <boost/metaparse/v1/get_position.hpp>
+#include <boost/metaparse/v1/get_result.hpp>
+#include <boost/metaparse/v1/is_error.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class StateP, class ForwardOp>
+ class foldl_reject_incomplete_start_with_parser
+ {
+ private:
+ template <class Res>
+ struct apply_unchecked :
+ foldl_reject_incomplete<
+ P,
+ typename get_result<Res>::type,
+ ForwardOp
+ >::template apply<
+ typename get_remaining<Res>::type,
+ typename get_position<Res>::type
+ >
+ {};
+ public:
+ typedef foldl_reject_incomplete_start_with_parser type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::eval_if<
+ typename is_error<typename StateP::template apply<S, Pos> >::type,
+ typename StateP::template apply<S, Pos>,
+ apply_unchecked<typename StateP::template apply<S, Pos> >
+ >
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/foldl_start_with_parser.hpp b/boost/metaparse/v1/foldl_start_with_parser.hpp
new file mode 100644
index 0000000000..4112f13955
--- /dev/null
+++ b/boost/metaparse/v1/foldl_start_with_parser.hpp
@@ -0,0 +1,45 @@
+#ifndef BOOST_METAPARSE_V1_FOLDL_START_WITH_PARSER_HPP
+#define BOOST_METAPARSE_V1_FOLDL_START_WITH_PARSER_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/foldl.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class StateP, class ForwardOp>
+ class foldl_start_with_parser
+ {
+ private:
+ template <class Res>
+ struct apply_unchecked :
+ foldl<P, typename get_result<Res>::type, ForwardOp>::template apply<
+ typename get_remaining<Res>::type,
+ typename get_position<Res>::type
+ >
+ {};
+ public:
+ typedef foldl_start_with_parser type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::eval_if<
+ typename is_error<typename StateP::template apply<S, Pos> >::type,
+ typename StateP::template apply<S, Pos>,
+ apply_unchecked<typename StateP::template apply<S, Pos> >
+ >
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/foldr.hpp b/boost/metaparse/v1/foldr.hpp
new file mode 100644
index 0000000000..333f67b51d
--- /dev/null
+++ b/boost/metaparse/v1/foldr.hpp
@@ -0,0 +1,25 @@
+#ifndef BOOST_METAPARSE_V1_FOLDR_HPP
+#define BOOST_METAPARSE_V1_FOLDR_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2011 - 2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/return_.hpp>
+#include <boost/metaparse/v1/foldr_start_with_parser.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class State, class BackwardOp>
+ struct foldr : foldr_start_with_parser<P, return_<State>, BackwardOp> {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/foldr1.hpp b/boost/metaparse/v1/foldr1.hpp
new file mode 100644
index 0000000000..1746d26630
--- /dev/null
+++ b/boost/metaparse/v1/foldr1.hpp
@@ -0,0 +1,38 @@
+#ifndef BOOST_METAPARSE_V1_FOLDR1_HPP
+#define BOOST_METAPARSE_V1_FOLDR1_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/foldr.hpp>
+
+#include <boost/mpl/if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class State, class BackwardOp>
+ struct foldr1
+ {
+ typedef foldr1 type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::if_<
+ is_error<typename P::template apply<S, Pos> >,
+ P,
+ foldr<P, State, BackwardOp>
+ >::type::template apply<S, Pos>
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/foldr_reject_incomplete.hpp b/boost/metaparse/v1/foldr_reject_incomplete.hpp
new file mode 100644
index 0000000000..1e1742aa64
--- /dev/null
+++ b/boost/metaparse/v1/foldr_reject_incomplete.hpp
@@ -0,0 +1,33 @@
+#ifndef BOOST_METAPARSE_V1_FOLDR_REJECT_INCOMPLETE_HPP
+#define BOOST_METAPARSE_V1_FOLDR_REJECT_INCOMPLETE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/return_.hpp>
+#include <boost/metaparse/v1/foldr_start_with_parser.hpp>
+#include <boost/metaparse/v1/first_of.hpp>
+#include <boost/metaparse/v1/fail_at_first_char_expected.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class State, class BackwardOp>
+ struct foldr_reject_incomplete :
+ foldr_start_with_parser<
+ P,
+ first_of<return_<State>, fail_at_first_char_expected<P> >,
+ BackwardOp
+ >
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/foldr_reject_incomplete1.hpp b/boost/metaparse/v1/foldr_reject_incomplete1.hpp
new file mode 100644
index 0000000000..270d4251e9
--- /dev/null
+++ b/boost/metaparse/v1/foldr_reject_incomplete1.hpp
@@ -0,0 +1,38 @@
+#ifndef BOOST_METAPARSE_V1_FOLDR_REJECT_INCOMPLETE1_HPP
+#define BOOST_METAPARSE_V1_FOLDR_REJECT_INCOMPLETE1_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/foldr_reject_incomplete.hpp>
+
+#include <boost/mpl/if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class State, class BackwardOp>
+ struct foldr_reject_incomplete1
+ {
+ typedef foldr_reject_incomplete1 type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::if_<
+ is_error<typename P::template apply<S, Pos> >,
+ P,
+ foldr_reject_incomplete<P, State, BackwardOp>
+ >::type::template apply<S, Pos>
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/foldr_start_with_parser.hpp b/boost/metaparse/v1/foldr_start_with_parser.hpp
new file mode 100644
index 0000000000..c5f59eacf4
--- /dev/null
+++ b/boost/metaparse/v1/foldr_start_with_parser.hpp
@@ -0,0 +1,78 @@
+#ifndef BOOST_METAPARSE_V1_FOLDR_START_WITH_PARSER_HPP
+#define BOOST_METAPARSE_V1_FOLDR_START_WITH_PARSER_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/accept.hpp>
+#include <boost/metaparse/v1/is_error.hpp>
+#include <boost/metaparse/v1/get_position.hpp>
+#include <boost/metaparse/v1/get_result.hpp>
+#include <boost/metaparse/v1/get_remaining.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class StateP, class BackwardOp>
+ struct foldr_start_with_parser
+ {
+ private:
+ template <class Res, class Rem>
+ struct apply_unchecked1 :
+ accept<
+ typename BackwardOp::template apply<
+ typename get_result<Rem>::type,
+ typename get_result<Res>::type
+ >::type,
+ typename get_remaining<Rem>::type,
+ typename get_position<Rem>::type
+ >
+ {};
+
+ template <class Res>
+ struct apply_unchecked;
+ public:
+ typedef foldr_start_with_parser type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::eval_if<
+ typename is_error<typename P::template apply<S, Pos> >::type,
+ typename StateP::template apply<S, Pos>,
+ apply_unchecked<typename P::template apply<S, Pos> >
+ >
+ {};
+ private:
+ template <class Res>
+ struct apply_unchecked
+ {
+ private:
+ typedef
+ typename foldr_start_with_parser::template apply<
+ typename get_remaining<Res>::type,
+ typename get_position<Res>::type
+ >
+ parsed_remaining;
+ public:
+ typedef
+ typename boost::mpl::eval_if<
+ typename is_error<parsed_remaining>::type,
+ parsed_remaining,
+ apply_unchecked1<Res, parsed_remaining>
+ >::type
+ type;
+ };
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/fwd/accept.hpp b/boost/metaparse/v1/fwd/accept.hpp
new file mode 100644
index 0000000000..c59097eb01
--- /dev/null
+++ b/boost/metaparse/v1/fwd/accept.hpp
@@ -0,0 +1,22 @@
+#ifndef BOOST_METAPARSE_V1_FWD_ACCEPT_HPP
+#define BOOST_METAPARSE_V1_FWD_ACCEPT_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class Result, class Remaining, class Pos>
+ struct accept;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/fwd/build_parser.hpp b/boost/metaparse/v1/fwd/build_parser.hpp
new file mode 100644
index 0000000000..848def8ec2
--- /dev/null
+++ b/boost/metaparse/v1/fwd/build_parser.hpp
@@ -0,0 +1,22 @@
+#ifndef BOOST_METAPARSE_V1_FWD_BUILD_PARSER_HPP
+#define BOOST_METAPARSE_V1_FWD_BUILD_PARSER_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P>
+ struct build_parser;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/fwd/get_col.hpp b/boost/metaparse/v1/fwd/get_col.hpp
new file mode 100644
index 0000000000..fa9e2a6c35
--- /dev/null
+++ b/boost/metaparse/v1/fwd/get_col.hpp
@@ -0,0 +1,26 @@
+#ifndef BOOST_METAPARSE_V1_FWD_GET_COL_HPP
+#define BOOST_METAPARSE_V1_FWD_GET_COL_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class>
+ struct get_col;
+
+ template <class>
+ struct get_col_impl;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/fwd/get_line.hpp b/boost/metaparse/v1/fwd/get_line.hpp
new file mode 100644
index 0000000000..0f53ae9d9d
--- /dev/null
+++ b/boost/metaparse/v1/fwd/get_line.hpp
@@ -0,0 +1,25 @@
+#ifndef BOOST_METAPARSE_V1_FWD_GET_LINE_HPP
+#define BOOST_METAPARSE_V1_FWD_GET_LINE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class>
+ struct get_line_impl;
+
+ template <class>
+ struct get_line;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/fwd/get_message.hpp b/boost/metaparse/v1/fwd/get_message.hpp
new file mode 100644
index 0000000000..383e17b122
--- /dev/null
+++ b/boost/metaparse/v1/fwd/get_message.hpp
@@ -0,0 +1,25 @@
+#ifndef BOOST_METAPARSE_V1_FWD_GET_MESSAGE_HPP
+#define BOOST_METAPARSE_V1_FWD_GET_MESSAGE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class>
+ struct get_message_impl;
+
+ template <class>
+ struct get_message;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/fwd/get_position.hpp b/boost/metaparse/v1/fwd/get_position.hpp
new file mode 100644
index 0000000000..9c0ceb00df
--- /dev/null
+++ b/boost/metaparse/v1/fwd/get_position.hpp
@@ -0,0 +1,25 @@
+#ifndef BOOST_METAPARSE_V1_FWD_GET_POSITION_HPP
+#define BOOST_METAPARSE_V1_FWD_GET_POSITION_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class>
+ struct get_position_impl;
+
+ template <class>
+ struct get_position;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/fwd/get_prev_char.hpp b/boost/metaparse/v1/fwd/get_prev_char.hpp
new file mode 100644
index 0000000000..fd7fe2608a
--- /dev/null
+++ b/boost/metaparse/v1/fwd/get_prev_char.hpp
@@ -0,0 +1,25 @@
+#ifndef BOOST_METAPARSE_V1_FWD_GET_PREV_CHAR_HPP
+#define BOOST_METAPARSE_V1_FWD_GET_PREV_CHAR_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class>
+ struct get_prev_char_impl;
+
+ template <class>
+ struct get_prev_char;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/fwd/get_remaining.hpp b/boost/metaparse/v1/fwd/get_remaining.hpp
new file mode 100644
index 0000000000..04d10f50c9
--- /dev/null
+++ b/boost/metaparse/v1/fwd/get_remaining.hpp
@@ -0,0 +1,25 @@
+#ifndef BOOST_METAPARSE_V1_FWD_GET_REMAINING_HPP
+#define BOOST_METAPARSE_V1_FWD_GET_REMAINING_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class>
+ struct get_remaining_impl;
+
+ template <class>
+ struct get_remaining;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/fwd/get_result.hpp b/boost/metaparse/v1/fwd/get_result.hpp
new file mode 100644
index 0000000000..529d9cf921
--- /dev/null
+++ b/boost/metaparse/v1/fwd/get_result.hpp
@@ -0,0 +1,25 @@
+#ifndef BOOST_METAPARSE_V1_FWD_GET_RESULT_HPP
+#define BOOST_METAPARSE_V1_FWD_GET_RESULT_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class>
+ struct get_result_impl;
+
+ template <class>
+ struct get_result;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/fwd/next_char.hpp b/boost/metaparse/v1/fwd/next_char.hpp
new file mode 100644
index 0000000000..a00cc27d54
--- /dev/null
+++ b/boost/metaparse/v1/fwd/next_char.hpp
@@ -0,0 +1,25 @@
+#ifndef BOOST_METAPARSE_V1_FWD_NEXT_CHAR_HPP
+#define BOOST_METAPARSE_V1_FWD_NEXT_CHAR_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P>
+ struct next_char_impl;
+
+ template <class P, class Ch>
+ struct next_char;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/fwd/next_line.hpp b/boost/metaparse/v1/fwd/next_line.hpp
new file mode 100644
index 0000000000..5e79235d43
--- /dev/null
+++ b/boost/metaparse/v1/fwd/next_line.hpp
@@ -0,0 +1,25 @@
+#ifndef BOOST_METAPARSE_V1_FWD_NEXT_LINE_IMPL_HPP
+#define BOOST_METAPARSE_V1_FWD_NEXT_LINE_IMPL_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P>
+ struct next_line_impl;
+
+ template <class P, class Ch>
+ struct next_line;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/fwd/reject.hpp b/boost/metaparse/v1/fwd/reject.hpp
new file mode 100644
index 0000000000..8e937b839b
--- /dev/null
+++ b/boost/metaparse/v1/fwd/reject.hpp
@@ -0,0 +1,22 @@
+#ifndef BOOST_METAPARSE_V1_FWD_REJECT_HPP
+#define BOOST_METAPARSE_V1_FWD_REJECT_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class Msg, class Pos>
+ struct reject;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/fwd/source_position.hpp b/boost/metaparse/v1/fwd/source_position.hpp
new file mode 100644
index 0000000000..be79bcf2cc
--- /dev/null
+++ b/boost/metaparse/v1/fwd/source_position.hpp
@@ -0,0 +1,22 @@
+#ifndef BOOST_METAPARSE_V1_FWD_SOURCE_POSITION_HPP
+#define BOOST_METAPARSE_V1_FWD_SOURCE_POSITION_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class Line, class Col, class PrevChar>
+ struct source_position;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/fwd/string.hpp b/boost/metaparse/v1/fwd/string.hpp
new file mode 100644
index 0000000000..b5ecbd21e4
--- /dev/null
+++ b/boost/metaparse/v1/fwd/string.hpp
@@ -0,0 +1,38 @@
+#ifndef BOOST_METAPARSE_V1_FWD_STRING_HPP
+#define BOOST_METAPARSE_V1_FWD_STRING_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/config.hpp>
+#include <boost/metaparse/limit_string_size.hpp>
+#include <boost/metaparse/v1/impl/no_char.hpp>
+#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+#ifdef BOOST_METAPARSE_VARIADIC_STRING
+ template <char... Cs>
+ struct string;
+#else
+ template <
+ BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
+ BOOST_METAPARSE_LIMIT_STRING_SIZE,
+ int C,
+ BOOST_NO_CHAR
+ )
+ >
+ struct string;
+#endif
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/get_col.hpp b/boost/metaparse/v1/get_col.hpp
new file mode 100644
index 0000000000..cd857229c7
--- /dev/null
+++ b/boost/metaparse/v1/get_col.hpp
@@ -0,0 +1,29 @@
+#ifndef BOOST_METAPARSE_V1_GET_COL_HPP
+#define BOOST_METAPARSE_V1_GET_COL_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/fwd/get_col.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class>
+ struct get_col_impl;
+
+ template <class T>
+ struct get_col : get_col_impl<typename T::type::tag>::template apply<typename T::type>
+ {};
+
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/get_line.hpp b/boost/metaparse/v1/get_line.hpp
new file mode 100644
index 0000000000..53b351a2a9
--- /dev/null
+++ b/boost/metaparse/v1/get_line.hpp
@@ -0,0 +1,29 @@
+#ifndef BOOST_METAPARSE_V1_GET_LINE_HPP
+#define BOOST_METAPARSE_V1_GET_LINE_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/fwd/get_line.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class>
+ struct get_line_impl;
+
+ template <class T>
+ struct get_line : get_line_impl<typename T::type::tag>::template apply<typename T::type>
+ {};
+
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/get_message.hpp b/boost/metaparse/v1/get_message.hpp
new file mode 100644
index 0000000000..81eb7571eb
--- /dev/null
+++ b/boost/metaparse/v1/get_message.hpp
@@ -0,0 +1,29 @@
+#ifndef BOOST_METAPARSE_V1_GET_MESSAGE_HPP
+#define BOOST_METAPARSE_V1_GET_MESSAGE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/fwd/get_message.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class>
+ struct get_message_impl;
+
+ template <class T>
+ struct get_message : get_message_impl<typename T::type::tag>::template apply<typename T::type>
+ {};
+
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/get_position.hpp b/boost/metaparse/v1/get_position.hpp
new file mode 100644
index 0000000000..fde338fe5b
--- /dev/null
+++ b/boost/metaparse/v1/get_position.hpp
@@ -0,0 +1,29 @@
+#ifndef BOOST_METAPARSE_V1_GET_POSITION_HPP
+#define BOOST_METAPARSE_V1_GET_POSITION_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/fwd/get_position.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class>
+ struct get_position_impl;
+
+ template <class T>
+ struct get_position : get_position_impl<typename T::type::tag>::template apply<typename T::type>
+ {};
+
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/get_prev_char.hpp b/boost/metaparse/v1/get_prev_char.hpp
new file mode 100644
index 0000000000..6c45d74ebf
--- /dev/null
+++ b/boost/metaparse/v1/get_prev_char.hpp
@@ -0,0 +1,29 @@
+#ifndef BOOST_METAPARSE_V1_GET_PREV_CHAR_HPP
+#define BOOST_METAPARSE_V1_GET_PREV_CHAR_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/fwd/get_prev_char.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class>
+ struct get_prev_char_impl;
+
+ template <class T>
+ struct get_prev_char : get_prev_char_impl<typename T::type::tag>::template apply<typename T::type>
+ {};
+
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/get_remaining.hpp b/boost/metaparse/v1/get_remaining.hpp
new file mode 100644
index 0000000000..7a7ac07e11
--- /dev/null
+++ b/boost/metaparse/v1/get_remaining.hpp
@@ -0,0 +1,29 @@
+#ifndef BOOST_METAPARSE_V1_GET_REMAINING_HPP
+#define BOOST_METAPARSE_V1_GET_REMAINING_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/fwd/get_remaining.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class>
+ struct get_remaining_impl;
+
+ template <class T>
+ struct get_remaining : get_remaining_impl<typename T::type::tag>::template apply<typename T::type>
+ {};
+
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/get_result.hpp b/boost/metaparse/v1/get_result.hpp
new file mode 100644
index 0000000000..3426ca544e
--- /dev/null
+++ b/boost/metaparse/v1/get_result.hpp
@@ -0,0 +1,29 @@
+#ifndef BOOST_METAPARSE_V1_GET_RESULT_HPP
+#define BOOST_METAPARSE_V1_GET_RESULT_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/fwd/get_result.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class>
+ struct get_result_impl;
+
+ template <class T>
+ struct get_result :
+ get_result_impl<typename T::type::tag>::template apply<typename T::type>
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/grammar.hpp b/boost/metaparse/v1/grammar.hpp
new file mode 100644
index 0000000000..6f885345d5
--- /dev/null
+++ b/boost/metaparse/v1/grammar.hpp
@@ -0,0 +1,386 @@
+#ifndef BOOST_METAPARSE_V1_GRAMMAR_HPP
+#define BOOST_METAPARSE_V1_GRAMMAR_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/repeated.hpp>
+#include <boost/metaparse/v1/repeated1.hpp>
+#include <boost/metaparse/v1/sequence.hpp>
+#include <boost/metaparse/v1/one_of.hpp>
+#include <boost/metaparse/v1/transform.hpp>
+#include <boost/metaparse/v1/lit.hpp>
+#include <boost/metaparse/v1/lit_c.hpp>
+#include <boost/metaparse/v1/token.hpp>
+#include <boost/metaparse/v1/keyword.hpp>
+#include <boost/metaparse/v1/middle_of.hpp>
+#include <boost/metaparse/v1/last_of.hpp>
+#include <boost/metaparse/v1/always.hpp>
+#include <boost/metaparse/v1/one_char_except_c.hpp>
+#include <boost/metaparse/v1/foldr1.hpp>
+#include <boost/metaparse/v1/foldl_start_with_parser.hpp>
+#include <boost/metaparse/v1/alphanum.hpp>
+#include <boost/metaparse/v1/build_parser.hpp>
+#include <boost/metaparse/v1/entire_input.hpp>
+#include <boost/metaparse/v1/string.hpp>
+#include <boost/metaparse/v1/impl/front_inserter.hpp>
+
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/map.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/has_key.hpp>
+#include <boost/mpl/lambda.hpp>
+#include <boost/mpl/front.hpp>
+#include <boost/mpl/back.hpp>
+#include <boost/mpl/pair.hpp>
+#include <boost/mpl/insert.hpp>
+
+/*
+ * The grammar
+ *
+ * rule_definition ::= name_token define_token expression
+ * expression ::= seq_expression (or_token seq_expression)*
+ * seq_expression ::= repeated_expression+
+ * repeated_expression ::= name_expression (repeated_token | repeated1_token)*
+ * name_expression ::= char_token | name_token | bracket_expression
+ * bracket_expression ::= open_bracket_token expression close_bracket_token
+ */
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace grammar_util
+ {
+ template <char Op, class FState>
+ struct repeated_apply_impl
+ {
+ typedef repeated_apply_impl type;
+
+ template <class G>
+ struct apply :
+ repeated<typename FState::template apply<G>::type>
+ {};
+ };
+
+ template <class FState>
+ struct repeated_apply_impl<'+', FState>
+ {
+ typedef repeated_apply_impl type;
+
+ template <class G>
+ struct apply :
+ repeated1<typename FState::template apply<G>::type>
+ {};
+ };
+
+ struct build_repeated
+ {
+ typedef build_repeated type;
+
+ template <class FState, class T>
+ struct apply : repeated_apply_impl<T::type::value, FState> {};
+ };
+
+ struct build_sequence
+ {
+ typedef build_sequence type;
+
+ template <class FState, class FP>
+ struct apply_impl
+ {
+ typedef apply_impl type;
+
+ template <class G>
+ struct apply :
+ sequence<
+ typename FState::template apply<G>::type,
+ typename FP::template apply<G>::type
+ >
+ {};
+ };
+
+ template <class FState, class FP>
+ struct apply : apply_impl<FState, FP> {};
+ };
+
+ struct build_selection
+ {
+ typedef build_selection type;
+
+ template <class FState, class FP>
+ struct apply_impl
+ {
+ typedef apply_impl type;
+
+ template <class G>
+ struct apply :
+ one_of<
+ typename FState::template apply<G>::type,
+ typename FP::template apply<G>::type
+ >
+ {};
+ };
+
+ template <class FState, class FP>
+ struct apply : apply_impl<FState, FP> {};
+ };
+
+ template <class G, class Name>
+ struct get_parser
+ {
+ typedef
+ typename boost::mpl::at<typename G::rules, Name>::type
+ ::template apply<G>
+ p;
+
+ template <class Actions>
+ struct impl : transform<typename p::type, typename Actions::type> {};
+
+ typedef
+ typename boost::mpl::eval_if<
+ typename boost::mpl::has_key<typename G::actions, Name>::type,
+ impl<boost::mpl::at<typename G::actions, Name> >,
+ p
+ >::type
+ type;
+ };
+
+ struct build_name
+ {
+ typedef build_name type;
+
+ template <class Name>
+ struct apply_impl
+ {
+ typedef apply_impl type;
+
+ template <class G>
+ struct apply : get_parser<G, Name> {};
+ };
+
+ template <class Name>
+ struct apply : apply_impl<Name> {};
+ };
+
+ struct build_char
+ {
+ typedef build_char type;
+
+ template <class C>
+ struct apply_impl
+ {
+ typedef apply_impl type;
+
+ template <class G>
+ struct apply : lit<C> {};
+ };
+
+ template <class C>
+ struct apply : apply_impl<C> {};
+ };
+
+ typedef token<lit_c<'*'> > repeated_token;
+ typedef token<lit_c<'+'> > repeated1_token;
+ typedef token<lit_c<'|'> > or_token;
+ typedef token<lit_c<'('> > open_bracket_token;
+ typedef token<lit_c<')'> > close_bracket_token;
+ typedef token<keyword<string<':',':','='> > > define_token;
+
+ typedef
+ middle_of<
+ lit_c<'\''>,
+ one_of<
+ last_of<
+ lit_c<'\\'>,
+ one_of<
+ always<lit_c<'n'>, boost::mpl::char_<'\n'> >,
+ always<lit_c<'r'>, boost::mpl::char_<'\r'> >,
+ always<lit_c<'t'>, boost::mpl::char_<'\t'> >,
+ lit_c<'\\'>,
+ lit_c<'\''>
+ >
+ >,
+ one_char_except_c<'\''>
+ >,
+ token<lit_c<'\''> >
+ >
+ char_token;
+
+ typedef
+ token<
+ foldr1<
+ one_of<alphanum, lit_c<'_'> >,
+ string<>,
+ impl::front_inserter
+ >
+ >
+ name_token;
+
+ struct expression;
+
+ typedef
+ middle_of<open_bracket_token, expression, close_bracket_token>
+ bracket_expression;
+
+ typedef
+ one_of<
+ transform<char_token, build_char>,
+ transform<name_token, build_name>,
+ bracket_expression
+ >
+ name_expression;
+
+ typedef
+ foldl_start_with_parser<
+ one_of<repeated_token, repeated1_token>,
+ name_expression,
+ build_repeated
+ >
+ repeated_expression;
+
+ typedef
+ foldl_start_with_parser<
+ repeated_expression,
+ repeated_expression,
+ build_sequence
+ >
+ seq_expression;
+
+ struct expression :
+ foldl_start_with_parser<
+ last_of<or_token, seq_expression>,
+ seq_expression,
+ build_selection
+ >
+ {};
+
+ typedef sequence<name_token, define_token, expression> rule_definition;
+
+ typedef build_parser<entire_input<rule_definition> > parser_parser;
+
+ template <class P>
+ struct build_native_parser
+ {
+ typedef build_native_parser type;
+
+ template <class G>
+ struct apply
+ {
+ typedef P type;
+ };
+ };
+
+ template <class S>
+ struct build_parsed_parser
+ {
+ typedef typename parser_parser::apply<S>::type p;
+ typedef typename boost::mpl::front<p>::type name;
+ typedef typename boost::mpl::back<p>::type exp;
+
+ struct the_parser
+ {
+ typedef the_parser type;
+
+ template <class G>
+ struct apply : exp::template apply<G> {};
+ };
+
+ typedef boost::mpl::pair<name, the_parser> type;
+ };
+
+ typedef build_parser<name_token> name_parser;
+
+ template <class S>
+ struct rebuild : name_parser::template apply<S> {};
+
+ struct no_action;
+
+ template <class G, class P, class F>
+ struct add_rule;
+
+ template <class G, class Name, class P>
+ struct add_import;
+
+ template <class Start, class Rules, class Actions>
+ struct grammar_builder
+ {
+ typedef grammar_builder type;
+ typedef Rules rules;
+ typedef Actions actions;
+
+ // Make it a parser
+ template <class S, class Pos>
+ struct apply :
+ get_parser<
+ grammar_builder,
+ typename rebuild<Start>::type
+ >::type::template apply<S, Pos>
+ {};
+
+ template <class Name, class P>
+ struct import :
+ add_import<grammar_builder, typename rebuild<Name>::type, P>
+ {};
+
+ template <class Def, class Action = no_action>
+ struct rule :
+ add_rule<grammar_builder, build_parsed_parser<Def>, Action>
+ {};
+ };
+
+ template <class Start, class Rules, class Actions, class P>
+ struct add_rule<grammar_builder<Start, Rules, Actions>, P, no_action> :
+ grammar_builder<
+ Start,
+ typename boost::mpl::insert<Rules, typename P::type>::type,
+ Actions
+ >
+ {};
+
+ template <class Start, class Rules, class Actions, class P, class F>
+ struct add_rule<grammar_builder<Start, Rules, Actions>, P, F> :
+ grammar_builder<
+ Start,
+ typename boost::mpl::insert<Rules, typename P::type>::type,
+ typename boost::mpl::insert<
+ Actions,
+ boost::mpl::pair<
+ typename P::name,
+ typename boost::mpl::lambda<F>::type
+ >
+ >
+ ::type
+ >
+ {};
+
+ template <class Start, class Rules, class Actions, class Name, class P>
+ struct add_import<grammar_builder<Start, Rules, Actions>, Name, P> :
+ grammar_builder<
+ Start,
+ typename boost::mpl::insert<
+ Rules,
+ boost::mpl::pair<Name, build_native_parser<P> >
+ >::type,
+ Actions
+ >
+ {};
+ }
+
+ template <class Start = string<'S'> >
+ struct grammar :
+ grammar_util::grammar_builder<
+ Start,
+ boost::mpl::map<>,
+ boost::mpl::map<>
+ >
+ {};
+ }
+ }
+}
+
+#endif
diff --git a/boost/metaparse/v1/if_.hpp b/boost/metaparse/v1/if_.hpp
new file mode 100644
index 0000000000..4c832d8197
--- /dev/null
+++ b/boost/metaparse/v1/if_.hpp
@@ -0,0 +1,43 @@
+#ifndef BOOST_METAPARSE_V1_IF__HPP
+#define BOOST_METAPARSE_V1_IF__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/accept.hpp>
+#include <boost/metaparse/v1/is_error.hpp>
+
+#include <boost/mpl/if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class T, class F>
+ struct if_
+ {
+ typedef if_ type;
+
+ template <class S, class Pos>
+ struct apply :
+ accept<
+ typename boost::mpl::if_<
+ is_error<typename P::template apply<S, Pos> >,
+ F,
+ T
+ >::type,
+ S,
+ Pos
+ >
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/apply_parser.hpp b/boost/metaparse/v1/impl/apply_parser.hpp
new file mode 100644
index 0000000000..65d0f76107
--- /dev/null
+++ b/boost/metaparse/v1/impl/apply_parser.hpp
@@ -0,0 +1,63 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_APPLY_PARSER_HPP
+#define BOOST_METAPARSE_V1_IMPL_APPLY_PARSER_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/unless_error.hpp>
+#include <boost/metaparse/v1/get_result.hpp>
+#include <boost/metaparse/v1/get_remaining.hpp>
+#include <boost/metaparse/v1/get_position.hpp>
+#include <boost/metaparse/v1/transform.hpp>
+
+#include <boost/mpl/push_back.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ struct apply_parser
+ {
+ private:
+ template <class ListToAppend>
+ struct do_append
+ {
+ template <class Item>
+ struct apply : boost::mpl::push_back<ListToAppend, Item> {};
+ };
+
+ template <class Accum, class S, class Pos, class Parser>
+ struct apply_unchecked :
+ transform<Parser,do_append<typename Accum::type> >::template apply<
+ typename S::type,
+ typename Pos::type
+ >
+ {};
+
+ public:
+ template <class State, class Parser>
+ struct apply :
+ unless_error<
+ State,
+ apply_unchecked<
+ get_result<State>,
+ get_remaining<State>,
+ get_position<State>,
+ Parser
+ >
+ >
+ {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/assert_string_length.hpp b/boost/metaparse/v1/impl/assert_string_length.hpp
new file mode 100644
index 0000000000..5dad4d9f49
--- /dev/null
+++ b/boost/metaparse/v1/impl/assert_string_length.hpp
@@ -0,0 +1,31 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_ASSERT_STRING_LENGTH_HPP
+#define BOOST_METAPARSE_V1_IMPL_ASSERT_STRING_LENGTH_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/static_assert.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <int Len, class S>
+ struct assert_string_length : S
+ {
+ BOOST_STATIC_ASSERT((Len <= BOOST_METAPARSE_LIMIT_STRING_SIZE));
+ };
+ }
+ }
+ }
+}
+
+#endif
+
+
diff --git a/boost/metaparse/v1/impl/at_c.hpp b/boost/metaparse/v1/impl/at_c.hpp
new file mode 100644
index 0000000000..af7177410e
--- /dev/null
+++ b/boost/metaparse/v1/impl/at_c.hpp
@@ -0,0 +1,66 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_AT_C_HPP
+#define BOOST_METAPARSE_V1_IMPL_AT_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/config.hpp>
+#include <boost/metaparse/v1/fwd/string.hpp>
+
+#include <boost/mpl/char.hpp>
+
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class S, int N>
+ struct at_c;
+
+#ifdef BOOST_METAPARSE_VARIADIC_STRING
+ template <char C, char... Cs, int N>
+ struct at_c<string<C, Cs...>, N> : at_c<string<Cs...>, N - 1> {};
+
+ template <char C, char... Cs>
+ struct at_c<string<C, Cs...>, 0> : boost::mpl::char_<C> {};
+#else
+ #ifdef BOOST_METAPARSE_STRING_CASE
+ # error BOOST_METAPARSE_STRING_CASE is already defined
+ #endif
+ #define BOOST_METAPARSE_STRING_CASE(z, n, unused) \
+ template < \
+ BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C) \
+ > \
+ struct \
+ at_c< \
+ string< \
+ BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C) \
+ >, \
+ n \
+ > : \
+ boost::mpl::char_<BOOST_PP_CAT(C, n)> \
+ {};
+
+ BOOST_PP_REPEAT(
+ BOOST_METAPARSE_LIMIT_STRING_SIZE,
+ BOOST_METAPARSE_STRING_CASE,
+ ~
+ )
+
+ #undef BOOST_METAPARSE_STRING_CASE
+#endif
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/back_inserter.hpp b/boost/metaparse/v1/impl/back_inserter.hpp
new file mode 100644
index 0000000000..986b2d32da
--- /dev/null
+++ b/boost/metaparse/v1/impl/back_inserter.hpp
@@ -0,0 +1,32 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_BACK_INSERTER_HPP
+#define BOOST_METAPARSE_V1_IMPL_BACK_INSERTER_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/mpl/push_back.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ struct back_inserter
+ {
+ typedef back_inserter type;
+
+ template <class T0, class T1>
+ struct apply : boost::mpl::push_back<T0, T1> {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/concat.hpp b/boost/metaparse/v1/impl/concat.hpp
new file mode 100644
index 0000000000..d866ae42b1
--- /dev/null
+++ b/boost/metaparse/v1/impl/concat.hpp
@@ -0,0 +1,106 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_CONCAT_HPP
+#define BOOST_METAPARSE_V1_IMPL_CONCAT_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/config.hpp>
+#include <boost/metaparse/v1/fwd/string.hpp>
+
+#include <boost/preprocessor/arithmetic/dec.hpp>
+#include <boost/preprocessor/arithmetic/inc.hpp>
+#include <boost/preprocessor/arithmetic/mul.hpp>
+#include <boost/preprocessor/arithmetic/sub.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class A, class B>
+ struct concat;
+
+#ifdef BOOST_METAPARSE_VARIADIC_STRING
+ template <char... As, char... Bs>
+ struct concat<string<As...>, string<Bs...>> : string<As..., Bs...> {};
+#else
+ template <class A, class B>
+ struct concat_impl;
+
+ #ifdef BOOST_METAPARSE_ARG
+ # error BOOST_METAPARSE_ARG already defined
+ #endif
+ #define BOOST_METAPARSE_ARG(z, n, unused) \
+ BOOST_PP_CAT(B, BOOST_PP_INC(n))
+
+ #ifdef BOOST_METAPARSE_CONCAT
+ # error BOOST_METAPARSE_CONCAT already defined
+ #endif
+ #define BOOST_METAPARSE_CONCAT(z, n, unused) \
+ template < \
+ BOOST_PP_ENUM_PARAMS(n, int A) BOOST_PP_COMMA_IF(n) \
+ BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int B) \
+ > \
+ struct \
+ concat_impl< \
+ string< \
+ BOOST_PP_ENUM_PARAMS(n, A) \
+ BOOST_PP_COMMA_IF( \
+ BOOST_PP_MUL( \
+ BOOST_PP_SUB(BOOST_METAPARSE_LIMIT_STRING_SIZE, n), \
+ n \
+ ) \
+ ) \
+ BOOST_PP_ENUM( \
+ BOOST_PP_SUB(BOOST_METAPARSE_LIMIT_STRING_SIZE, n), \
+ BOOST_NO_CHAR BOOST_PP_TUPLE_EAT(3), \
+ ~ \
+ ) \
+ >, \
+ string< \
+ BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, B) \
+ > \
+ > : \
+ concat< \
+ string<BOOST_PP_ENUM_PARAMS(n, A) BOOST_PP_COMMA_IF(n) B0>, \
+ string< \
+ BOOST_PP_ENUM( \
+ BOOST_PP_DEC(BOOST_METAPARSE_LIMIT_STRING_SIZE), \
+ BOOST_METAPARSE_ARG, \
+ ~ \
+ ) \
+ > \
+ > \
+ {};
+
+ BOOST_PP_REPEAT(
+ BOOST_METAPARSE_LIMIT_STRING_SIZE,
+ BOOST_METAPARSE_CONCAT,
+ ~
+ )
+
+ #undef BOOST_METAPARSE_ARG
+ #undef BOOST_METAPARSE_CONCAT
+
+ template <class S>
+ struct concat<S, string<> > : S {};
+
+ template <class A, class B>
+ struct concat : concat_impl<A, B> {};
+#endif
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/empty_string.hpp b/boost/metaparse/v1/impl/empty_string.hpp
new file mode 100644
index 0000000000..7b62496450
--- /dev/null
+++ b/boost/metaparse/v1/impl/empty_string.hpp
@@ -0,0 +1,44 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_EMPTY_STRING_HPP
+#define BOOST_METAPARSE_V1_IMPL_EMPTY_STRING_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/config.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class Ignore = int>
+ struct empty_string
+ {
+ typedef empty_string type;
+
+ #ifdef BOOST_NO_CONSTEXPR_C_STR
+ static const char value[1];
+ #else
+ static constexpr char value[1] = {0};
+ #endif
+ };
+
+ #ifdef BOOST_NO_CONSTEXPR_C_STR
+ template <class Ignore>
+ const char empty_string<Ignore>::value[1] = {0};
+ #else
+ template <class Ignore>
+ constexpr char empty_string<Ignore>::value[1];
+ #endif
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/front_inserter.hpp b/boost/metaparse/v1/impl/front_inserter.hpp
new file mode 100644
index 0000000000..620533bfbd
--- /dev/null
+++ b/boost/metaparse/v1/impl/front_inserter.hpp
@@ -0,0 +1,32 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_FRONT_INSERTER_HPP
+#define BOOST_METAPARSE_V1_IMPL_FRONT_INSERTER_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/mpl/push_front.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ struct front_inserter
+ {
+ typedef front_inserter type;
+
+ template <class T0, class T1>
+ struct apply : boost::mpl::push_front<T0, T1> {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/fwd/iterate_impl.hpp b/boost/metaparse/v1/impl/fwd/iterate_impl.hpp
new file mode 100644
index 0000000000..7773bf4ca1
--- /dev/null
+++ b/boost/metaparse/v1/impl/fwd/iterate_impl.hpp
@@ -0,0 +1,34 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_FWD_ITERATE_IMPL_HPP
+#define BOOST_METAPARSE_V1_IMPL_FWD_ITERATE_IMPL_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/is_error.hpp>
+#include <boost/metaparse/v1/get_result.hpp>
+#include <boost/metaparse/v1/get_remaining.hpp>
+#include <boost/metaparse/v1/get_position.hpp>
+
+#include <boost/mpl/deque.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/push_back.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <int N, class P, class Accum>
+ struct iterate_impl;
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/has_type.hpp b/boost/metaparse/v1/impl/has_type.hpp
new file mode 100644
index 0000000000..167ea600a3
--- /dev/null
+++ b/boost/metaparse/v1/impl/has_type.hpp
@@ -0,0 +1,26 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_HAS_TYPE_HPP
+#define BOOST_METAPARSE_V1_IMPL_HAS_TYPE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/mpl/has_xxx.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(type)
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/is_any.hpp b/boost/metaparse/v1/impl/is_any.hpp
new file mode 100644
index 0000000000..23122b35ce
--- /dev/null
+++ b/boost/metaparse/v1/impl/is_any.hpp
@@ -0,0 +1,70 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_IS_ANY_HPP
+#define BOOST_METAPARSE_V1_IMPL_IS_ANY_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/limit_one_char_except_size.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/bool.hpp>
+
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/arithmetic/dec.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class Stub = int>
+ struct is_any0
+ {
+ template <class C>
+ struct apply : boost::mpl::true_ {};
+ };
+
+ #ifdef BOOST_METAPARSE_DEFINE_IS_ANY
+ # error BOOST_METAPARSE_DEFINE_IS_ANY already defined
+ #endif
+ #define BOOST_METAPARSE_DEFINE_IS_ANY(z, n, unused) \
+ template <BOOST_PP_ENUM_PARAMS(n, class T)> \
+ struct BOOST_PP_CAT(is_any, n) \
+ { \
+ template <class C> \
+ struct apply : \
+ boost::mpl::eval_if< \
+ boost::mpl::bool_< \
+ C::type::value \
+ == BOOST_PP_CAT(T, BOOST_PP_DEC(n))::type::value \
+ >, \
+ boost::mpl::false_, \
+ typename BOOST_PP_CAT(is_any, BOOST_PP_DEC(n))< \
+ BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(n), T) \
+ >::template apply<C> \
+ > \
+ {}; \
+ };
+
+ BOOST_PP_REPEAT_FROM_TO(
+ 1,
+ BOOST_METAPARSE_LIMIT_ONE_CHAR_EXCEPT_SIZE,
+ BOOST_METAPARSE_DEFINE_IS_ANY,
+ ~
+ )
+
+ #undef BOOST_METAPARSE_DEFINE_IS_ANY
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/is_char_c.hpp b/boost/metaparse/v1/impl/is_char_c.hpp
new file mode 100644
index 0000000000..1ad298f848
--- /dev/null
+++ b/boost/metaparse/v1/impl/is_char_c.hpp
@@ -0,0 +1,33 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_IS_CHAR_C_HPP
+#define BOOST_METAPARSE_V1_IMPL_IS_CHAR_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/mpl/bool.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <char C>
+ struct is_char_c
+ {
+ typedef is_char_c type;
+
+ template <class Ch>
+ struct apply : boost::mpl::bool_<Ch::type::value == C> {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/iterate_impl.hpp b/boost/metaparse/v1/impl/iterate_impl.hpp
new file mode 100644
index 0000000000..f12be9edf6
--- /dev/null
+++ b/boost/metaparse/v1/impl/iterate_impl.hpp
@@ -0,0 +1,46 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_ITERATE_IMPL_HPP
+#define BOOST_METAPARSE_V1_IMPL_ITERATE_IMPL_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/iterate_impl_unchecked.hpp>
+#include <boost/metaparse/v1/return_.hpp>
+#include <boost/metaparse/v1/is_error.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <int N, class P, class Accum>
+ struct iterate_impl
+ {
+ typedef iterate_impl 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>,
+ iterate_impl_unchecked<N, P, Accum, S, Pos>
+ >
+ {};
+ };
+
+ template <class P, class Accum>
+ struct iterate_impl<0, P, Accum> : return_<Accum> {};
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/iterate_impl_unchecked.hpp b/boost/metaparse/v1/impl/iterate_impl_unchecked.hpp
new file mode 100644
index 0000000000..535cd379d9
--- /dev/null
+++ b/boost/metaparse/v1/impl/iterate_impl_unchecked.hpp
@@ -0,0 +1,44 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_ITERATE_IMPL_UNCHECKED_HPP
+#define BOOST_METAPARSE_V1_IMPL_ITERATE_IMPL_UNCHECKED_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/fwd/iterate_impl.hpp>
+#include <boost/metaparse/v1/get_result.hpp>
+#include <boost/metaparse/v1/get_remaining.hpp>
+#include <boost/metaparse/v1/get_position.hpp>
+
+#include <boost/mpl/push_back.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <int N, class P, class Accum, class S, class Pos>
+ struct iterate_impl_unchecked :
+ iterate_impl<
+ N - 1,
+ P,
+ typename boost::mpl::push_back<
+ Accum,
+ typename get_result<typename P::template apply<S, Pos> >::type
+ >::type
+ >::template apply<
+ typename get_remaining<typename P::template apply<S, Pos> >::type,
+ typename get_position<typename P::template apply<S, Pos> >::type
+ >
+ {};
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/later_result.hpp b/boost/metaparse/v1/impl/later_result.hpp
new file mode 100644
index 0000000000..69c2e5b89a
--- /dev/null
+++ b/boost/metaparse/v1/impl/later_result.hpp
@@ -0,0 +1,39 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_LATER_RESULT_HPP
+#define BOOST_METAPARSE_V1_IMPL_LATER_RESULT_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/get_position.hpp>
+
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/less.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class R1, class R2>
+ struct later_result :
+ boost::mpl::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/impl/next_digit.hpp b/boost/metaparse/v1/impl/next_digit.hpp
new file mode 100644
index 0000000000..959ea114c6
--- /dev/null
+++ b/boost/metaparse/v1/impl/next_digit.hpp
@@ -0,0 +1,36 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_NEXT_DIGIT_HPP
+#define BOOST_METAPARSE_V1_IMPL_NEXT_DIGIT_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/mpl/int.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ struct next_digit
+ {
+ typedef next_digit type;
+
+ template <class PartialResult, class NextDigit>
+ struct apply :
+ boost::mpl::int_<
+ PartialResult::type::value * 10 + NextDigit::type::value
+ >
+ {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/no_char.hpp b/boost/metaparse/v1/impl/no_char.hpp
new file mode 100644
index 0000000000..c6b91f07a6
--- /dev/null
+++ b/boost/metaparse/v1/impl/no_char.hpp
@@ -0,0 +1,17 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_NO_CHAR_HPP
+#define BOOST_METAPARSE_V1_IMPL_NO_CHAR_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 <cstdio>
+
+#ifdef BOOST_NO_CHAR
+# error BOOST_NO_CHAR already defined
+#endif
+#define BOOST_NO_CHAR EOF
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/nth_of_c.hpp b/boost/metaparse/v1/impl/nth_of_c.hpp
new file mode 100644
index 0000000000..d12d164eaa
--- /dev/null
+++ b/boost/metaparse/v1/impl/nth_of_c.hpp
@@ -0,0 +1,61 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_NTH_OF_C_HPP
+#define BOOST_METAPARSE_V1_IMPL_NTH_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/impl/nth_of_c_impl.hpp>
+#include <boost/metaparse/v1/error/index_out_of_range.hpp>
+#include <boost/metaparse/v1/fail.hpp>
+#include <boost/metaparse/limit_sequence_size.hpp>
+
+#include <boost/mpl/list.hpp>
+
+#include <boost/preprocessor/repetition/repeat.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/cat.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ #ifdef BOOST_METAPARSE_NTH_OF_CASE
+ # error BOOST_METAPARSE_NTH_OF_CASE already defined
+ #endif
+ #define BOOST_METAPARSE_NTH_OF_CASE(z, n, unused) \
+ template < \
+ int K BOOST_PP_COMMA_IF(n) \
+ BOOST_PP_ENUM_PARAMS(n, class P) \
+ > \
+ struct BOOST_PP_CAT(nth_of_c, n) : \
+ boost::mpl::if_< \
+ boost::mpl::bool_<(0 <= K && K < n)>, \
+ nth_of_c_impl< \
+ K, \
+ boost::mpl::list<BOOST_PP_ENUM_PARAMS(n, P)> \
+ >, \
+ fail<error::index_out_of_range<0, n - 1, K> > \
+ >::type \
+ {};
+
+ BOOST_PP_REPEAT(
+ BOOST_METAPARSE_LIMIT_SEQUENCE_SIZE,
+ BOOST_METAPARSE_NTH_OF_CASE,
+ ~
+ )
+
+ #undef BOOST_METAPARSE_NTH_OF_CASE
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/nth_of_c_impl.hpp b/boost/metaparse/v1/impl/nth_of_c_impl.hpp
new file mode 100644
index 0000000000..c74dcc0dae
--- /dev/null
+++ b/boost/metaparse/v1/impl/nth_of_c_impl.hpp
@@ -0,0 +1,77 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_NTH_OF_C_IMPL_HPP
+#define BOOST_METAPARSE_V1_IMPL_NTH_OF_C_IMPL_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/skip_seq.hpp>
+
+#include <boost/mpl/front.hpp>
+#include <boost/mpl/pop_front.hpp>
+#include <boost/mpl/fold.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <int N, class Seq>
+ struct nth_of_c_impl
+ {
+ private:
+ template <class NextResult>
+ struct apply_unchecked :
+ nth_of_c_impl<
+ N - 1,
+ typename boost::mpl::pop_front<Seq>::type
+ >::template apply<
+ typename get_remaining<NextResult>::type,
+ typename get_position<NextResult>::type
+ >
+ {};
+ public:
+ typedef nth_of_c_impl type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::eval_if<
+ typename is_error<
+ typename boost::mpl::front<Seq>::type::template apply<S, Pos>
+ >::type,
+ typename boost::mpl::front<Seq>::type::template apply<S, Pos>,
+ apply_unchecked<
+ typename boost::mpl::front<Seq>::type::template apply<S, Pos>
+ >
+ >
+ {};
+ };
+
+ template <class Seq>
+ struct nth_of_c_impl<0, Seq>
+ {
+ typedef nth_of_c_impl type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::fold<
+ typename boost::mpl::pop_front<Seq>::type,
+ typename boost::mpl::front<Seq>::type::template apply<
+ S,
+ Pos
+ >::type,
+ skip_seq
+ >
+ {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/one_char_except_not_used.hpp b/boost/metaparse/v1/impl/one_char_except_not_used.hpp
new file mode 100644
index 0000000000..249fcdd725
--- /dev/null
+++ b/boost/metaparse/v1/impl/one_char_except_not_used.hpp
@@ -0,0 +1,24 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_ONE_CHAR_EXCEPT_NOT_USED_HPP
+#define BOOST_METAPARSE_V1_IMPL_ONE_CHAR_EXCEPT_NOT_USED_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ struct one_char_except_not_used {};
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/one_of.hpp b/boost/metaparse/v1/impl/one_of.hpp
new file mode 100644
index 0000000000..e5b53e2e5c
--- /dev/null
+++ b/boost/metaparse/v1/impl/one_of.hpp
@@ -0,0 +1,44 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_ONE_OF_HPP
+#define BOOST_METAPARSE_V1_IMPL_ONE_OF_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/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/mpl/fold.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class Parsers>
+ struct one_of
+ {
+ typedef one_of type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::fold<
+ Parsers,
+ fail<error::none_of_the_expected_cases_found>::apply<S, Pos>,
+ one_of_fwd_op<S, Pos>
+ >::type
+ {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/one_of_fwd_op.hpp b/boost/metaparse/v1/impl/one_of_fwd_op.hpp
new file mode 100644
index 0000000000..97d4658381
--- /dev/null
+++ b/boost/metaparse/v1/impl/one_of_fwd_op.hpp
@@ -0,0 +1,46 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_ONE_OF_FWD_OP_HPP
+#define BOOST_METAPARSE_V1_IMPL_ONE_OF_FWD_OP_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/is_error.hpp>
+#include <boost/metaparse/v1/impl/later_result.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class S, class Pos>
+ struct one_of_fwd_op
+ {
+ typedef one_of_fwd_op type;
+
+ template <class State, class P>
+ struct apply :
+ boost::mpl::eval_if<
+ typename is_error<State>::type,
+ boost::mpl::eval_if<
+ typename is_error<typename P::template apply<S, Pos> >::type,
+ later_result<State, typename P::template apply<S, Pos> >,
+ typename P::template apply<S, Pos>
+ >,
+ State
+ >
+ {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/pop_back.hpp b/boost/metaparse/v1/impl/pop_back.hpp
new file mode 100644
index 0000000000..7c3d9b30b2
--- /dev/null
+++ b/boost/metaparse/v1/impl/pop_back.hpp
@@ -0,0 +1,52 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_POP_BACK_HPP
+#define BOOST_METAPARSE_V1_IMPL_POP_BACK_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/config.hpp>
+#include <boost/metaparse/v1/fwd/string.hpp>
+#include <boost/metaparse/v1/impl/push_front_c.hpp>
+#include <boost/metaparse/v1/impl/size.hpp>
+#include <boost/metaparse/v1/impl/update_c.hpp>
+
+#include <boost/mpl/clear.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class S>
+ struct pop_back;
+
+#ifdef BOOST_METAPARSE_VARIADIC_STRING
+ template <char C>
+ struct pop_back<string<C>> : boost::mpl::clear<string<C>> {};
+
+ template <char C, char... Cs>
+ struct pop_back<string<C, Cs...>> :
+ push_front_c<typename pop_back<string<Cs...>>::type, C>
+ {};
+#else
+ template <class S>
+ struct pop_back :
+ update_c<
+ typename S::type,
+ size<typename S::type>::type::value - 1,
+ BOOST_NO_CHAR
+ >
+ {};
+#endif
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/pop_front.hpp b/boost/metaparse/v1/impl/pop_front.hpp
new file mode 100644
index 0000000000..ac02d35aa1
--- /dev/null
+++ b/boost/metaparse/v1/impl/pop_front.hpp
@@ -0,0 +1,62 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_POP_FRONT_HPP
+#define BOOST_METAPARSE_V1_IMPL_POP_FRONT_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/config.hpp>
+#include <boost/metaparse/v1/fwd/string.hpp>
+
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class S>
+ struct pop_front;
+
+#ifdef BOOST_METAPARSE_VARIADIC_STRING
+ template <char C, char... Cs>
+ struct pop_front<string<C, Cs...>> : string<Cs...> {};
+#else
+ #ifdef BOOST_METAPARSE_POP_FRONT
+ # error BOOST_METAPARSE_POP_FRONT already defined
+ #endif
+ #define BOOST_METAPARSE_POP_FRONT(z, n, unused) \
+ BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) BOOST_PP_CAT(C, n)
+
+ template < \
+ BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C) \
+ >
+ struct
+ pop_front<
+ string<BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C)>
+ > :
+ string<
+ BOOST_PP_REPEAT_FROM_TO(
+ 1,
+ BOOST_METAPARSE_LIMIT_STRING_SIZE,
+ BOOST_METAPARSE_POP_FRONT,
+ ~
+ ),
+ BOOST_NO_CHAR
+ >
+ {};
+
+ #undef BOOST_METAPARSE_POP_FRONT
+#endif
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/push_back_c.hpp b/boost/metaparse/v1/impl/push_back_c.hpp
new file mode 100644
index 0000000000..453043d97c
--- /dev/null
+++ b/boost/metaparse/v1/impl/push_back_c.hpp
@@ -0,0 +1,40 @@
+#ifndef BOOST_METAPARSE_V1_PUSH_BACK_C_HPP
+#define BOOST_METAPARSE_V1_PUSH_BACK_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/config.hpp>
+#include <boost/metaparse/v1/fwd/string.hpp>
+#include <boost/metaparse/v1/impl/update_c.hpp>
+#include <boost/metaparse/v1/impl/size.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class S, char C>
+ struct push_back_c;
+
+#ifdef BOOST_METAPARSE_VARIADIC_STRING
+ template <char... Cs, char C>
+ struct push_back_c<string<Cs...>, C> : string<Cs..., C> {};
+#else
+ template <class S, char C>
+ struct push_back_c :
+ update_c<typename S::type, size<typename S::type>::type::value, C>
+ {};
+#endif
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/push_front_c.hpp b/boost/metaparse/v1/impl/push_front_c.hpp
new file mode 100644
index 0000000000..27d0d3c7c9
--- /dev/null
+++ b/boost/metaparse/v1/impl/push_front_c.hpp
@@ -0,0 +1,53 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_PUSH_FRONT_C_HPP
+#define BOOST_METAPARSE_V1_IMPL_PUSH_FRONT_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/config.hpp>
+#include <boost/metaparse/v1/fwd/string.hpp>
+
+#include <boost/preprocessor/arithmetic/dec.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class S, char C>
+ struct push_front_c;
+
+#ifdef BOOST_METAPARSE_VARIADIC_STRING
+ template <char... Cs, char C>
+ struct push_front_c<string<Cs...>, C> : string<C, Cs...> {};
+#else
+ template <
+ BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C),
+ char Ch
+ >
+ struct push_front_c<
+ string<BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C)>,
+ Ch
+ > :
+ string<
+ Ch,
+ BOOST_PP_ENUM_PARAMS(
+ BOOST_PP_DEC(BOOST_METAPARSE_LIMIT_STRING_SIZE),
+ C
+ )
+ >
+ {};
+#endif
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/remove_trailing_no_chars.hpp b/boost/metaparse/v1/impl/remove_trailing_no_chars.hpp
new file mode 100644
index 0000000000..7d561d2709
--- /dev/null
+++ b/boost/metaparse/v1/impl/remove_trailing_no_chars.hpp
@@ -0,0 +1,57 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_REMOVE_TRAILING_NO_CHARS_HPP
+#define BOOST_METAPARSE_V1_IMPL_REMOVE_TRAILING_NO_CHARS_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/config.hpp>
+#include <boost/metaparse/v1/string.hpp>
+#include <boost/metaparse/v1/impl/push_front_c.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class S>
+ struct remove_trailing_no_chars : S {};
+
+#ifdef BOOST_METAPARSE_VARIADIC_STRING
+ // this code assumes that BOOST_NO_CHARs are at the end of the string
+ template <char... Cs>
+ struct remove_trailing_no_chars<string<BOOST_NO_CHAR, Cs...>> :
+ 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
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/returns.hpp b/boost/metaparse/v1/impl/returns.hpp
new file mode 100644
index 0000000000..ede50f6a8f
--- /dev/null
+++ b/boost/metaparse/v1/impl/returns.hpp
@@ -0,0 +1,28 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_RETURNS_HPP
+#define BOOST_METAPARSE_V1_IMPL_RETURNS_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class T>
+ struct returns
+ {
+ typedef T type;
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/sequence.hpp b/boost/metaparse/v1/impl/sequence.hpp
new file mode 100644
index 0000000000..c500cdf046
--- /dev/null
+++ b/boost/metaparse/v1/impl/sequence.hpp
@@ -0,0 +1,59 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_SEQUENCE_HPP
+#define BOOST_METAPARSE_V1_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/limit_sequence_size.hpp>
+
+#include <boost/mpl/vector.hpp>
+
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/cat.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ #ifdef BOOST_METAPARSE_SEQUENCE_CASE
+ # error BOOST_METAPARSE_SEQUENCE_CASE already defined
+ #endif
+ #define BOOST_METAPARSE_SEQUENCE_CASE(z, n, unused) \
+ template <BOOST_PP_ENUM_PARAMS(n, class P)> \
+ struct BOOST_PP_CAT(sequence, n) \
+ { \
+ typedef BOOST_PP_CAT(sequence, n) type; \
+ \
+ template <class S, class Pos> \
+ struct apply : \
+ sequence_impl< \
+ boost::mpl::vector<BOOST_PP_ENUM_PARAMS(n, P)>, \
+ S, \
+ Pos \
+ > \
+ {}; \
+ };
+
+ BOOST_PP_REPEAT_FROM_TO(
+ 1,
+ BOOST_METAPARSE_LIMIT_SEQUENCE_SIZE,
+ BOOST_METAPARSE_SEQUENCE_CASE,
+ ~
+ )
+
+ #undef BOOST_METAPARSE_SEQUENCE_CASE
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/sequence_impl.hpp b/boost/metaparse/v1/impl/sequence_impl.hpp
new file mode 100644
index 0000000000..d3310ed8af
--- /dev/null
+++ b/boost/metaparse/v1/impl/sequence_impl.hpp
@@ -0,0 +1,37 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_SEQUENCE_IMPL_HPP
+#define BOOST_METAPARSE_V1_IMPL_SEQUENCE_IMPL_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/apply_parser.hpp>
+#include <boost/metaparse/v1/accept.hpp>
+
+#include <boost/mpl/deque.hpp>
+#include <boost/mpl/fold.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class Ps, class S, class Pos>
+ struct sequence_impl :
+ boost::mpl::fold<
+ Ps,
+ accept<boost::mpl::deque<>, S, Pos>,
+ apply_parser
+ >
+ {};
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/size.hpp b/boost/metaparse/v1/impl/size.hpp
new file mode 100644
index 0000000000..c6e0ee7e27
--- /dev/null
+++ b/boost/metaparse/v1/impl/size.hpp
@@ -0,0 +1,69 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_SIZE_HPP
+#define BOOST_METAPARSE_V1_IMPL_SIZE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/config.hpp>
+#include <boost/metaparse/v1/fwd/string.hpp>
+
+#include <boost/mpl/int.hpp>
+
+#include <boost/preprocessor/arithmetic/sub.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+#include <boost/preprocessor/tuple/eat.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <class S>
+ struct size;
+
+#ifdef BOOST_METAPARSE_VARIADIC_STRING
+ template <char... Cs>
+ struct size<string<Cs...>> : boost::mpl::int_<sizeof...(Cs)> {};
+#else
+ #ifdef BOOST_METAPARSE_STRING_CASE
+ # error BOOST_METAPARSE_STRING_CASE
+ #endif
+ #define BOOST_METAPARSE_STRING_CASE(z, n, unused) \
+ template <BOOST_PP_ENUM_PARAMS(n, int C)> \
+ struct \
+ size< \
+ string< \
+ BOOST_PP_ENUM_PARAMS(n, C) BOOST_PP_COMMA_IF(n) \
+ BOOST_PP_ENUM( \
+ BOOST_PP_SUB(BOOST_METAPARSE_LIMIT_STRING_SIZE, n), \
+ BOOST_NO_CHAR BOOST_PP_TUPLE_EAT(3), \
+ ~ \
+ ) \
+ > \
+ > : \
+ boost::mpl::int_<n> \
+ {};
+
+ BOOST_PP_REPEAT(
+ BOOST_METAPARSE_LIMIT_STRING_SIZE,
+ BOOST_METAPARSE_STRING_CASE,
+ ~
+ )
+
+ #undef BOOST_METAPARSE_STRING_CASE
+#endif
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/skip_seq.hpp b/boost/metaparse/v1/impl/skip_seq.hpp
new file mode 100644
index 0000000000..4d7e5b138a
--- /dev/null
+++ b/boost/metaparse/v1/impl/skip_seq.hpp
@@ -0,0 +1,74 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_SKIP_SEQ_HPP
+#define BOOST_METAPARSE_V1_IMPL_SKIP_SEQ_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/is_error.hpp>
+#include <boost/metaparse/v1/accept.hpp>
+#include <boost/metaparse/v1/get_remaining.hpp>
+#include <boost/metaparse/v1/get_position.hpp>
+#include <boost/metaparse/v1/get_result.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ struct skip_seq
+ {
+ private:
+ template <class ParsingResult, class NewResultValue>
+ struct change_result :
+ accept<
+ NewResultValue,
+ typename get_remaining<ParsingResult>::type,
+ typename get_position<ParsingResult>::type
+ >
+ {};
+
+ template <class Result, class P>
+ struct apply_unchecked :
+ boost::mpl::eval_if<
+ typename is_error<
+ typename P::template apply<
+ typename get_remaining<Result>::type,
+ typename get_position<Result>::type
+ >
+ >::type,
+ typename P::template apply<
+ typename get_remaining<Result>::type,
+ typename get_position<Result>::type
+ >,
+ change_result<
+ typename P::template apply<
+ typename get_remaining<Result>::type,
+ typename get_position<Result>::type
+ >,
+ typename get_result<Result>::type
+ >
+ >
+ {};
+
+ public:
+ template <class Result, class P>
+ struct apply :
+ boost::mpl::eval_if<
+ is_error<Result>,
+ Result,
+ apply_unchecked<Result, P>
+ >
+ {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/split_at_c.hpp b/boost/metaparse/v1/impl/split_at_c.hpp
new file mode 100644
index 0000000000..44c2675905
--- /dev/null
+++ b/boost/metaparse/v1/impl/split_at_c.hpp
@@ -0,0 +1,101 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_SPLIT_AT_C_HPP
+#define BOOST_METAPARSE_V1_IMPL_SPLIT_AT_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/config.hpp>
+#include <boost/metaparse/v1/fwd/string.hpp>
+#include <boost/metaparse/v1/impl/push_front_c.hpp>
+
+#include <boost/preprocessor/arithmetic/add.hpp>
+#include <boost/preprocessor/arithmetic/sub.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+
+#include <boost/mpl/pair.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <int N, class S>
+ struct split_at_c;
+
+#ifdef BOOST_METAPARSE_VARIADIC_STRING
+ template <int N, char C, char... Cs>
+ struct split_at_c<N, string<C, Cs...>> :
+ boost::mpl::pair<
+ typename push_front_c<
+ typename split_at_c<N - 1, string<Cs...>>::type::first,
+ C
+ >::type,
+ typename split_at_c<N - 1, string<Cs...>>::type::second
+ >
+ {};
+
+ template <char C, char... Cs>
+ struct split_at_c<0, string<C, Cs...>> :
+ boost::mpl::pair<string<>, string<C, Cs...>>
+ {};
+
+ template <char... Cs>
+ struct split_at_c<0, string<Cs...>> :
+ boost::mpl::pair<string<>, string<Cs...>>
+ {};
+#else
+ #ifdef BOOST_METAPARSE_ARG
+ # error BOOST_METAPARSE_ARG already defined
+ #endif
+ #define BOOST_METAPARSE_ARG(z, n, d) BOOST_PP_CAT(C, BOOST_PP_ADD(n, d))
+
+ #ifdef BOOST_METAPARSE_SPLIT_AT
+ # error BOOST_METAPARSE_SPLIT_AT already defined
+ #endif
+ #define BOOST_METAPARSE_SPLIT_AT(z, n, unused) \
+ template < \
+ BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C) \
+ > \
+ struct \
+ split_at_c< \
+ n, \
+ string<BOOST_PP_ENUM_PARAMS( \
+ BOOST_METAPARSE_LIMIT_STRING_SIZE, C) \
+ > \
+ > : \
+ boost::mpl::pair< \
+ string<BOOST_PP_ENUM_PARAMS(n, C)>, \
+ string< \
+ BOOST_PP_ENUM( \
+ BOOST_PP_SUB(BOOST_METAPARSE_LIMIT_STRING_SIZE, n), \
+ BOOST_METAPARSE_ARG, \
+ n \
+ ) \
+ > \
+ > \
+ {};
+
+ BOOST_PP_REPEAT(
+ BOOST_METAPARSE_LIMIT_STRING_SIZE,
+ BOOST_METAPARSE_SPLIT_AT,
+ ~
+ )
+
+ #undef BOOST_METAPARSE_SPLIT_AT
+ #undef BOOST_METAPARSE_ARG
+#endif
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/string_iterator.hpp b/boost/metaparse/v1/impl/string_iterator.hpp
new file mode 100644
index 0000000000..3e37ff3b0d
--- /dev/null
+++ b/boost/metaparse/v1/impl/string_iterator.hpp
@@ -0,0 +1,159 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_STRING_ITERATOR_HPP
+#define BOOST_METAPARSE_V1_IMPL_STRING_ITERATOR_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/string_iterator_tag.hpp>
+#include <boost/metaparse/v1/impl/at_c.hpp>
+
+
+#include <boost/mpl/iterator_tags.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/bool.hpp>
+
+#include <boost/type_traits/is_same.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ // string_iterator
+ template <class S, int N>
+ struct string_iterator
+ {
+ typedef string_iterator type;
+ typedef string_iterator_tag tag;
+ typedef boost::mpl::random_access_iterator_tag category;
+ };
+
+ // advance_c
+
+ template <class S, int N>
+ struct advance_c;
+
+ template <class S, int N, int P>
+ struct advance_c<string_iterator<S, N>, P> :
+ string_iterator<S, N + P>
+ {};
+
+ // distance
+
+ template <class A, class B>
+ struct distance;
+
+ template <class S, int A, int B>
+ struct distance<string_iterator<S, A>, string_iterator<S, B> > :
+ boost::mpl::int_<B - A>
+ {};
+ }
+ }
+ }
+}
+
+namespace boost
+{
+ namespace mpl
+ {
+ // advance
+ template <class S>
+ struct advance_impl;
+
+ template <>
+ struct advance_impl<boost::metaparse::v1::impl::string_iterator_tag>
+ {
+ typedef advance_impl type;
+
+ template <class S, class N>
+ struct apply :
+ boost::metaparse::v1::impl::advance_c<
+ typename S::type, N::type::value
+ >
+ {};
+ };
+
+ // distance
+ template <class S>
+ struct distance_impl;
+
+ template <>
+ struct distance_impl<boost::metaparse::v1::impl::string_iterator_tag>
+ {
+ typedef distance_impl type;
+
+ template <class A, class B>
+ struct apply :
+ boost::metaparse::v1::impl::distance<
+ typename A::type,
+ typename B::type
+ >
+ {};
+ };
+
+ // next
+ template <class S>
+ struct next;
+
+ template <class S, int N>
+ struct next<boost::metaparse::v1::impl::string_iterator<S, N> > :
+ boost::metaparse::v1::impl::string_iterator<S, N + 1>
+ {};
+
+ // prior
+ template <class S>
+ struct prior;
+
+ template <class S, int N>
+ struct prior<boost::metaparse::v1::impl::string_iterator<S, N> > :
+ boost::metaparse::v1::impl::string_iterator<S, N - 1>
+ {};
+
+ // deref
+ template <class S>
+ struct deref;
+
+ template <class S, int N>
+ struct deref<boost::metaparse::v1::impl::string_iterator<S, N> > :
+ boost::metaparse::v1::impl::at_c<S, N>
+ {};
+
+ // equal_to
+ template <class A, class B>
+ struct equal_to_impl;
+
+ template <>
+ struct equal_to_impl<
+ boost::metaparse::v1::impl::string_iterator_tag,
+ boost::metaparse::v1::impl::string_iterator_tag
+ >
+ {
+ typedef equal_to_impl type;
+
+ template <class A, class B>
+ struct apply : is_same<typename A::type, typename B::type> {};
+ };
+
+ template <class T>
+ struct equal_to_impl<boost::metaparse::v1::impl::string_iterator_tag, T>
+ {
+ typedef equal_to_impl type;
+
+ template <class, class>
+ struct apply : false_ {};
+ };
+
+ template <class T>
+ struct equal_to_impl<T, boost::metaparse::v1::impl::string_iterator_tag> :
+ equal_to_impl<boost::metaparse::v1::impl::string_iterator_tag, T>
+ {};
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/string_iterator_tag.hpp b/boost/metaparse/v1/impl/string_iterator_tag.hpp
new file mode 100644
index 0000000000..b7d9041006
--- /dev/null
+++ b/boost/metaparse/v1/impl/string_iterator_tag.hpp
@@ -0,0 +1,27 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_STRING_ITERATOR_TAG_HPP
+#define BOOST_METAPARSE_V1_IMPL_STRING_ITERATOR_TAG_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ struct string_iterator_tag
+ {
+ typedef string_iterator_tag type;
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/update_c.hpp b/boost/metaparse/v1/impl/update_c.hpp
new file mode 100644
index 0000000000..5553933e95
--- /dev/null
+++ b/boost/metaparse/v1/impl/update_c.hpp
@@ -0,0 +1,93 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_UPDATE_C_HPP
+#define BOOST_METAPARSE_V1_IMPL_UPDATE_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/config.hpp>
+#include <boost/metaparse/v1/fwd/string.hpp>
+#include <boost/metaparse/v1/impl/split_at_c.hpp>
+#include <boost/metaparse/v1/impl/concat.hpp>
+
+#include <boost/preprocessor/arithmetic/dec.hpp>
+#include <boost/preprocessor/arithmetic/inc.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+#ifndef BOOST_METAPARSE_VARIADIC_STRING
+ template <class S, int N, int C>
+ struct update_c;
+
+ #ifdef BOOST_METAPARSE_ARGN
+ # error BOOST_METAPARSE_ARGN already defined
+ #endif
+ #define BOOST_METAPARSE_ARGN(z, n, unused) , BOOST_PP_CAT(C, n)
+
+ #ifdef BOOST_METAPARSE_UPDATE
+ # error BOOST_METAPARSE_UPDATE already defined
+ #endif
+ #define BOOST_METAPARSE_UPDATE(z, n, unused) \
+ template < \
+ BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C), \
+ int Ch \
+ > \
+ struct update_c< \
+ string<BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C)>,\
+ n, \
+ Ch \
+ > : \
+ string< \
+ BOOST_PP_ENUM_PARAMS(n, C) BOOST_PP_COMMA_IF(n) \
+ Ch \
+ BOOST_PP_REPEAT_FROM_TO( \
+ BOOST_PP_INC(n), \
+ BOOST_PP_DEC(BOOST_METAPARSE_LIMIT_STRING_SIZE), \
+ BOOST_METAPARSE_ARGN, \
+ ~ \
+ ) \
+ > \
+ {};
+
+ BOOST_PP_REPEAT(
+ BOOST_METAPARSE_LIMIT_STRING_SIZE,
+ BOOST_METAPARSE_UPDATE,
+ ~
+ )
+
+ #undef BOOST_METAPARSE_UPDATE
+ #undef BOOST_METAPARSE_ARGN
+#else
+ template <class S, int N, char C>
+ struct update_c :
+ concat<
+ typename split_at_c<N, S>::type::first,
+ typename
+ update_c<typename split_at_c<N, S>::type::second, 0, C>::type
+ >
+ {};
+
+ template <char... Cs, char C, char NewChar>
+ struct update_c<string<C, Cs...>, 0, NewChar> :
+ string<NewChar, Cs...>
+ {};
+#endif
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/impl/void_.hpp b/boost/metaparse/v1/impl/void_.hpp
new file mode 100644
index 0000000000..03c1d4598f
--- /dev/null
+++ b/boost/metaparse/v1/impl/void_.hpp
@@ -0,0 +1,25 @@
+#ifndef BOOST_METAPARSE_V1_IMPL_VOID_HPP
+#define BOOST_METAPARSE_V1_IMPL_VOID_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ struct void_ { typedef void_ type; };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/int_.hpp b/boost/metaparse/v1/int_.hpp
new file mode 100644
index 0000000000..12228d2c12
--- /dev/null
+++ b/boost/metaparse/v1/int_.hpp
@@ -0,0 +1,25 @@
+#ifndef BOOST_METAPARSE_V1_INT__HPP
+#define BOOST_METAPARSE_V1_INT__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/digit_val.hpp>
+#include <boost/metaparse/v1/foldl1.hpp>
+#include <boost/metaparse/v1/impl/next_digit.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ typedef foldl1<digit_val, boost::mpl::int_<0>, impl::next_digit> int_;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/is_error.hpp b/boost/metaparse/v1/is_error.hpp
new file mode 100644
index 0000000000..78866cde30
--- /dev/null
+++ b/boost/metaparse/v1/is_error.hpp
@@ -0,0 +1,43 @@
+#ifndef BOOST_METAPARSE_V1_IS_ERROR_HPP
+#define BOOST_METAPARSE_V1_IS_ERROR_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/fail_tag.hpp>
+
+#include <boost/mpl/tag.hpp>
+#include <boost/mpl/vector.hpp>
+
+#include <boost/type_traits/is_same.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class T = boost::mpl::na>
+ struct is_error :
+ boost::is_same<
+ fail_tag,
+ typename boost::mpl::tag<typename T::type>::type
+ >
+ {};
+
+ template <>
+ struct is_error<boost::mpl::na>
+ {
+ typedef is_error type;
+
+ template <class T = boost::mpl::na>
+ struct apply : is_error<T> {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/iterate.hpp b/boost/metaparse/v1/iterate.hpp
new file mode 100644
index 0000000000..8efa61efd0
--- /dev/null
+++ b/boost/metaparse/v1/iterate.hpp
@@ -0,0 +1,24 @@
+#ifndef BOOST_METAPARSE_V1_ITERATE_HPP
+#define BOOST_METAPARSE_V1_ITERATE_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/iterate_c.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class N>
+ struct iterate : iterate_c<P, N::type::value> {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/iterate_c.hpp b/boost/metaparse/v1/iterate_c.hpp
new file mode 100644
index 0000000000..bb50f15deb
--- /dev/null
+++ b/boost/metaparse/v1/iterate_c.hpp
@@ -0,0 +1,26 @@
+#ifndef BOOST_METAPARSE_V1_ITERATE_C_HPP
+#define BOOST_METAPARSE_V1_ITERATE_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/v1/impl/iterate_impl.hpp>
+
+#include <boost/mpl/deque.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, int N>
+ struct iterate_c : impl::iterate_impl<N, P, boost::mpl::deque<> > {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/keyword.hpp b/boost/metaparse/v1/keyword.hpp
new file mode 100644
index 0000000000..c5a9f60622
--- /dev/null
+++ b/boost/metaparse/v1/keyword.hpp
@@ -0,0 +1,82 @@
+#ifndef BOOST_METAPARSE_V1_KEYWORD_HPP
+#define BOOST_METAPARSE_V1_KEYWORD_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/impl/void_.hpp>
+#include <boost/metaparse/v1/lit.hpp>
+#include <boost/metaparse/v1/return_.hpp>
+#include <boost/metaparse/v1/is_error.hpp>
+#include <boost/metaparse/v1/get_remaining.hpp>
+#include <boost/metaparse/v1/get_position.hpp>
+
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/empty.hpp>
+#include <boost/mpl/pop_front.hpp>
+#include <boost/mpl/front.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ // Does not consume/check anything after the keyword
+ template <class Kw, class ResultType = impl::void_>
+ struct keyword
+ {
+ private:
+ struct nonempty
+ {
+ private:
+ typedef lit<typename boost::mpl::front<Kw>::type> next_char_parser;
+
+ typedef
+ keyword<typename boost::mpl::pop_front<Kw>::type, ResultType>
+ rest_parser;
+
+ template <class S, class Pos>
+ struct apply_unchecked :
+ rest_parser::template apply<
+ typename get_remaining<
+ typename next_char_parser::template apply<S, Pos>
+ >::type,
+ typename get_position<
+ typename next_char_parser::template apply<S, Pos>
+ >::type
+ >
+ {};
+ public:
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::eval_if<
+ typename is_error<
+ typename next_char_parser::template apply<S, Pos>
+ >::type,
+ typename next_char_parser::template apply<S, Pos>,
+ apply_unchecked<S, Pos>
+ >
+ {};
+ };
+ public:
+ typedef keyword type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::if_<
+ boost::mpl::empty<Kw>,
+ return_<ResultType>,
+ nonempty
+ >::type::template apply<S, Pos>
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/last_of.hpp b/boost/metaparse/v1/last_of.hpp
new file mode 100644
index 0000000000..583ed6db3e
--- /dev/null
+++ b/boost/metaparse/v1/last_of.hpp
@@ -0,0 +1,66 @@
+#ifndef BOOST_METAPARSE_V1_LAST_OF_HPP
+#define BOOST_METAPARSE_V1_LAST_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/nth_of.hpp>
+
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+#include <boost/preprocessor/arithmetic/sub.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 last_of;
+
+ #ifdef BOOST_METAPARSE_LAST_OF_N
+ # error BOOST_METAPARSE_LAST_OF_N already defined
+ #endif
+ #define BOOST_METAPARSE_LAST_OF_N(z, n, unused) \
+ template <BOOST_PP_ENUM_PARAMS(n, class P)> \
+ struct last_of< \
+ 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(nth_of_c, n)< \
+ n - 1 BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, P) \
+ > \
+ {};
+
+ BOOST_PP_REPEAT(
+ BOOST_METAPARSE_LIMIT_SEQUENCE_SIZE,
+ BOOST_METAPARSE_LAST_OF_N,
+ ~
+ )
+
+ #undef BOOST_METAPARSE_LAST_OF_N
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/letter.hpp b/boost/metaparse/v1/letter.hpp
new file mode 100644
index 0000000000..cf1f0d3aff
--- /dev/null
+++ b/boost/metaparse/v1/letter.hpp
@@ -0,0 +1,29 @@
+#ifndef BOOST_METAPARSE_V1_LETTER_HPP
+#define BOOST_METAPARSE_V1_LETTER_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/error/letter_expected.hpp>
+#include <boost/metaparse/v1/accept_when.hpp>
+#include <boost/metaparse/v1/one_char.hpp>
+
+#include <boost/metaparse/v1/util/is_letter.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ typedef
+ accept_when<one_char, util::is_letter<>, error::letter_expected>
+ letter;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/lit.hpp b/boost/metaparse/v1/lit.hpp
new file mode 100644
index 0000000000..c045420898
--- /dev/null
+++ b/boost/metaparse/v1/lit.hpp
@@ -0,0 +1,24 @@
+#ifndef BOOST_METAPARSE_V1_LIT_HPP
+#define BOOST_METAPARSE_V1_LIT_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/lit_c.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class C>
+ struct lit : lit_c<C::type::value> {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/lit_c.hpp b/boost/metaparse/v1/lit_c.hpp
new file mode 100644
index 0000000000..c5eccbc59a
--- /dev/null
+++ b/boost/metaparse/v1/lit_c.hpp
@@ -0,0 +1,34 @@
+#ifndef BOOST_METAPARSE_V1_LIT_C_HPP
+#define BOOST_METAPARSE_V1_LIT_C_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/error/literal_expected.hpp>
+#include <boost/metaparse/v1/accept_when.hpp>
+#include <boost/metaparse/v1/one_char.hpp>
+#include <boost/metaparse/v1/change_error_message.hpp>
+#include <boost/metaparse/v1/impl/is_char_c.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <char C>
+ struct lit_c :
+ accept_when<
+ change_error_message<one_char, error::literal_expected<C> >,
+ impl::is_char_c<C>,
+ error::literal_expected<C>
+ >
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/look_ahead.hpp b/boost/metaparse/v1/look_ahead.hpp
new file mode 100644
index 0000000000..768d980c70
--- /dev/null
+++ b/boost/metaparse/v1/look_ahead.hpp
@@ -0,0 +1,50 @@
+#ifndef BOOST_METAPARSE_V1_LOOK_AHEAD_HPP
+#define BOOST_METAPARSE_V1_LOOK_AHEAD_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/is_error.hpp>
+#include <boost/metaparse/v1/accept.hpp>
+#include <boost/metaparse/v1/get_result.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P>
+ struct look_ahead
+ {
+ private:
+ template <class S, class Pos>
+ struct no_error :
+ accept<
+ typename get_result<typename P::template apply<S, Pos> >::type,
+ S,
+ Pos
+ >
+ {};
+ public:
+ typedef look_ahead 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>,
+ no_error<S, Pos>
+ >
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/middle_of.hpp b/boost/metaparse/v1/middle_of.hpp
new file mode 100644
index 0000000000..3526153af8
--- /dev/null
+++ b/boost/metaparse/v1/middle_of.hpp
@@ -0,0 +1,48 @@
+#ifndef BOOST_METAPARSE_V1_KEEP_MIDDLE_HPP
+#define BOOST_METAPARSE_V1_KEEP_MIDDLE_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/nth_of.hpp>
+#include <boost/metaparse/v1/transform_error_message.hpp>
+#include <boost/metaparse/v1/get_col.hpp>
+#include <boost/metaparse/v1/get_line.hpp>
+
+#include <boost/metaparse/v1/error/unpaired.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P1, class P2, class P3>
+ struct middle_of
+ {
+ typedef middle_of type;
+
+ template <class S, class Pos>
+ struct apply :
+ nth_of_c<
+ 1,
+ P1,
+ P2,
+ transform_error_message<
+ P3,
+ error::unpaired<
+ get_line<Pos>::type::value,
+ get_col<Pos>::type::value
+ >
+ >
+ >::template apply<S, Pos>
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/next_char.hpp b/boost/metaparse/v1/next_char.hpp
new file mode 100644
index 0000000000..053e4fd7d1
--- /dev/null
+++ b/boost/metaparse/v1/next_char.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_METAPARSE_V1_NEXT_CHAR_HPP
+#define BOOST_METAPARSE_V1_NEXT_CHAR_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/fwd/next_char.hpp>
+
+#include <boost/mpl/tag.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class Ch>
+ struct next_char :
+ next_char_impl<
+ typename boost::mpl::tag<typename P::type>::type
+ >::template apply<typename P::type, typename Ch::type>
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/next_line.hpp b/boost/metaparse/v1/next_line.hpp
new file mode 100644
index 0000000000..4f190369cc
--- /dev/null
+++ b/boost/metaparse/v1/next_line.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_METAPARSE_V1_NEXT_LINE_HPP
+#define BOOST_METAPARSE_V1_NEXT_LINE_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/fwd/next_line.hpp>
+
+#include <boost/mpl/tag.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class Ch>
+ struct next_line :
+ next_line_impl<
+ typename boost::mpl::tag<typename P::type>::type
+ >::template apply<typename P::type, typename Ch::type>
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/nth_of.hpp b/boost/metaparse/v1/nth_of.hpp
new file mode 100644
index 0000000000..843733a91d
--- /dev/null
+++ b/boost/metaparse/v1/nth_of.hpp
@@ -0,0 +1,39 @@
+#ifndef BOOST_METAPARSE_V1_NTH_OF_HPP
+#define BOOST_METAPARSE_V1_NTH_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/v1/nth_of_c.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 <
+ class K,
+ BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
+ BOOST_METAPARSE_LIMIT_SEQUENCE_SIZE,
+ class P,
+ boost::mpl::na
+ )
+ >
+ struct nth_of :
+ nth_of_c<
+ K::type::value,
+ BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_SEQUENCE_SIZE, P)
+ >
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/nth_of_c.hpp b/boost/metaparse/v1/nth_of_c.hpp
new file mode 100644
index 0000000000..12af00a224
--- /dev/null
+++ b/boost/metaparse/v1/nth_of_c.hpp
@@ -0,0 +1,70 @@
+#ifndef BOOST_METAPARSE_V1_NTH_OF_C_HPP
+#define BOOST_METAPARSE_V1_NTH_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/impl/nth_of_c.hpp>
+#include <boost/metaparse/limit_sequence_size.hpp>
+
+#include <boost/preprocessor/repetition/repeat.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/punctuation/comma_if.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 <
+ int N,
+ BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
+ BOOST_METAPARSE_LIMIT_SEQUENCE_SIZE,
+ class P,
+ boost::mpl::na
+ )
+ >
+ struct nth_of_c;
+
+ #ifdef BOOST_METAPARSE_NTH_OF_N
+ # error BOOST_METAPARSE_NTH_OF_N already defined
+ #endif
+ #define BOOST_METAPARSE_NTH_OF_N(z, n, unused) \
+ template <int K BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class P)> \
+ struct nth_of_c< \
+ K, \
+ 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(nth_of_c, n)< \
+ K BOOST_PP_COMMA_IF(n) \
+ BOOST_PP_ENUM_PARAMS(n, P) \
+ > \
+ {};
+
+ BOOST_PP_REPEAT(
+ BOOST_METAPARSE_LIMIT_SEQUENCE_SIZE,
+ BOOST_METAPARSE_NTH_OF_N,
+ ~
+ )
+
+ #undef BOOST_METAPARSE_NTH_OF_N
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/one_char.hpp b/boost/metaparse/v1/one_char.hpp
new file mode 100644
index 0000000000..0b129b2702
--- /dev/null
+++ b/boost/metaparse/v1/one_char.hpp
@@ -0,0 +1,71 @@
+#ifndef BOOST_METAPARSE_V1_ONE_CHAR_HPP
+#define BOOST_METAPARSE_V1_ONE_CHAR_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2009 - 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_end_of_input.hpp>
+#include <boost/metaparse/v1/next_char.hpp>
+#include <boost/metaparse/v1/next_line.hpp>
+#include <boost/metaparse/v1/accept.hpp>
+#include <boost/metaparse/v1/reject.hpp>
+#include <boost/metaparse/v1/get_prev_char.hpp>
+
+#include <boost/mpl/empty.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/front.hpp>
+#include <boost/mpl/pop_front.hpp>
+#include <boost/mpl/bool.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ struct one_char
+ {
+ private:
+ template <class C, class Pos>
+ struct next_pos :
+ boost::mpl::eval_if<
+ boost::mpl::bool_<
+ C::type::value == '\r'
+ || (
+ C::type::value == '\n'
+ && get_prev_char<Pos>::type::value != '\r'
+ )
+ >,
+ next_line<Pos, C>,
+ next_char<Pos, C>
+ >
+ {};
+
+ template <class S, class NextPos>
+ struct unchecked :
+ accept<
+ typename boost::mpl::front<S>::type,
+ boost::mpl::pop_front<S>,
+ NextPos
+ >
+ {};
+ public:
+ typedef one_char type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::eval_if<
+ typename boost::mpl::empty<S>::type,
+ reject<error::unexpected_end_of_input, Pos>,
+ unchecked<S, next_pos<boost::mpl::front<S>, Pos> >
+ >
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/one_char_except.hpp b/boost/metaparse/v1/one_char_except.hpp
new file mode 100644
index 0000000000..c859ab23f3
--- /dev/null
+++ b/boost/metaparse/v1/one_char_except.hpp
@@ -0,0 +1,85 @@
+#ifndef BOOST_METAPARSE_V1_ONE_CHAR_EXCEPT_HPP
+#define BOOST_METAPARSE_V1_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/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/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
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/one_char_except_c.hpp b/boost/metaparse/v1/one_char_except_c.hpp
new file mode 100644
index 0000000000..780cb5924f
--- /dev/null
+++ b/boost/metaparse/v1/one_char_except_c.hpp
@@ -0,0 +1,96 @@
+#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.
+// Distributed under the 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/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
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/one_of.hpp b/boost/metaparse/v1/one_of.hpp
new file mode 100644
index 0000000000..d48db4c4c0
--- /dev/null
+++ b/boost/metaparse/v1/one_of.hpp
@@ -0,0 +1,42 @@
+#ifndef BOOST_METAPARSE_V1_ONE_OF_HPP
+#define BOOST_METAPARSE_V1_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/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/one_of_c.hpp b/boost/metaparse/v1/one_of_c.hpp
new file mode 100644
index 0000000000..ff7251a4e0
--- /dev/null
+++ b/boost/metaparse/v1/one_of_c.hpp
@@ -0,0 +1,80 @@
+#ifndef BOOST_METAPARSE_V1_ONE_OF_C_HPP
+#define BOOST_METAPARSE_V1_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/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/optional.hpp b/boost/metaparse/v1/optional.hpp
new file mode 100644
index 0000000000..efebcd4663
--- /dev/null
+++ b/boost/metaparse/v1/optional.hpp
@@ -0,0 +1,40 @@
+#ifndef BOOST_METAPARSE_V1_OPTIONAL_HPP
+#define BOOST_METAPARSE_V1_OPTIONAL_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/is_error.hpp>
+#include <boost/metaparse/v1/accept.hpp>
+
+#include <boost/mpl/if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class Default = void>
+ struct optional
+ {
+ typedef optional type;
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::if_<
+ is_error<typename P::template apply<S, Pos> >,
+ accept<Default, S, Pos>,
+ // is_error evaluates it anyway
+ typename P::template apply<S, Pos>::type
+ >
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/range.hpp b/boost/metaparse/v1/range.hpp
new file mode 100644
index 0000000000..efddfc41f8
--- /dev/null
+++ b/boost/metaparse/v1/range.hpp
@@ -0,0 +1,33 @@
+#ifndef BOOST_METAPARSE_V1_RANGE_HPP
+#define BOOST_METAPARSE_V1_RANGE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/accept_when.hpp>
+#include <boost/metaparse/v1/one_char.hpp>
+#include <boost/metaparse/v1/util/in_range_c.hpp>
+#include <boost/metaparse/v1/error/unexpected_character.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class From, class To>
+ struct range :
+ accept_when<
+ one_char,
+ util::in_range_c<char, From::type::value, To::type::value>,
+ error::unexpected_character
+ >
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/range_c.hpp b/boost/metaparse/v1/range_c.hpp
new file mode 100644
index 0000000000..d843df19c9
--- /dev/null
+++ b/boost/metaparse/v1/range_c.hpp
@@ -0,0 +1,33 @@
+#ifndef BOOST_METAPARSE_V1_RANGE_C_HPP
+#define BOOST_METAPARSE_V1_RANGE_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/accept_when.hpp>
+#include <boost/metaparse/v1/one_char.hpp>
+#include <boost/metaparse/v1/util/in_range_c.hpp>
+#include <boost/metaparse/v1/error/unexpected_character.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <char From, char To>
+ struct range_c :
+ accept_when<
+ one_char,
+ util::in_range_c<char, From, To>,
+ error::unexpected_character
+ >
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/reject.hpp b/boost/metaparse/v1/reject.hpp
new file mode 100644
index 0000000000..a25e3b0dbe
--- /dev/null
+++ b/boost/metaparse/v1/reject.hpp
@@ -0,0 +1,33 @@
+#ifndef BOOST_METAPARSE_V1_REJECT_HPP
+#define BOOST_METAPARSE_V1_REJECT_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/fwd/reject.hpp>
+#include <boost/metaparse/v1/fail_tag.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class Msg, class Pos>
+ struct reject
+ {
+ typedef fail_tag tag;
+
+ typedef reject<Msg, typename Pos::type> type;
+
+ typedef Pos source_position;
+ typedef Msg message;
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/repeated.hpp b/boost/metaparse/v1/repeated.hpp
new file mode 100644
index 0000000000..111f3a10d0
--- /dev/null
+++ b/boost/metaparse/v1/repeated.hpp
@@ -0,0 +1,27 @@
+#ifndef BOOST_METAPARSE_V1_REPEATED_HPP
+#define BOOST_METAPARSE_V1_REPEATED_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/foldl.hpp>
+#include <boost/metaparse/v1/impl/back_inserter.hpp>
+
+#include <boost/mpl/vector.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P>
+ struct repeated : foldl<P, boost::mpl::vector<>, impl::back_inserter> {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/repeated1.hpp b/boost/metaparse/v1/repeated1.hpp
new file mode 100644
index 0000000000..ea77b20385
--- /dev/null
+++ b/boost/metaparse/v1/repeated1.hpp
@@ -0,0 +1,29 @@
+#ifndef BOOST_METAPARSE_V1_REPEATED1_HPP
+#define BOOST_METAPARSE_V1_REPEATED1_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/foldl1.hpp>
+#include <boost/metaparse/v1/impl/back_inserter.hpp>
+
+#include <boost/mpl/vector.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P>
+ struct repeated1 :
+ foldl1<P, boost::mpl::vector<>, impl::back_inserter>
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/repeated_one_of.hpp b/boost/metaparse/v1/repeated_one_of.hpp
new file mode 100644
index 0000000000..3296030b62
--- /dev/null
+++ b/boost/metaparse/v1/repeated_one_of.hpp
@@ -0,0 +1,45 @@
+#ifndef BOOST_METAPARSE_V1_REPEATED_ONE_OF_HPP
+#define BOOST_METAPARSE_V1_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/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/repeated_one_of1.hpp b/boost/metaparse/v1/repeated_one_of1.hpp
new file mode 100644
index 0000000000..2d305d2abd
--- /dev/null
+++ b/boost/metaparse/v1/repeated_one_of1.hpp
@@ -0,0 +1,45 @@
+#ifndef BOOST_METAPARSE_V1_REPEATED_ONE_OF1_HPP
+#define BOOST_METAPARSE_V1_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/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/repeated_reject_incomplete.hpp b/boost/metaparse/v1/repeated_reject_incomplete.hpp
new file mode 100644
index 0000000000..ec82597949
--- /dev/null
+++ b/boost/metaparse/v1/repeated_reject_incomplete.hpp
@@ -0,0 +1,29 @@
+#ifndef BOOST_METAPARSE_V1_REPEATED_REJECT_INCOMPLETE_HPP
+#define BOOST_METAPARSE_V1_REPEATED_REJECT_INCOMPLETE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/foldl_reject_incomplete.hpp>
+#include <boost/metaparse/v1/impl/back_inserter.hpp>
+
+#include <boost/mpl/vector.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P>
+ struct repeated_reject_incomplete :
+ foldl_reject_incomplete<P, boost::mpl::vector<>, impl::back_inserter>
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/repeated_reject_incomplete1.hpp b/boost/metaparse/v1/repeated_reject_incomplete1.hpp
new file mode 100644
index 0000000000..e67ca8e8f1
--- /dev/null
+++ b/boost/metaparse/v1/repeated_reject_incomplete1.hpp
@@ -0,0 +1,29 @@
+#ifndef BOOST_METAPARSE_V1_REPEATED_REJECT_INCOMPLETE1_HPP
+#define BOOST_METAPARSE_V1_REPEATED_REJECT_INCOMPLETE1_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/foldl_reject_incomplete1.hpp>
+#include <boost/metaparse/v1/impl/back_inserter.hpp>
+
+#include <boost/mpl/vector.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P>
+ struct repeated_reject_incomplete1 :
+ foldl_reject_incomplete1<P, boost::mpl::vector<>, impl::back_inserter>
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/return_.hpp b/boost/metaparse/v1/return_.hpp
new file mode 100644
index 0000000000..5333b106c6
--- /dev/null
+++ b/boost/metaparse/v1/return_.hpp
@@ -0,0 +1,34 @@
+#ifndef BOOST_METAPARSE_V1_RETURN__HPP
+#define BOOST_METAPARSE_V1_RETURN__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/accept.hpp>
+#include <boost/metaparse/v1/get_result.hpp>
+
+
+#include <iostream>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class C>
+ struct return_
+ {
+ typedef return_ type;
+
+ template <class S, class Pos>
+ struct apply : accept<C, S, Pos> {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/sequence.hpp b/boost/metaparse/v1/sequence.hpp
new file mode 100644
index 0000000000..f25c632fbd
--- /dev/null
+++ b/boost/metaparse/v1/sequence.hpp
@@ -0,0 +1,64 @@
+#ifndef BOOST_METAPARSE_V1_SEQUENCE_HPP
+#define BOOST_METAPARSE_V1_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/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/sequence_apply.hpp b/boost/metaparse/v1/sequence_apply.hpp
new file mode 100644
index 0000000000..54ee03fa23
--- /dev/null
+++ b/boost/metaparse/v1/sequence_apply.hpp
@@ -0,0 +1,80 @@
+#ifndef BOOST_METAPARSE_V1_SEQUENCE_APPLY_HPP
+#define BOOST_METAPARSE_V1_SEQUENCE_APPLY_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/letter.hpp>
+#include <boost/metaparse/v1/sequence.hpp>
+
+#include <boost/metaparse/limit_sequence_size.hpp>
+
+#include <boost/mpl/at.hpp>
+
+#include <boost/preprocessor/cat.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/tuple/eat.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+#ifdef BOOST_METAPARSE_SEQUENCE_APPLY_ARG
+# error BOOST_METAPARSE_SEQUENCE_APPLY_ARG already defined
+#endif
+#define BOOST_METAPARSE_SEQUENCE_APPLY_ARG(z, n, container) \
+ typename boost::mpl::at_c<container, n>::type
+
+#ifdef BOOST_METAPARSE_SEQUENCE_APPLY
+# error BOOST_METAPARSE_SEQUENCE_APPLY already defined
+#endif
+#define BOOST_METAPARSE_SEQUENCE_APPLY(z, n, unused) \
+ namespace impl \
+ { \
+ template < \
+ template <BOOST_PP_ENUM(n, class BOOST_PP_TUPLE_EAT(3), ~)> class T \
+ > \
+ struct BOOST_PP_CAT(sequence_apply_transform, n) \
+ { \
+ typedef BOOST_PP_CAT(sequence_apply_transform, n) type; \
+ \
+ template <class V> \
+ struct apply \
+ { \
+ typedef T<BOOST_PP_ENUM(n, BOOST_METAPARSE_SEQUENCE_APPLY_ARG, V)> type; \
+ }; \
+ }; \
+ } \
+ \
+ template < \
+ template <BOOST_PP_ENUM(n, class BOOST_PP_TUPLE_EAT(3), ~)> class T, \
+ BOOST_PP_ENUM_PARAMS(n, class P) \
+ > \
+ struct BOOST_PP_CAT(sequence_apply, n) : \
+ transform< \
+ sequence<BOOST_PP_ENUM_PARAMS(n, P)>, \
+ BOOST_PP_CAT(impl::sequence_apply_transform, n)<T> \
+ > \
+ {};
+
+ BOOST_PP_REPEAT_FROM_TO(
+ 1,
+ BOOST_METAPARSE_LIMIT_SEQUENCE_SIZE,
+ BOOST_METAPARSE_SEQUENCE_APPLY,
+ ~
+ )
+
+#undef BOOST_METAPARSE_SEQUENCE_APPLY
+#undef BOOST_METAPARSE_SEQUENCE_APPLY_ARG
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/source_position.hpp b/boost/metaparse/v1/source_position.hpp
new file mode 100644
index 0000000000..3548940ea9
--- /dev/null
+++ b/boost/metaparse/v1/source_position.hpp
@@ -0,0 +1,156 @@
+#ifndef BOOST_METAPARSE_V1_SOURCE_POSITION_HPP
+#define BOOST_METAPARSE_V1_SOURCE_POSITION_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/fwd/source_position.hpp>
+#include <boost/metaparse/v1/source_position_tag.hpp>
+
+
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/less.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class Line, class Col, class PrevChar>
+ struct source_position
+ {
+ typedef source_position_tag tag;
+ typedef source_position type;
+
+ typedef Line line;
+ typedef Col col;
+ typedef PrevChar prev_char;
+ };
+ }
+ }
+}
+
+namespace boost
+{
+ namespace mpl
+ {
+ template <class TagA, class TagB>
+ struct equal_to_impl;
+
+ template <>
+ struct equal_to_impl<
+ boost::metaparse::v1::source_position_tag,
+ boost::metaparse::v1::source_position_tag
+ >
+ {
+ typedef equal_to_impl type;
+
+ template <class A, class B>
+ struct apply :
+ bool_<
+ A::type::line::value == B::type::line::value
+ && A::type::col::value == B::type::col::value
+ && A::type::prev_char::value == B::type::prev_char::value
+ >
+ {};
+ };
+
+ template <class TagA, class TagB>
+ struct not_equal_to_impl;
+
+ template <>
+ struct not_equal_to_impl<
+ boost::metaparse::v1::source_position_tag,
+ boost::metaparse::v1::source_position_tag
+ >
+ {
+ typedef not_equal_to_impl type;
+
+ template <class A, class B>
+ struct apply : bool_<!equal_to<A, B>::type::value> {};
+ };
+
+ template <class TagA, class TagB>
+ struct less_impl;
+
+ template <>
+ struct less_impl<
+ boost::metaparse::v1::source_position_tag,
+ boost::metaparse::v1::source_position_tag
+ >
+ {
+ typedef less_impl type;
+
+ template <class A, class B>
+ struct apply :
+ bool_<(
+ (A::type::line::value) < (B::type::line::value) || (
+ (A::type::line::value) == (B::type::line::value) && (
+ (A::type::col::value) < (B::type::col::value) || (
+ (A::type::col::value) == (B::type::col::value) &&
+ (A::type::prev_char::value) < (B::type::prev_char::value)
+ )
+ )
+ )
+ )>
+ {};
+ };
+
+ template <class TagA, class TagB>
+ struct greater_impl;
+
+ template <>
+ struct greater_impl<
+ boost::metaparse::v1::source_position_tag,
+ boost::metaparse::v1::source_position_tag
+ >
+ {
+ typedef greater_impl type;
+
+ template <class A, class B>
+ struct apply :
+ bool_<!(less<A, B>::type::value || equal_to<A, B>::type::value)>
+ {};
+ };
+
+ template <class TagA, class TagB>
+ struct greater_equal_impl;
+
+ template <>
+ struct greater_equal_impl<
+ boost::metaparse::v1::source_position_tag,
+ boost::metaparse::v1::source_position_tag
+ >
+ {
+ typedef greater_equal_impl type;
+
+ template <class A, class B>
+ struct apply : bool_<!less<A, B>::type::value> {};
+ };
+
+ template <class TagA, class TagB>
+ struct less_equal_impl;
+
+ template <>
+ struct less_equal_impl<
+ boost::metaparse::v1::source_position_tag,
+ boost::metaparse::v1::source_position_tag
+ >
+ {
+ typedef less_equal_impl type;
+
+ template <class A, class B>
+ struct apply :
+ bool_<less<A, B>::type::value || equal_to<A, B>::type::value>
+ {};
+ };
+
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/source_position_tag.hpp b/boost/metaparse/v1/source_position_tag.hpp
new file mode 100644
index 0000000000..d0178bce35
--- /dev/null
+++ b/boost/metaparse/v1/source_position_tag.hpp
@@ -0,0 +1,80 @@
+#ifndef BOOST_METAPARSE_V1_SOURCE_POSITION_TAG_HPP
+#define BOOST_METAPARSE_V1_SOURCE_POSITION_TAG_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/fwd/source_position.hpp>
+#include <boost/metaparse/v1/fwd/get_prev_char.hpp>
+#include <boost/metaparse/v1/fwd/next_line.hpp>
+#include <boost/metaparse/v1/fwd/next_char.hpp>
+#include <boost/metaparse/v1/get_col.hpp>
+#include <boost/metaparse/v1/get_line.hpp>
+
+
+#include <boost/mpl/int.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ struct source_position_tag { typedef source_position_tag type; };
+
+ template <>
+ struct get_col_impl<source_position_tag>
+ {
+ template <class P>
+ struct apply : P::col {};
+ };
+
+ template <>
+ struct get_line_impl<source_position_tag>
+ {
+ template <class P>
+ struct apply : P::line {};
+ };
+
+
+ template <>
+ struct get_prev_char_impl<source_position_tag>
+ {
+ template <class P>
+ struct apply : P::prev_char {};
+ };
+
+
+ template <>
+ struct next_char_impl<source_position_tag>
+ {
+ template <class P, class Ch>
+ struct apply :
+ source_position<
+ typename get_line<P>::type,
+ boost::mpl::int_<get_col<P>::type::value + 1>,
+ Ch
+ >
+ {};
+ };
+
+ template <>
+ struct next_line_impl<source_position_tag>
+ {
+ template <class P, class Ch>
+ struct apply :
+ source_position<
+ boost::mpl::int_<get_line<P>::type::value + 1>,
+ boost::mpl::int_<1>,
+ Ch
+ >
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/space.hpp b/boost/metaparse/v1/space.hpp
new file mode 100644
index 0000000000..dda377b422
--- /dev/null
+++ b/boost/metaparse/v1/space.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_METAPARSE_V1_SPACE_HPP
+#define BOOST_METAPARSE_V1_SPACE_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/error/whitespace_expected.hpp>
+#include <boost/metaparse/v1/accept_when.hpp>
+#include <boost/metaparse/v1/one_char.hpp>
+
+#include <boost/metaparse/v1/util/is_whitespace.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ typedef
+ accept_when<one_char, util::is_whitespace<>, error::whitespace_expected>
+ space;
+ }
+ }
+}
+
+#endif
+
+
diff --git a/boost/metaparse/v1/spaces.hpp b/boost/metaparse/v1/spaces.hpp
new file mode 100644
index 0000000000..6d35ee7893
--- /dev/null
+++ b/boost/metaparse/v1/spaces.hpp
@@ -0,0 +1,24 @@
+#ifndef BOOST_METAPARSE_V1_SPACES_HPP
+#define BOOST_METAPARSE_V1_SPACES_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/repeated1.hpp>
+#include <boost/metaparse/v1/space.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ typedef repeated1<space> spaces;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/start.hpp b/boost/metaparse/v1/start.hpp
new file mode 100644
index 0000000000..d38b897968
--- /dev/null
+++ b/boost/metaparse/v1/start.hpp
@@ -0,0 +1,32 @@
+#ifndef BOOST_METAPARSE_V1_START_HPP
+#define BOOST_METAPARSE_V1_START_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/source_position.hpp>
+
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/char.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ typedef
+ source_position<
+ boost::mpl::int_<1>,
+ boost::mpl::int_<1>,
+ boost::mpl::char_<0>
+ >
+ start;
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/string.hpp b/boost/metaparse/v1/string.hpp
new file mode 100644
index 0000000000..d72c28ec94
--- /dev/null
+++ b/boost/metaparse/v1/string.hpp
@@ -0,0 +1,408 @@
+#ifndef BOOST_METAPARSE_V1_STRING_HPP
+#define BOOST_METAPARSE_V1_STRING_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/config.hpp>
+#include <boost/metaparse/v1/fwd/string.hpp>
+#include <boost/metaparse/v1/string_tag.hpp>
+#include <boost/metaparse/v1/impl/string_iterator.hpp>
+#include <boost/metaparse/v1/impl/empty_string.hpp>
+#include <boost/metaparse/v1/impl/size.hpp>
+#include <boost/metaparse/v1/impl/pop_front.hpp>
+#include <boost/metaparse/v1/impl/push_front_c.hpp>
+#include <boost/metaparse/v1/impl/push_back_c.hpp>
+#include <boost/metaparse/v1/impl/pop_back.hpp>
+#include <boost/metaparse/v1/impl/assert_string_length.hpp>
+
+
+#include <boost/preprocessor/arithmetic/sub.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+#include <boost/preprocessor/tuple/eat.hpp>
+
+#include <boost/type_traits/is_same.hpp>
+
+/*
+ * The string type
+ */
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+#ifdef BOOST_METAPARSE_VARIADIC_STRING
+ template <char... Cs>
+ struct string
+ {
+ typedef string type;
+ typedef string_tag tag;
+ };
+#else
+ template <BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C)>
+ struct string
+ {
+ typedef string type;
+ typedef string_tag tag;
+ };
+#endif
+ }
+ }
+}
+
+/*
+ * Boost.MPL overloads
+ */
+
+namespace boost
+{
+ namespace mpl
+ {
+ // push_back
+ template <class S>
+ struct push_back_impl;
+
+ template <>
+ struct push_back_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef push_back_impl type;
+
+ template <class S, class C>
+ struct apply :
+ boost::metaparse::v1::impl::push_back_c<
+ typename S::type,
+ C::type::value
+ >
+ {};
+ };
+
+ // pop_back
+ template <class S>
+ struct pop_back_impl;
+
+ template <>
+ struct pop_back_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef pop_back_impl type;
+
+ template <class S>
+ struct apply : boost::metaparse::v1::impl::pop_back<S> {};
+ };
+
+ // push_front
+ template <class S>
+ struct push_front_impl;
+
+ template <>
+ struct push_front_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef push_front_impl type;
+
+ template <class S, class C>
+ struct apply :
+ boost::metaparse::v1::impl::push_front_c<
+ typename S::type,
+ C::type::value
+ >
+ {};
+ };
+
+ // pop_front
+ template <class S>
+ struct pop_front_impl;
+
+ template <>
+ struct pop_front_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef pop_front_impl type;
+
+ template <class S>
+ struct apply : boost::metaparse::v1::impl::pop_front<S> {};
+ };
+
+ // clear
+ template <class S>
+ struct clear_impl;
+
+ template <>
+ struct clear_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef clear_impl type;
+
+ template <class S>
+ struct apply : boost::metaparse::v1::string<> {};
+ };
+
+ // begin
+ template <class S>
+ struct begin_impl;
+
+ template <>
+ struct begin_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef begin_impl type;
+
+ template <class S>
+ struct apply :
+ boost::metaparse::v1::impl::string_iterator<typename S::type, 0>
+ {};
+ };
+
+ // end
+ template <class S>
+ struct end_impl;
+
+ template <>
+ struct end_impl<boost::metaparse::v1::string_tag>
+ {
+ typedef end_impl type;
+
+ template <class S>
+ struct apply :
+ boost::metaparse::v1::impl::string_iterator<
+ typename S::type,
+ boost::metaparse::v1::impl::size<typename S::type>::type::value
+ >
+ {};
+ };
+
+ // equal_to
+ template <class A, class B>
+ struct equal_to_impl;
+
+ template <>
+ struct equal_to_impl<
+ boost::metaparse::v1::string_tag,
+ boost::metaparse::v1::string_tag
+ >
+ {
+ typedef equal_to_impl type;
+
+ template <class A, class B>
+ struct apply : boost::is_same<typename A::type, typename B::type> {};
+ };
+
+ template <class T>
+ struct equal_to_impl<boost::metaparse::v1::string_tag, T>
+ {
+ typedef equal_to_impl type;
+
+ template <class, class>
+ struct apply : false_ {};
+ };
+
+ template <class T>
+ struct equal_to_impl<T, boost::metaparse::v1::string_tag> :
+ equal_to_impl<boost::metaparse::v1::string_tag, T>
+ {};
+
+ // c_str
+ template <class S>
+ struct c_str;
+
+#ifdef BOOST_METAPARSE_VARIADIC_STRING
+ template <char... Cs>
+ struct c_str<boost::metaparse::v1::string<Cs...>>
+ {
+ typedef c_str type;
+ #ifdef BOOST_NO_CONSTEXPR_C_STR
+ static const char value[sizeof...(Cs) + 1];
+ #else
+ static constexpr char value[sizeof...(Cs) + 1] = {Cs..., 0};
+ #endif
+ };
+
+ template <>
+ struct c_str<boost::metaparse::v1::string<>> :
+ boost::metaparse::v1::impl::empty_string<>
+ {};
+
+ #ifdef BOOST_NO_CONSTEXPR_C_STR
+ template <char... Cs>
+ const char c_str<boost::metaparse::v1::string<Cs...>>::value[]
+ = {Cs..., 0};
+ #else
+ template <char... Cs>
+ constexpr char c_str<boost::metaparse::v1::string<Cs...>>::value[];
+ #endif
+
+#else
+ template <BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C)>
+ struct c_str<
+ boost::metaparse::v1::string<
+ BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C)
+ >
+ >
+ {
+ typedef c_str type;
+ static BOOST_CONSTEXPR const char
+ value[BOOST_METAPARSE_LIMIT_STRING_SIZE + 1]
+ #if !defined BOOST_NO_CONSTEXPR && !defined BOOST_NO_CXX11_CONSTEXPR
+ = {BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C), 0}
+ #endif
+ ;
+ };
+
+ template <BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C)>
+ BOOST_CONSTEXPR const char
+ c_str<
+ boost::metaparse::v1::string<
+ BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C)
+ >
+ >::value[BOOST_METAPARSE_LIMIT_STRING_SIZE + 1]
+ #if defined BOOST_NO_CONSTEXPR || defined BOOST_NO_CXX11_CONSTEXPR
+ = {BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C), 0}
+ #endif
+ ;
+
+ template <>
+ struct c_str<boost::metaparse::v1::string<> > :
+ boost::metaparse::v1::impl::empty_string<>
+ {
+ typedef c_str type;
+ };
+
+ #ifdef BOOST_METAPARSE_DEF
+ # error BOOST_METAPARSE_DEF already defined
+ #endif
+ #define BOOST_METAPARSE_DEF(n) \
+ = {BOOST_PP_ENUM_PARAMS(n, C) BOOST_PP_COMMA_IF(n) 0}
+
+ #ifdef BOOST_METAPARSE_STRING_DECLARE
+ # error BOOST_METAPARSE_STRING_DECLARE already defined
+ #endif
+ #ifdef BOOST_METAPARSE_STRING_DEFINE
+ # error BOOST_METAPARSE_STRING_DECLARE already defined
+ #endif
+ #if !defined BOOST_NO_CONSTEXPR && !defined BOOST_NO_CXX11_CONSTEXPR
+ # define BOOST_METAPARSE_STRING_DECLARE(n) BOOST_METAPARSE_DEF(n)
+ # define BOOST_METAPARSE_STRING_DEFINE(n)
+ #else
+ # define BOOST_METAPARSE_STRING_DECLARE(n)
+ # define BOOST_METAPARSE_STRING_DEFINE(n) BOOST_METAPARSE_DEF(n)
+ #endif
+
+ #ifdef BOOST_METAPARSE_STRING_CASE
+ # error BOOST_METAPARSE_STRING_CASE is already defined
+ #endif
+ #define BOOST_METAPARSE_STRING_CASE(z, n, unused) \
+ template <BOOST_PP_ENUM_PARAMS(n, int C)> \
+ struct \
+ c_str< \
+ boost::metaparse::v1::string< \
+ BOOST_PP_ENUM_PARAMS(n, C) BOOST_PP_COMMA_IF(n) \
+ BOOST_PP_ENUM( \
+ BOOST_PP_SUB(BOOST_METAPARSE_LIMIT_STRING_SIZE, n), \
+ BOOST_NO_CHAR BOOST_PP_TUPLE_EAT(3), \
+ ~ \
+ ) \
+ > \
+ > \
+ { \
+ typedef c_str type; \
+ static BOOST_CONSTEXPR const char value[n + 1] \
+ BOOST_METAPARSE_STRING_DECLARE(n); \
+ }; \
+ \
+ template <BOOST_PP_ENUM_PARAMS(n, int C)> \
+ BOOST_CONSTEXPR const char c_str< \
+ boost::metaparse::v1::string< \
+ BOOST_PP_ENUM_PARAMS(n, C) BOOST_PP_COMMA_IF(n) \
+ BOOST_PP_ENUM( \
+ BOOST_PP_SUB(BOOST_METAPARSE_LIMIT_STRING_SIZE, n), \
+ BOOST_NO_CHAR BOOST_PP_TUPLE_EAT(3), \
+ ~ \
+ ) \
+ > \
+ >::value[n + 1] BOOST_METAPARSE_STRING_DEFINE(n);
+
+ BOOST_PP_REPEAT_FROM_TO(
+ 1,
+ BOOST_METAPARSE_LIMIT_STRING_SIZE,
+ BOOST_METAPARSE_STRING_CASE,
+ ~
+ )
+
+ #undef BOOST_METAPARSE_STRING_CASE
+ #undef BOOST_METAPARSE_STRING_DECLARE
+ #undef BOOST_METAPARSE_STRING_DEFINE
+ #undef BOOST_METAPARSE_DEF
+#endif
+ }
+}
+
+/*
+ * The BOOST_METAPARSE_STRING macro
+ */
+
+#if \
+ !defined BOOST_NO_CONSTEXPR && !defined BOOST_NO_CXX11_CONSTEXPR \
+ && !defined BOOST_CONFIG_NO_BOOST_METAPARSE_STRING
+
+#include <boost/metaparse/v1/impl/remove_trailing_no_chars.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace impl
+ {
+ template <int Len, class T>
+ constexpr int string_at(const T (&s)[Len], int n)
+ {
+ return n >= Len - 1 ? BOOST_NO_CHAR : s[n];
+ }
+ }
+ }
+ }
+}
+
+ #ifdef BOOST_METAPARSE_V1_STRING_N
+ # error BOOST_METAPARSE_V1_STRING_N already defined
+ #endif
+ #define BOOST_METAPARSE_V1_STRING_N(z, n, s) \
+ boost::metaparse::v1::impl::string_at((s), n)
+
+ #ifdef BOOST_METAPARSE_V1_STRING
+ # error BOOST_METAPARSE_V1_STRING already defined
+ #endif
+ #define BOOST_METAPARSE_V1_STRING(s) \
+ boost::metaparse::v1::impl::assert_string_length< \
+ sizeof(s) - 1, \
+ boost::metaparse::v1::impl::remove_trailing_no_chars< \
+ boost::metaparse::v1::string< \
+ BOOST_PP_ENUM( \
+ BOOST_METAPARSE_LIMIT_STRING_SIZE, \
+ BOOST_METAPARSE_V1_STRING_N, \
+ s \
+ ) \
+ > \
+ > \
+ >::type
+
+#else
+
+ // Include it only when it is needed
+ #include <boost/static_assert.hpp>
+
+ #ifdef BOOST_METAPARSE_V1_STRING
+ # error BOOST_METAPARSE_V1_STRING already defined
+ #endif
+ #define BOOST_METAPARSE_V1_STRING(s) \
+ BOOST_STATIC_ASSERT_MSG(false, "BOOST_METAPARSE_STRING is not supported")
+
+ #define BOOST_METAPARSE_V1_CONFIG_NO_BOOST_METAPARSE_STRING
+
+#endif
+
+#endif
+
diff --git a/boost/metaparse/v1/string_tag.hpp b/boost/metaparse/v1/string_tag.hpp
new file mode 100644
index 0000000000..f60a9fa731
--- /dev/null
+++ b/boost/metaparse/v1/string_tag.hpp
@@ -0,0 +1,24 @@
+#ifndef BOOST_METAPARSE_V1_STRING_TAG_HPP
+#define BOOST_METAPARSE_V1_STRING_TAG_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ struct string_tag
+ {
+ typedef string_tag type;
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/swap.hpp b/boost/metaparse/v1/swap.hpp
new file mode 100644
index 0000000000..b73ebf1b32
--- /dev/null
+++ b/boost/metaparse/v1/swap.hpp
@@ -0,0 +1,29 @@
+#ifndef BOOST_METAPARSE_V1_SWAP_HPP
+#define BOOST_METAPARSE_V1_SWAP_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class F>
+ struct swap
+ {
+ typedef swap type;
+
+ template <class A, class B>
+ struct apply : F::template apply<B, A> {};
+ };
+ }
+ }
+}
+
+#endif
+
+
diff --git a/boost/metaparse/v1/token.hpp b/boost/metaparse/v1/token.hpp
new file mode 100644
index 0000000000..5eef9a0bff
--- /dev/null
+++ b/boost/metaparse/v1/token.hpp
@@ -0,0 +1,28 @@
+#ifndef BOOST_METAPARSE_V1_TOKEN_HPP
+#define BOOST_METAPARSE_V1_TOKEN_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/space.hpp>
+#include <boost/metaparse/v1/repeated.hpp>
+#include <boost/metaparse/v1/first_of.hpp>
+
+#include <boost/mpl/void.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P>
+ struct token : first_of<P, repeated<space> > {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/transform.hpp b/boost/metaparse/v1/transform.hpp
new file mode 100644
index 0000000000..7573210a0c
--- /dev/null
+++ b/boost/metaparse/v1/transform.hpp
@@ -0,0 +1,50 @@
+#ifndef BOOST_METAPARSE_V1_TRANSFORM_HPP
+#define BOOST_METAPARSE_V1_TRANSFORM_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/accept.hpp>
+#include <boost/metaparse/v1/get_result.hpp>
+#include <boost/metaparse/v1/get_remaining.hpp>
+#include <boost/metaparse/v1/get_position.hpp>
+#include <boost/metaparse/v1/unless_error.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class T>
+ struct transform
+ {
+ private:
+ template <class S, class Pos>
+ struct no_error :
+ accept<
+ typename T::template apply<
+ typename get_result<typename P::template apply<S, Pos> >::type
+ >::type,
+ get_remaining<typename P::template apply<S, Pos> >,
+ get_position<typename P::template apply<S, Pos> >
+ >
+ {};
+ public:
+ typedef transform type;
+
+ template <class S, class Pos>
+ struct apply :
+ unless_error<typename P::template apply<S, Pos>, no_error<S, Pos> >
+ {};
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/transform_error.hpp b/boost/metaparse/v1/transform_error.hpp
new file mode 100644
index 0000000000..87ce37b84b
--- /dev/null
+++ b/boost/metaparse/v1/transform_error.hpp
@@ -0,0 +1,40 @@
+#ifndef BOOST_METAPARSE_V1_TRANSFORM_ERROR_HPP
+#define BOOST_METAPARSE_V1_TRANSFORM_ERROR_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/is_error.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class F>
+ struct transform_error
+ {
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::eval_if<
+ typename is_error<typename P::template apply<S, Pos> >::type,
+ typename F::template apply<
+ typename P::template apply<S, Pos>::type
+ >,
+ typename P::template apply<S, Pos>
+ >
+ {};
+
+ typedef transform_error type;
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/transform_error_message.hpp b/boost/metaparse/v1/transform_error_message.hpp
new file mode 100644
index 0000000000..7aba6c3bcb
--- /dev/null
+++ b/boost/metaparse/v1/transform_error_message.hpp
@@ -0,0 +1,49 @@
+#ifndef BOOST_METAPARSE_V1_TRANSFORM_ERROR_MESSAGE_HPP
+#define BOOST_METAPARSE_V1_TRANSFORM_ERROR_MESSAGE_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/is_error.hpp>
+#include <boost/metaparse/v1/reject.hpp>
+#include <boost/metaparse/v1/get_position.hpp>
+#include <boost/metaparse/v1/get_message.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class P, class F>
+ struct transform_error_message
+ {
+ template <class R>
+ struct rejection :
+ reject<
+ typename F::template apply<typename get_message<R>::type>::type,
+ get_position<R>
+ >
+ {};
+
+ template <class S, class Pos>
+ struct apply :
+ boost::mpl::eval_if<
+ typename is_error<typename P::template apply<S, Pos> >::type,
+ rejection<typename P::template apply<S, Pos> >,
+ typename P::template apply<S, Pos>
+ >
+ {};
+
+ typedef transform_error_message type;
+ };
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/unless_error.hpp b/boost/metaparse/v1/unless_error.hpp
new file mode 100644
index 0000000000..0578cd41b2
--- /dev/null
+++ b/boost/metaparse/v1/unless_error.hpp
@@ -0,0 +1,29 @@
+#ifndef BOOST_METAPARSE_V1_UTIL_UNLESS_ERROR_HPP
+#define BOOST_METAPARSE_V1_UTIL_UNLESS_ERROR_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/is_error.hpp>
+
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/eval_if.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ template <class T, class NotErrorCase>
+ struct unless_error :
+ boost::mpl::eval_if<typename is_error<T>::type, T, NotErrorCase>
+ {};
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/util/digit_to_int.hpp b/boost/metaparse/v1/util/digit_to_int.hpp
new file mode 100644
index 0000000000..5ec885bbd1
--- /dev/null
+++ b/boost/metaparse/v1/util/digit_to_int.hpp
@@ -0,0 +1,38 @@
+#ifndef BOOST_METAPARSE_V1_UTIL_DIGIT_TO_INT_HPP
+#define BOOST_METAPARSE_V1_UTIL_DIGIT_TO_INT_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/util/digit_to_int_c.hpp>
+
+#include <boost/mpl/vector.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace util
+ {
+ template <class D = boost::mpl::na>
+ struct digit_to_int : digit_to_int_c<D::type::value> {};
+
+ template <>
+ struct digit_to_int<boost::mpl::na>
+ {
+ typedef digit_to_int type;
+
+ template <class D = boost::mpl::na>
+ struct apply : digit_to_int<D> {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/util/digit_to_int_c.hpp b/boost/metaparse/v1/util/digit_to_int_c.hpp
new file mode 100644
index 0000000000..51cc13d915
--- /dev/null
+++ b/boost/metaparse/v1/util/digit_to_int_c.hpp
@@ -0,0 +1,40 @@
+#ifndef BOOST_METAPARSE_V1_UTIL_DIGIT_TO_INT_C_HPP
+#define BOOST_METAPARSE_V1_UTIL_DIGIT_TO_INT_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/error/digit_expected.hpp>
+
+#include <boost/mpl/int.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace util
+ {
+ template <char C>
+ struct digit_to_int_c : error::digit_expected {};
+
+ template <> struct digit_to_int_c<'0'> : boost::mpl::int_<0> {};
+ template <> struct digit_to_int_c<'1'> : boost::mpl::int_<1> {};
+ template <> struct digit_to_int_c<'2'> : boost::mpl::int_<2> {};
+ template <> struct digit_to_int_c<'3'> : boost::mpl::int_<3> {};
+ template <> struct digit_to_int_c<'4'> : boost::mpl::int_<4> {};
+ template <> struct digit_to_int_c<'5'> : boost::mpl::int_<5> {};
+ template <> struct digit_to_int_c<'6'> : boost::mpl::int_<6> {};
+ template <> struct digit_to_int_c<'7'> : boost::mpl::int_<7> {};
+ template <> struct digit_to_int_c<'8'> : boost::mpl::int_<8> {};
+ template <> struct digit_to_int_c<'9'> : boost::mpl::int_<9> {};
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/util/in_range.hpp b/boost/metaparse/v1/util/in_range.hpp
new file mode 100644
index 0000000000..a4baba073c
--- /dev/null
+++ b/boost/metaparse/v1/util/in_range.hpp
@@ -0,0 +1,75 @@
+#ifndef BOOST_METAPARSE_V1_UTIL_IN_RANGE_HPP
+#define BOOST_METAPARSE_V1_UTIL_IN_RANGE_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/mpl/less_equal.hpp>
+#include <boost/mpl/comparison.hpp>
+#include <boost/mpl/quote.hpp>
+#include <boost/mpl/bool.hpp>
+
+#include <boost/mpl/vector.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace util
+ {
+ template <
+ class LowerBound = boost::mpl::na,
+ class UpperBound = boost::mpl::na,
+ class Item = boost::mpl::na
+ >
+ struct in_range :
+ boost::mpl::bool_<
+ boost::mpl::less_equal<LowerBound, Item>::type::value
+ && boost::mpl::less_equal<Item, UpperBound>::type::value
+ >
+ {};
+
+ template <class LowerBound, class UpperBound>
+ struct in_range<LowerBound, UpperBound, boost::mpl::na>
+ {
+ typedef in_range type;
+
+ template <class Item = boost::mpl::na>
+ struct apply : in_range<LowerBound, UpperBound, Item> {};
+ };
+
+ template <class LowerBound>
+ struct in_range<LowerBound, boost::mpl::na, boost::mpl::na>
+ {
+ typedef in_range type;
+
+ template <
+ class UpperBound = boost::mpl::na,
+ class Item = boost::mpl::na
+ >
+ struct apply : in_range<LowerBound, UpperBound, Item> {};
+ };
+
+ template <>
+ struct in_range<boost::mpl::na, boost::mpl::na, boost::mpl::na>
+ {
+ typedef in_range type;
+
+ template <
+ class LowerBound = boost::mpl::na,
+ class UpperBound = boost::mpl::na,
+ class Item = boost::mpl::na
+ >
+ struct apply : in_range<LowerBound, UpperBound, Item> {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/util/in_range_c.hpp b/boost/metaparse/v1/util/in_range_c.hpp
new file mode 100644
index 0000000000..21fde89871
--- /dev/null
+++ b/boost/metaparse/v1/util/in_range_c.hpp
@@ -0,0 +1,38 @@
+#ifndef BOOST_METAPARSE_V1_UTIL_IN_RANGE_C_HPP
+#define BOOST_METAPARSE_V1_UTIL_IN_RANGE_C_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/mpl/bool.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace util
+ {
+ template <class T, T LowerBound, T UpperBound>
+ struct in_range_c
+ {
+ typedef in_range_c type;
+
+ template <class Item>
+ struct apply :
+ boost::mpl::bool_<(
+ LowerBound <= Item::type::value
+ && Item::type::value <= UpperBound
+ )>
+ {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/util/int_to_digit.hpp b/boost/metaparse/v1/util/int_to_digit.hpp
new file mode 100644
index 0000000000..0e093e9de3
--- /dev/null
+++ b/boost/metaparse/v1/util/int_to_digit.hpp
@@ -0,0 +1,38 @@
+#ifndef BOOST_METAPARSE_V1_UTIL_INT_TO_DIGIT_HPP
+#define BOOST_METAPARSE_V1_UTIL_INT_TO_DIGIT_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/metaparse/v1/util/int_to_digit_c.hpp>
+
+#include <boost/mpl/vector.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace util
+ {
+ template <class N = boost::mpl::na>
+ struct int_to_digit : int_to_digit_c<N::type::value> {};
+
+ template <>
+ struct int_to_digit<boost::mpl::na>
+ {
+ typedef int_to_digit type;
+
+ template <class N = boost::mpl::na>
+ struct apply : int_to_digit<N> {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/util/int_to_digit_c.hpp b/boost/metaparse/v1/util/int_to_digit_c.hpp
new file mode 100644
index 0000000000..2742e330b6
--- /dev/null
+++ b/boost/metaparse/v1/util/int_to_digit_c.hpp
@@ -0,0 +1,38 @@
+#ifndef BOOST_METAPARSE_V1_UTIL_INT_TO_DIGIT_C_HPP
+#define BOOST_METAPARSE_V1_UTIL_INT_TO_DIGIT_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/mpl/char.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace util
+ {
+ template <int N>
+ struct int_to_digit_c;
+
+ template <> struct int_to_digit_c<0> : boost::mpl::char_<'0'> {};
+ template <> struct int_to_digit_c<1> : boost::mpl::char_<'1'> {};
+ template <> struct int_to_digit_c<2> : boost::mpl::char_<'2'> {};
+ template <> struct int_to_digit_c<3> : boost::mpl::char_<'3'> {};
+ template <> struct int_to_digit_c<4> : boost::mpl::char_<'4'> {};
+ template <> struct int_to_digit_c<5> : boost::mpl::char_<'5'> {};
+ template <> struct int_to_digit_c<6> : boost::mpl::char_<'6'> {};
+ template <> struct int_to_digit_c<7> : boost::mpl::char_<'7'> {};
+ template <> struct int_to_digit_c<8> : boost::mpl::char_<'8'> {};
+ template <> struct int_to_digit_c<9> : boost::mpl::char_<'9'> {};
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/util/is_digit.hpp b/boost/metaparse/v1/util/is_digit.hpp
new file mode 100644
index 0000000000..ccc9b456f0
--- /dev/null
+++ b/boost/metaparse/v1/util/is_digit.hpp
@@ -0,0 +1,38 @@
+#ifndef BOOST_METAPARSE_V1_UTIL_IS_DIGIT_HPP
+#define BOOST_METAPARSE_V1_UTIL_IS_DIGIT_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/util/in_range_c.hpp>
+
+#include <boost/mpl/vector.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace util
+ {
+ template <class C = boost::mpl::na>
+ struct is_digit : in_range_c<char, '0', '9'>::apply<C> {};
+
+ template <>
+ struct is_digit<boost::mpl::na>
+ {
+ typedef is_digit type;
+
+ template <class C = boost::mpl::na>
+ struct apply : is_digit<C> {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/util/is_lcase_letter.hpp b/boost/metaparse/v1/util/is_lcase_letter.hpp
new file mode 100644
index 0000000000..9c05b48208
--- /dev/null
+++ b/boost/metaparse/v1/util/is_lcase_letter.hpp
@@ -0,0 +1,38 @@
+#ifndef BOOST_METAPARSE_V1_UTIL_IS_LCASE_LETTER_HPP
+#define BOOST_METAPARSE_V1_UTIL_IS_LCASE_LETTER_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/util/in_range_c.hpp>
+
+#include <boost/mpl/vector.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace util
+ {
+ template <class C = boost::mpl::na>
+ struct is_lcase_letter : in_range_c<char, 'a', 'z'>::apply<C> {};
+
+ template <>
+ struct is_lcase_letter<boost::mpl::na>
+ {
+ typedef is_lcase_letter type;
+
+ template <class C = boost::mpl::na>
+ struct apply : is_lcase_letter<C> {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/util/is_letter.hpp b/boost/metaparse/v1/util/is_letter.hpp
new file mode 100644
index 0000000000..a3bc3114a7
--- /dev/null
+++ b/boost/metaparse/v1/util/is_letter.hpp
@@ -0,0 +1,44 @@
+#ifndef BOOST_METAPARSE_V1_UTIL_IS_LETTER_HPP
+#define BOOST_METAPARSE_V1_UTIL_IS_LETTER_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/util/is_ucase_letter.hpp>
+#include <boost/metaparse/v1/util/is_lcase_letter.hpp>
+
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/vector.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace util
+ {
+ template <class C = boost::mpl::na>
+ struct is_letter :
+ boost::mpl::bool_<
+ is_lcase_letter<C>::type::value || is_ucase_letter<C>::type::value
+ >
+ {};
+
+ template <>
+ struct is_letter<boost::mpl::na>
+ {
+ typedef is_letter type;
+
+ template <class C = boost::mpl::na>
+ struct apply : is_letter<C> {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/util/is_ucase_letter.hpp b/boost/metaparse/v1/util/is_ucase_letter.hpp
new file mode 100644
index 0000000000..37926b6075
--- /dev/null
+++ b/boost/metaparse/v1/util/is_ucase_letter.hpp
@@ -0,0 +1,38 @@
+#ifndef BOOST_METAPARSE_V1_UTIL_IS_UCASE_LETTER_HPP
+#define BOOST_METAPARSE_V1_UTIL_IS_UCASE_LETTER_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/util/in_range_c.hpp>
+
+#include <boost/mpl/vector.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace util
+ {
+ template <class C = boost::mpl::na>
+ struct is_ucase_letter : in_range_c<char, 'A', 'Z'>::apply<C> {};
+
+ template <>
+ struct is_ucase_letter<boost::mpl::na>
+ {
+ typedef is_ucase_letter type;
+
+ template <class C = boost::mpl::na>
+ struct apply : is_ucase_letter<C> {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/util/is_whitespace.hpp b/boost/metaparse/v1/util/is_whitespace.hpp
new file mode 100644
index 0000000000..93940fd8fb
--- /dev/null
+++ b/boost/metaparse/v1/util/is_whitespace.hpp
@@ -0,0 +1,38 @@
+#ifndef BOOST_METAPARSE_V1_UTIL_IS_WHITESPACE_HPP
+#define BOOST_METAPARSE_V1_UTIL_IS_WHITESPACE_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/util/is_whitespace_c.hpp>
+
+#include <boost/mpl/vector.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace util
+ {
+ template <class C = boost::mpl::na>
+ struct is_whitespace : is_whitespace_c<C::type::value> {};
+
+ template <>
+ struct is_whitespace<boost::mpl::na>
+ {
+ typedef is_whitespace type;
+
+ template <class C = boost::mpl::na>
+ struct apply : is_whitespace<C> {};
+ };
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/v1/util/is_whitespace_c.hpp b/boost/metaparse/v1/util/is_whitespace_c.hpp
new file mode 100644
index 0000000000..b37ab7cbc6
--- /dev/null
+++ b/boost/metaparse/v1/util/is_whitespace_c.hpp
@@ -0,0 +1,32 @@
+#ifndef BOOST_METAPARSE_V1_UTIL_IS_WHITESPACE_C_HPP
+#define BOOST_METAPARSE_V1_UTIL_IS_WHITESPACE_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/mpl/bool.hpp>
+
+namespace boost
+{
+ namespace metaparse
+ {
+ namespace v1
+ {
+ namespace util
+ {
+ template <char C>
+ struct is_whitespace_c : boost::mpl::false_ {};
+
+ template <> struct is_whitespace_c<' '> : boost::mpl::true_ {};
+ template <> struct is_whitespace_c<'\r'> : boost::mpl::true_ {};
+ template <> struct is_whitespace_c<'\n'> : boost::mpl::true_ {};
+ template <> struct is_whitespace_c<'\t'> : boost::mpl::true_ {};
+ }
+ }
+ }
+}
+
+#endif
+
diff --git a/boost/metaparse/version.hpp b/boost/metaparse/version.hpp
new file mode 100644
index 0000000000..0ac171730a
--- /dev/null
+++ b/boost/metaparse/version.hpp
@@ -0,0 +1,14 @@
+#ifndef BOOST_METAPARSE_VERSION_HPP
+#define BOOST_METAPARSE_VERSION_HPP
+
+// Copyright Abel Sinkovics (abel@sinkovics.hu) 2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/predef/version_number.h>
+
+#define BOOST_METAPARSE_VERSION BOOST_VERSION_NUMBER(1, 0, 0)
+
+#endif
+
diff --git a/boost/move/adl_move_swap.hpp b/boost/move/adl_move_swap.hpp
index 2a010cda57..930320108d 100644
--- a/boost/move/adl_move_swap.hpp
+++ b/boost/move/adl_move_swap.hpp
@@ -22,9 +22,8 @@
//Based on Boost.Core's swap.
//Many thanks to Steven Watanabe, Joseph Gauterin and Niels Dekker.
-
-#include <boost/config.hpp>
#include <cstddef> //for std::size_t
+#include <boost/move/detail/workaround.hpp> //forceinline
//Try to avoid including <algorithm>, as it's quite big
#if defined(_MSC_VER) && defined(BOOST_DINKUMWARE_STDLIB)
@@ -156,7 +155,7 @@ struct and_op_not
{};
template<class T>
-void swap_proxy(T& x, T& y, typename boost::move_detail::enable_if_c<!boost::move_detail::has_move_emulation_enabled_impl<T>::value>::type* = 0)
+BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y, typename boost::move_detail::enable_if_c<!boost::move_detail::has_move_emulation_enabled_impl<T>::value>::type* = 0)
{
//use std::swap if argument dependent lookup fails
//Use using directive ("using namespace xxx;") instead as some older compilers
@@ -166,14 +165,14 @@ void swap_proxy(T& x, T& y, typename boost::move_detail::enable_if_c<!boost::mov
}
template<class T>
-void swap_proxy(T& x, T& y
+BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y
, typename boost::move_detail::enable_if< and_op_not_impl<boost::move_detail::has_move_emulation_enabled_impl<T>
, boost_move_member_swap::has_member_swap<T> >
>::type* = 0)
{ T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t); }
template<class T>
-void swap_proxy(T& x, T& y
+BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y
, typename boost::move_detail::enable_if< and_op_impl< boost::move_detail::has_move_emulation_enabled_impl<T>
, boost_move_member_swap::has_member_swap<T> >
>::type* = 0)
@@ -186,7 +185,7 @@ void swap_proxy(T& x, T& y
namespace boost_move_adl_swap{
template<class T>
-void swap_proxy(T& x, T& y)
+BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y)
{
using std::swap;
swap(x, y);
@@ -223,11 +222,45 @@ namespace boost{
//! - Otherwise a move-based swap is called, equivalent to:
//! <code>T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t);</code>.
template<class T>
-void adl_move_swap(T& x, T& y)
+BOOST_MOVE_FORCEINLINE void adl_move_swap(T& x, T& y)
{
::boost_move_adl_swap::swap_proxy(x, y);
}
+//! Exchanges elements between range [first1, last1) and another range starting at first2
+//! using boost::adl_move_swap.
+//!
+//! Parameters:
+//! first1, last1 - the first range of elements to swap
+//! first2 - beginning of the second range of elements to swap
+//!
+//! Type requirements:
+//! - ForwardIt1, ForwardIt2 must meet the requirements of ForwardIterator.
+//! - The types of dereferenced ForwardIt1 and ForwardIt2 must meet the
+//! requirements of Swappable
+//!
+//! Return value: Iterator to the element past the last element exchanged in the range
+//! beginning with first2.
+template<class ForwardIt1, class ForwardIt2>
+ForwardIt2 adl_move_swap_ranges(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2)
+{
+ while (first1 != last1) {
+ ::boost::adl_move_swap(*first1, *first2);
+ ++first1;
+ ++first2;
+ }
+ return first2;
+}
+
+template<class BidirIt1, class BidirIt2>
+BidirIt2 adl_move_swap_ranges_backward(BidirIt1 first1, BidirIt1 last1, BidirIt2 last2)
+{
+ while (first1 != last1) {
+ ::boost::adl_move_swap(*(--last1), *(--last2));
+ }
+ return last2;
+}
+
} //namespace boost{
#endif //#ifndef BOOST_MOVE_ADL_MOVE_SWAP_HPP
diff --git a/boost/move/algo/adaptive_merge.hpp b/boost/move/algo/adaptive_merge.hpp
new file mode 100644
index 0000000000..ef20651bbf
--- /dev/null
+++ b/boost/move/algo/adaptive_merge.hpp
@@ -0,0 +1,67 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_MOVE_ADAPTIVE_MERGE_HPP
+#define BOOST_MOVE_ADAPTIVE_MERGE_HPP
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/algo/detail/adaptive_sort_merge.hpp>
+
+namespace boost {
+namespace movelib {
+
+//! <b>Effects</b>: Merges two consecutive sorted ranges [first, middle) and [middle, last)
+//! into one sorted range [first, last) according to the given comparison function comp.
+//! The algorithm is stable (if there are equivalent elements in the original two ranges,
+//! the elements from the first range (preserving their original order) precede the elements
+//! from the second range (preserving their original order).
+//!
+//! <b>Requires</b>:
+//! - RandIt must meet the requirements of ValueSwappable and RandomAccessIterator.
+//! - The type of dereferenced RandIt must meet the requirements of MoveAssignable and MoveConstructible.
+//!
+//! <b>Parameters</b>:
+//! - first: the beginning of the first sorted range.
+//! - middle: the end of the first sorted range and the beginning of the second
+//! - last: the end of the second sorted range
+//! - comp: comparison function object which returns true if the first argument is is ordered before the second.
+//! - uninitialized, uninitialized_len: raw storage starting on "uninitialized", able to hold "uninitialized_len"
+//! elements of type iterator_traits<RandIt>::value_type. Maximum performance is achieved when uninitialized_len
+//! is min(std::distance(first, middle), std::distance(middle, last)).
+//!
+//! <b>Throws</b>: If comp throws or the move constructor, move assignment or swap of the type
+//! of dereferenced RandIt throws.
+//!
+//! <b>Complexity</b>: Always K x O(N) comparisons and move assignments/constructors/swaps.
+//! Constant factor for comparisons and data movement is minimized when uninitialized_len
+//! is min(std::distance(first, middle), std::distance(middle, last)).
+//! Pretty good enough performance is achieved when uninitialized_len is
+//! ceil(sqrt(std::distance(first, last)))*2.
+//!
+//! <b>Caution</b>: Experimental implementation, not production-ready.
+template<class RandIt, class Compare>
+void adaptive_merge( RandIt first, RandIt middle, RandIt last, Compare comp
+ , typename iterator_traits<RandIt>::value_type* uninitialized = 0
+ , std::size_t uninitialized_len = 0)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+
+ ::boost::movelib::detail_adaptive::adaptive_xbuf<value_type> xbuf(uninitialized, uninitialized_len);
+ ::boost::movelib::detail_adaptive::adaptive_merge_impl(first, size_type(middle - first), size_type(last - middle), comp, xbuf);
+}
+
+} //namespace movelib {
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#define BOOST_MOVE_ADAPTIVE_MERGE_HPP
diff --git a/boost/move/algo/adaptive_sort.hpp b/boost/move/algo/adaptive_sort.hpp
new file mode 100644
index 0000000000..6b5586e587
--- /dev/null
+++ b/boost/move/algo/adaptive_sort.hpp
@@ -0,0 +1,63 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_MOVE_ADAPTIVE_SORT_HPP
+#define BOOST_MOVE_ADAPTIVE_SORT_HPP
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/algo/detail/adaptive_sort_merge.hpp>
+
+namespace boost {
+namespace movelib {
+
+//! <b>Effects</b>: Sorts the elements in the range [first, last) in ascending order according
+//! to comparison functor "comp". The sort is stable (order of equal elements
+//! is guaranteed to be preserved). Performance is improved if additional raw storage is
+//! provided.
+//!
+//! <b>Requires</b>:
+//! - RandIt must meet the requirements of ValueSwappable and RandomAccessIterator.
+//! - The type of dereferenced RandIt must meet the requirements of MoveAssignable and MoveConstructible.
+//!
+//! <b>Parameters</b>:
+//! - first, last: the range of elements to sort
+//! - comp: comparison function object which returns true if the first argument is is ordered before the second.
+//! - uninitialized, uninitialized_len: raw storage starting on "uninitialized", able to hold "uninitialized_len"
+//! elements of type iterator_traits<RandIt>::value_type. Maximum performance is achieved when uninitialized_len
+//! is ceil(std::distance(first, last)/2).
+//!
+//! <b>Throws</b>: If comp throws or the move constructor, move assignment or swap of the type
+//! of dereferenced RandIt throws.
+//!
+//! <b>Complexity</b>: Always K x O(Nxlog(N)) comparisons and move assignments/constructors/swaps.
+//! Comparisons are close to minimum even with no additional memory. Constant factor for data movement is minimized
+//! when uninitialized_len is ceil(std::distance(first, last)/2). Pretty good enough performance is achieved when
+//! ceil(sqrt(std::distance(first, last)))*2.
+//!
+//! <b>Caution</b>: Experimental implementation, not production-ready.
+template<class RandIt, class Compare>
+void adaptive_sort( RandIt first, RandIt last, Compare comp
+ , typename iterator_traits<RandIt>::value_type* uninitialized = 0
+ , std::size_t uninitialized_len = 0)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+
+ ::boost::movelib::detail_adaptive::adaptive_xbuf<value_type> xbuf(uninitialized, uninitialized_len);
+ ::boost::movelib::detail_adaptive::adaptive_sort_impl(first, size_type(last - first), comp, xbuf);
+}
+
+} //namespace movelib {
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#define BOOST_MOVE_ADAPTIVE_SORT_HPP
diff --git a/boost/move/algo/detail/adaptive_sort_merge.hpp b/boost/move/algo/detail/adaptive_sort_merge.hpp
new file mode 100644
index 0000000000..46dba187c5
--- /dev/null
+++ b/boost/move/algo/detail/adaptive_sort_merge.hpp
@@ -0,0 +1,2284 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// Stable sorting that works in O(N*log(N)) worst time
+// and uses O(1) extra memory
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// The main idea of the adaptive_sort algorithm was developed by Andrey Astrelin
+// and explained in the article from the russian collaborative blog
+// Habrahabr (http://habrahabr.ru/post/205290/). The algorithm is based on
+// ideas from B-C. Huang and M. A. Langston explained in their article
+// "Fast Stable Merging and Sorting in Constant Extra Space (1989-1992)"
+// (http://comjnl.oxfordjournals.org/content/35/6/643.full.pdf).
+//
+// This implementation by Ion Gaztanaga uses previous ideas with additional changes:
+//
+// - Use of GCD-based rotation.
+// - Non power of two buffer-sizes.
+// - Tries to find sqrt(len)*2 unique keys, so that the merge sort
+// phase can form up to sqrt(len)*4 segments if enough keys are found.
+// - The merge-sort phase can take advantage of external memory to
+// save some additional combination steps.
+// - Optimized comparisons when selection-sorting blocks as A and B blocks
+// are already sorted.
+// - The combination phase is performed alternating merge to left and merge
+// to right phases minimizing swaps due to internal buffer repositioning.
+// - When merging blocks special optimizations are made to avoid moving some
+// elements twice.
+//
+// The adaptive_merge algorithm was developed by Ion Gaztanaga reusing some parts
+// from the sorting algorithm and implementing a block merge algorithm
+// without moving elements left or right, which is used when external memory
+// is available.
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_MOVE_ADAPTIVE_SORT_MERGE_HPP
+#define BOOST_MOVE_ADAPTIVE_SORT_MERGE_HPP
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/algo/move.hpp>
+#include <boost/move/algo/detail/merge.hpp>
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/move/algo/detail/insertion_sort.hpp>
+#include <boost/move/algo/detail/merge_sort.hpp>
+#include <boost/move/algo/detail/merge.hpp>
+#include <boost/assert.hpp>
+#include <boost/cstdint.hpp>
+
+#ifdef BOOST_MOVE_ADAPTIVE_SORT_STATS
+ #define BOOST_MOVE_ADAPTIVE_SORT_PRINT(STR, L) \
+ print_stats(STR, L)\
+ //
+#else
+ #define BOOST_MOVE_ADAPTIVE_SORT_PRINT(STR, L)
+#endif
+
+namespace boost {
+namespace movelib {
+
+namespace detail_adaptive {
+
+static const std::size_t AdaptiveSortInsertionSortThreshold = 16;
+//static const std::size_t AdaptiveSortInsertionSortThreshold = 4;
+BOOST_STATIC_ASSERT((AdaptiveSortInsertionSortThreshold&(AdaptiveSortInsertionSortThreshold-1)) == 0);
+
+#if defined BOOST_HAS_INTPTR_T
+ typedef ::boost::uintptr_t uintptr_t;
+#else
+ typedef std::size_t uintptr_t;
+#endif
+
+template<class T>
+const T &min_value(const T &a, const T &b)
+{
+ return a < b ? a : b;
+}
+
+template<class T>
+const T &max_value(const T &a, const T &b)
+{
+ return a > b ? a : b;
+}
+
+template<class T>
+class adaptive_xbuf
+{
+ adaptive_xbuf(const adaptive_xbuf &);
+ adaptive_xbuf & operator=(const adaptive_xbuf &);
+
+ public:
+ typedef T* iterator;
+
+ adaptive_xbuf()
+ : m_ptr(0), m_size(0), m_capacity(0)
+ {}
+
+ adaptive_xbuf(T *raw_memory, std::size_t capacity)
+ : m_ptr(raw_memory), m_size(0), m_capacity(capacity)
+ {}
+
+ template<class RandIt>
+ void move_assign(RandIt first, std::size_t n)
+ {
+ if(n <= m_size){
+ boost::move(first, first+n, m_ptr);
+ std::size_t size = m_size;
+ while(size-- != n){
+ m_ptr[size].~T();
+ }
+ m_size = n;
+ }
+ else{
+ T *result = boost::move(first, first+m_size, m_ptr);
+ boost::uninitialized_move(first+m_size, first+n, result);
+ m_size = n;
+ }
+ }
+
+ template<class RandIt>
+ void push_back(RandIt first, std::size_t n)
+ {
+ BOOST_ASSERT(m_capacity - m_size >= n);
+ boost::uninitialized_move(first, first+n, m_ptr+m_size);
+ m_size += n;
+ }
+
+ template<class RandIt>
+ iterator add(RandIt it)
+ {
+ BOOST_ASSERT(m_size < m_capacity);
+ T * p_ret = m_ptr + m_size;
+ ::new(p_ret) T(::boost::move(*it));
+ ++m_size;
+ return p_ret;
+ }
+
+ template<class RandIt>
+ void insert(iterator pos, RandIt it)
+ {
+ if(pos == (m_ptr + m_size)){
+ this->add(it);
+ }
+ else{
+ this->add(m_ptr+m_size-1);
+ //m_size updated
+ boost::move_backward(pos, m_ptr+m_size-2, m_ptr+m_size-1);
+ *pos = boost::move(*it);
+ }
+ }
+
+ void set_size(std::size_t size)
+ {
+ m_size = size;
+ }
+
+ template<class U>
+ bool supports_aligned_trailing(std::size_t size, std::size_t trail_count) const
+ {
+ if(this->data()){
+ uintptr_t u_addr_sz = uintptr_t(this->data()+size);
+ uintptr_t u_addr_cp = uintptr_t(this->data()+this->capacity());
+ u_addr_sz = ((u_addr_sz + sizeof(U)-1)/sizeof(U))*sizeof(U);
+
+ return (u_addr_cp >= u_addr_sz) && ((u_addr_cp - u_addr_sz)/sizeof(U) >= trail_count);
+ }
+ return false;
+ }
+
+ template<class U>
+ U *aligned_trailing() const
+ {
+ return this->aligned_trailing<U>(this->size());
+ }
+
+ template<class U>
+ U *aligned_trailing(std::size_t pos) const
+ {
+ uintptr_t u_addr = uintptr_t(this->data()+pos);
+ u_addr = ((u_addr + sizeof(U)-1)/sizeof(U))*sizeof(U);
+ return (U*)u_addr;
+ }
+
+ ~adaptive_xbuf()
+ {
+ this->clear();
+ }
+
+ std::size_t capacity() const
+ { return m_capacity; }
+
+ iterator data() const
+ { return m_ptr; }
+
+ iterator end() const
+ { return m_ptr+m_size; }
+
+ std::size_t size() const
+ { return m_size; }
+
+ bool empty() const
+ { return !m_size; }
+
+ void clear()
+ {
+ std::size_t size = m_size;
+ while(size--){
+ m_ptr[size].~T();
+ }
+ m_size = 0u;
+ }
+
+ private:
+ T *m_ptr;
+ std::size_t m_size;
+ std::size_t m_capacity;
+};
+
+template<class Iterator, class Op>
+class range_xbuf
+{
+ range_xbuf(const range_xbuf &);
+ range_xbuf & operator=(const range_xbuf &);
+
+ public:
+ typedef typename iterator_traits<Iterator>::size_type size_type;
+ typedef Iterator iterator;
+
+ range_xbuf(Iterator first, Iterator last)
+ : m_first(first), m_last(first), m_cap(last)
+ {}
+
+ template<class RandIt>
+ void move_assign(RandIt first, std::size_t n)
+ {
+ BOOST_ASSERT(size_type(n) <= size_type(m_cap-m_first));
+ m_last = Op()(forward_t(), first, first+n, m_first);
+ }
+
+ ~range_xbuf()
+ {}
+
+ std::size_t capacity() const
+ { return m_cap-m_first; }
+
+ Iterator data() const
+ { return m_first; }
+
+ Iterator end() const
+ { return m_last; }
+
+ std::size_t size() const
+ { return m_last-m_first; }
+
+ bool empty() const
+ { return m_first == m_last; }
+
+ void clear()
+ {
+ m_last = m_first;
+ }
+
+ template<class RandIt>
+ iterator add(RandIt it)
+ {
+ Iterator pos(m_last);
+ *pos = boost::move(*it);
+ ++m_last;
+ return pos;
+ }
+
+ void set_size(std::size_t size)
+ {
+ m_last = m_first;
+ m_last += size;
+ }
+
+ private:
+ Iterator const m_first;
+ Iterator m_last;
+ Iterator const m_cap;
+};
+
+template<class RandIt, class Buf>
+bool three_way_init( RandIt first1, RandIt last1, Buf &buf
+ , typename Buf::iterator &buf_first, typename Buf::iterator &buf_last, move_op)
+{
+ buf.move_assign(first1, last1-first1);
+ buf_first = buf.data();
+ buf_last = buf.end();
+ return true;
+}
+
+template<class RandIt, class Buf>
+bool three_way_init( RandIt first, RandIt last, Buf &buf
+ , typename Buf::iterator &buf_first, typename Buf::iterator &buf_last, swap_op)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ buf.clear();
+ buf_first = buf.data();
+ buf_last = buf_first + size_type(last-first);
+ return false;
+}
+
+template<class T, class Buf>
+void three_way_move(T &a, T &b, Buf &buf, move_op)
+{
+ buf.add(&b);
+ b = boost::move(a);
+}
+
+template<class T, class Buf>
+void three_way_move(T &a, T &b, Buf &buf, swap_op)
+{
+ T tmp(boost::move(*buf.end()));
+ buf.add(&b);
+ b = boost::move(a);
+ a = boost::move(tmp);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// PARTIAL MERGE BUF
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+template<class Buf, class RandIt, class Compare, class Op>
+RandIt op_partial_merge_with_buf_impl
+ ( RandIt first1, RandIt const last1, RandIt first2, RandIt last2
+ , Buf &buf, typename Buf::iterator &buf_first1_in_out, typename Buf::iterator &buf_last1_in_out
+ , Compare comp, Op op
+ )
+{
+ typedef typename Buf::iterator buf_iterator;
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+
+ BOOST_ASSERT(first1 != last1);
+ BOOST_ASSERT(first2 != last2);
+ buf_iterator buf_first1 = buf_first1_in_out;
+ buf_iterator buf_last1 = buf_last1_in_out;
+
+ if(buf_first1 == buf_last1){
+ //Skip any element that does not need to be moved
+ while(!comp(*last1, *first1)){
+ ++first1;
+ if(first1 == last1){
+ return first1;
+ }
+ }
+
+ //If initialization is successful, move to buffer while merging
+ //Three way moves need less moves when op is swap_op so use it
+ //when merging elements from range2 to the destination occupied by range1
+ if(!three_way_init(first1, last1, buf, buf_first1, buf_last1, op)){
+ three_way_move(*first2, *first1, buf, op);
+ for(++first1, ++first2; first1 != last1; ++first1){
+ value_type &v = comp(*first2, *buf_first1) ? *first2++ : *buf_first1++;
+ three_way_move(v, *first1, buf, op);
+ }
+ }
+ }
+
+ //Now merge from buffer
+ if(first2 != last2)
+ while(1){
+ if(comp(*first2, *buf_first1)) {
+ op(first2++, first1++);
+ if(first2 == last2)
+ break;
+ }
+ else{
+ op(buf_first1++, first1++);
+ if(buf_first1 == buf_last1)
+ break;
+ }
+ }
+
+ buf_first1_in_out = buf_first1;
+ buf_last1_in_out = buf_last1;
+ return first1;
+}
+
+template<class RandIt, class Buf, class Compare, class Op>
+RandIt op_partial_merge_with_buf
+ ( RandIt first1, RandIt const last1, RandIt first2, RandIt last2
+ , Buf &buf
+ , typename Buf::iterator &buf_first1_in_out
+ , typename Buf::iterator &buf_last1_in_out
+ , Compare comp
+ , Op op
+ , bool is_stable)
+{
+ return is_stable
+ ? op_partial_merge_with_buf_impl
+ (first1, last1, first2, last2, buf, buf_first1_in_out, buf_last1_in_out, comp, op)
+ : op_partial_merge_with_buf_impl
+ (first1, last1, first2, last2, buf, buf_first1_in_out, buf_last1_in_out, antistable<Compare>(comp), op)
+ ;
+}
+
+// key_first - sequence of keys, in same order as blocks. key_comp(key, midkey) means stream A
+// first - first element to merge.
+// first[-l_block, 0) - buffer
+// l_block - length of regular blocks. Blocks are stable sorted by 1st elements and key-coded
+// l_irreg1 is the irregular block to be merged before n_bef_irreg2 blocks (can be 0)
+// n_bef_irreg2/n_aft_irreg2 are regular blocks
+// l_irreg2 is a irregular block, that is to be merged after n_bef_irreg2 blocks and before n_aft_irreg2 blocks
+// If l_irreg2==0 then n_aft_irreg2==0 (no irregular blocks).
+template<class RandItKeys, class KeyCompare, class RandIt, class Compare, class Op, class Buf>
+void op_merge_blocks_with_buf
+ ( RandItKeys key_first
+ , const typename iterator_traits<RandItKeys>::value_type &midkey
+ , KeyCompare key_comp
+ , RandIt const first
+ , typename iterator_traits<RandIt>::size_type const l_block
+ , typename iterator_traits<RandIt>::size_type const l_irreg1
+ , typename iterator_traits<RandIt>::size_type const n_bef_irreg2
+ , typename iterator_traits<RandIt>::size_type const n_aft_irreg2
+ , typename iterator_traits<RandIt>::size_type const l_irreg2
+ , Compare comp
+ , Op op
+ , Buf & xbuf)
+{
+ if(n_bef_irreg2 == 0){
+ RandIt const last_reg(first+l_irreg1+n_aft_irreg2*l_block);
+ op_buffered_merge(first, last_reg, last_reg+l_irreg2, comp, op, xbuf);
+ }
+ else {
+ typedef typename Buf::iterator buf_iterator;
+ buf_iterator buffer = xbuf.data();
+ buf_iterator buffer_end = buffer;
+ RandIt first1 = first;
+ RandIt last1 = l_irreg1 ? first1 + l_irreg1 : first1 + l_block;
+ RandIt first2 = last1;
+ RandItKeys const key_end (key_first+n_bef_irreg2);
+
+ for( bool is_range1_A = l_irreg1 ? true : key_comp(*key_first, midkey), skip_first_it = l_irreg1 != 0
+ ; key_first != key_end; ){
+ if(!skip_first_it){
+ ++key_first;
+ }
+ skip_first_it = false;
+ bool const last_it = key_first == key_end;
+ //If the trailing block is empty, we'll make it equal to the previous if empty
+ bool const is_range2_A = last_it ? (!l_irreg2 && is_range1_A) : key_comp(*key_first, midkey);
+
+ if(is_range1_A == is_range2_A){
+ if(buffer != buffer_end){
+ first1 = op(forward_t(), buffer, buffer_end, first1);
+ BOOST_ASSERT(first1 == first2);
+ buffer_end = buffer;
+ }
+ first1 = first2;
+ if(last_it){
+ xbuf.clear();
+ last1 = first2+l_block*n_aft_irreg2;
+ op_buffered_merge(first1, last1, last1+l_irreg2, comp, op, xbuf);
+ break;
+ }
+ else{
+ last1 = first2 + l_block;
+ }
+ first2 += l_block;
+ }
+ else {
+ BOOST_ASSERT(!last_it || (l_irreg2 || n_aft_irreg2));
+ if(last_it){
+ RandIt res = op(forward_t(), buffer, buffer_end, first1);
+ BOOST_ASSERT(buffer == buffer_end || res == last1); (void)res;
+ last1 += l_block*n_aft_irreg2;
+ xbuf.clear();
+ op_buffered_merge(first1, last1, last1+l_irreg2, comp, op, xbuf);
+ break;
+ }
+ else{
+ RandIt const last2 = first2 + l_block;
+ first1 = op_partial_merge_with_buf(first1, last1, first2, last2, xbuf, buffer, buffer_end, comp, op, is_range1_A);
+ if(buffer == buffer_end){
+ is_range1_A = is_range2_A;
+ }
+ last1 = last2;
+ first2 = last1;
+ BOOST_ASSERT((buffer == buffer_end) || (buffer_end-buffer) == (last1-first1));
+ }
+ }
+ }
+ }
+}
+
+template<class RandItKeys, class KeyCompare, class RandIt, class Compare, class Buf>
+void merge_blocks_with_buf
+ ( RandItKeys key_first
+ , const typename iterator_traits<RandItKeys>::value_type &midkey
+ , KeyCompare key_comp
+ , RandIt const first
+ , typename iterator_traits<RandIt>::size_type const l_block
+ , typename iterator_traits<RandIt>::size_type const l_irreg1
+ , typename iterator_traits<RandIt>::size_type const n_bef_irreg2
+ , typename iterator_traits<RandIt>::size_type const n_aft_irreg2
+ , typename iterator_traits<RandIt>::size_type const l_irreg2
+ , Compare comp
+ , Buf & xbuf
+ , bool const xbuf_used)
+{
+ if(xbuf_used){
+ op_merge_blocks_with_buf
+ (key_first, midkey, key_comp, first, l_block, l_irreg1, n_bef_irreg2, n_aft_irreg2, l_irreg2, comp, move_op(), xbuf);
+ }
+ else{
+ op_merge_blocks_with_buf
+ (key_first, midkey, key_comp, first, l_block, l_irreg1, n_bef_irreg2, n_aft_irreg2, l_irreg2, comp, swap_op(), xbuf);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// PARTIAL MERGE LEFT
+//
+///////////////////////////////////////////////////////////////////////////////
+
+template<class RandIt, class Compare, class Op>
+RandIt op_partial_merge_left_middle_buffer_impl
+ (RandIt first1, RandIt const last1, RandIt const first2
+ , const typename iterator_traits<RandIt>::value_type &next_key, Compare comp
+ , Op op)
+{
+ while(first1 != last1 && !comp(next_key, *first1)){
+ ++first1;
+ }
+ //Even if we copy backward, no overlapping occurs so use forward copy
+ //that can be faster specially with trivial types
+ RandIt const new_first1 = first2 - (last1 - first1);
+ BOOST_ASSERT(last1 <= new_first1);
+ op(forward_t(), first1, last1, new_first1);
+ return new_first1;
+}
+
+template<class RandIt, class Compare, class Op>
+RandIt op_partial_merge_left_middle_buffer
+ ( RandIt first1, RandIt const last1, RandIt const first2
+ , const typename iterator_traits<RandIt>::value_type &next_key, Compare comp, Op op, bool is_stable)
+{
+ return is_stable ? op_partial_merge_left_middle_buffer_impl(first1, last1, first2, next_key, comp, op)
+ : op_partial_merge_left_middle_buffer_impl(first1, last1, first2, next_key, antistable<Compare>(comp), op);
+}
+
+// Partially merges two ordered ranges. Partially means that elements are merged
+// until one of two ranges is exhausted (M elements from ranges 1 y 2).
+// [buf_first, ...) -> buffer that can be overwritten
+// [first1, last1) merge [last1,last2) -> [buf_first, buf_first+M)
+// Note: distance(buf_first, first1) >= distance(last1, last2), so no overlapping occurs.
+template<class RandIt, class Compare, class Op>
+RandIt op_partial_merge_left_impl
+ ( RandIt buf_first, RandIt first1, RandIt const last1, RandIt const last2, Compare comp, Op op)
+{
+ RandIt first2 = last1;
+ while(first1 != last1){
+ if(first2 == last2){
+ return first1;
+ }
+ if(comp(*first2, *first1)) {
+ op(first2, buf_first);
+ ++first2;
+ }
+ else{
+ op(first1, buf_first);
+ ++first1;
+ }
+ ++buf_first;
+ }
+ return first2;
+}
+
+
+template<class RandIt, class Compare, class Op>
+RandIt op_partial_merge_left
+ ( RandIt buf_first, RandIt first1, RandIt const last1, RandIt const last2, Compare comp, Op op, bool is_stable)
+{
+ return is_stable ? op_partial_merge_left_impl(buf_first, first1, last1, last2, comp, op)
+ : op_partial_merge_left_impl(buf_first, first1, last1, last2, antistable<Compare>(comp), op);
+}
+
+template<class RandIt>
+bool three_way_side_init( RandIt first1, RandIt last1, RandIt buf_first1, move_op)
+{
+ boost::move(first1, last1, buf_first1);
+ return true;
+}
+
+template<class RandIt>
+bool three_way_side_init( RandIt, RandIt, RandIt, swap_op)
+{
+ return false;
+}
+
+template<class T>
+void three_way_side_move(T &a, T &b, T&c, move_op)
+{
+ c = boost::move(b);
+ b = boost::move(a);
+}
+
+template<class T>
+void three_way_side_move(T &a, T &b, T &c, swap_op)
+{
+ T tmp(boost::move(c));
+ c = boost::move(b);
+ b = boost::move(a);
+ a = boost::move(tmp);
+}
+
+
+// Partially merges two ordered ranges. Partially means that elements are merged
+// until one of two ranges is exhausted (M elements from ranges 1 y 2).
+// [buf_first, ...) -> buffer that can be overwritten
+// [first1, last1) merge [last1,last2) -> [buf_first, buf_first+M)
+// Note: distance(buf_first, first1) >= distance(last1, last2), so no overlapping occurs.
+template<class RandIt, class Compare, class Op>
+RandIt op_partial_merge_left_smart_impl
+ ( RandIt first1, RandIt last1, RandIt first2, RandIt const last2, Compare comp, Op op)
+{
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+
+ RandIt dest;
+ if(last1 != first2){
+ BOOST_ASSERT((first2-last1)==(last2-first2));
+ //Skip any element that does not need to be moved
+ while(!comp(*first2, *first1)){
+ ++first1;
+ if(first1 == last1)
+ return first2;
+ }
+
+ RandIt buf_first1 = first2 - (last1-first1);
+
+ //If initialization is successful, move to buffer while merging
+ //Three way moves need less moves when op is swap_op so use it
+ //when merging elements from range2 to the destination occupied by range1
+ if(!three_way_side_init(first1, last1, buf_first1, op)){
+ RandIt buf_last1 = buf_first1;
+ three_way_side_move(*first2, *first1, *buf_last1++, op);
+
+ RandIt const orig_first2 = first2;(void)(orig_first2);
+ for(++first1, ++first2; first1 != last1; ++first1, ++buf_last1){
+ value_type &v = comp(*first2, *buf_first1) ? *first2++ : *buf_first1++;
+ three_way_side_move(v, *first1, *buf_last1, op);
+ }
+ BOOST_ASSERT(buf_last1 == orig_first2);
+ last1 = buf_last1;
+ }
+ else{
+ last1 = first2;
+ }
+ dest = first1;
+ first1 = buf_first1;
+ BOOST_ASSERT((first1-dest) == (last2-first2));
+ }
+ else{
+ dest = first1-(last2-first2);
+ }
+
+ BOOST_ASSERT(0 != (last1-first1));
+ if(first2 != last2)
+ while(1){
+ if(comp(*first2, *first1)) {
+ op(first2++, dest++);
+ if(first2 == last2){
+ return first1;
+ }
+ }
+ else{
+ op(first1++, dest++);
+ if(first1 == last1){
+ return first2;
+ }
+ }
+ }
+ return first1;
+}
+
+
+
+template<class RandIt, class Compare, class Op>
+RandIt op_partial_merge_left_smart
+ (RandIt first1, RandIt const last1, RandIt first2, RandIt const last2, Compare comp, Op op, bool is_stable)
+{
+ return is_stable ? op_partial_merge_left_smart_impl(first1, last1, first2, last2, comp, op)
+ : op_partial_merge_left_smart_impl(first1, last1, first2, last2, antistable<Compare>(comp), op);
+}
+
+
+// first - first element to merge.
+// first[-l_block, 0) - buffer
+// l_block - length of regular blocks. Blocks are stable sorted by 1st elements and key-coded
+// key_first - sequence of keys, in same order as blocks. key<midkey means stream A
+// n_bef_irreg2/n_aft_irreg2 are regular blocks
+// l_irreg2 is a irregular block, that is to be merged after n_bef_irreg2 blocks and before n_aft_irreg2 blocks
+// If l_irreg2==0 then n_aft_irreg2==0 (no irregular blocks).
+template<class RandItKeys, class KeyCompare, class RandIt, class Compare, class Op>
+void op_merge_blocks_left
+ ( RandItKeys key_first
+ , const typename iterator_traits<RandItKeys>::value_type &midkey
+ , KeyCompare key_comp
+ , RandIt const first
+ , typename iterator_traits<RandIt>::size_type const l_block
+ , typename iterator_traits<RandIt>::size_type const l_irreg1
+ , typename iterator_traits<RandIt>::size_type const n_bef_irreg2
+ , typename iterator_traits<RandIt>::size_type const n_aft_irreg2
+ , typename iterator_traits<RandIt>::size_type const l_irreg2
+ , Compare comp, Op op)
+{
+ if(n_bef_irreg2 == 0){
+ RandIt const last_reg(first+l_irreg1+n_aft_irreg2*l_block);
+ op_merge_left(first-l_block, first, last_reg, last_reg+l_irreg2, comp, op);
+ }
+ else {
+ RandIt buffer = first - l_block;
+ RandIt first1 = first;
+ RandIt last1 = l_irreg1 ? first1 + l_irreg1 : first1 + l_block;
+ RandIt first2 = last1;
+ RandItKeys const key_end (key_first+n_bef_irreg2);
+ bool skip_first_it = l_irreg1 != 0;
+ for( bool is_range1_A = l_irreg1 ? true : key_comp(*key_first, midkey)
+ ; key_first != key_end; first2 += l_block){
+ if(!skip_first_it){
+ ++key_first;
+ }
+ skip_first_it = false;
+ bool const last_it = key_first == key_end;
+ //If the trailing block is empty, we'll make it equal to the previous if empty
+ bool const is_range2_A = last_it ? (!l_irreg2 && is_range1_A) : key_comp(*key_first, midkey);
+ bool const is_buffer_middle = last1 == buffer;
+
+ if(is_range1_A == is_range2_A){
+ //If range1 is buffered, write it to its final position
+ if(!is_buffer_middle){
+ buffer = op(forward_t(), first1, last1, buffer);
+ }
+
+ first1 = first2;
+ if(last_it){
+ last1 = first2+l_block*n_aft_irreg2;
+ op_merge_left(buffer, first1, last1, last1+l_irreg2, comp, op);
+ break;
+ }
+ else{
+ last1 = first2 + l_block;
+ }
+ }
+ else {
+ BOOST_ASSERT(!last_it || (l_irreg2 || n_aft_irreg2));
+ if(last_it){
+ if(is_buffer_middle){
+ //See comment below marked with (*)
+ first1 = op_partial_merge_left_middle_buffer(first1, last1, first2, first2[l_block*n_aft_irreg2], comp, op, is_range1_A);
+ last1 = first2;
+ buffer = first1 - l_block;
+ }
+ last1 += l_block*n_aft_irreg2;
+ op_merge_left(buffer, first1, last1, last1+l_irreg2, comp, op);
+ break;
+ }
+ else{
+ RandIt const last2 = first2 + l_block;
+ first1 = op_partial_merge_left_smart(first1, last1, first2, last2, comp, op, is_range1_A);
+
+ if(first1 < first2){ //is_buffer_middle == true for the next iteration
+ last1 = first2;
+ buffer = last1;
+ }
+ else{ //is_buffer_middle == false for the next iteration
+ is_range1_A = is_range2_A;
+ buffer = first1 - l_block;
+ last1 = last2;
+ }
+ }
+ }
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// PARTIAL MERGE RIGHT
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+template<class RandIt, class Compare, class Op>
+RandIt op_partial_merge_right_middle_buffer_impl
+ ( RandIt const last1, RandIt const first2, RandIt last2, Compare comp, Op op)
+{
+ while(first2 != last2 && !comp(last2[-1], last1[-1])){
+ --last2;
+ }
+ return op(forward_t(), first2, last2, last1);
+}
+
+template<class RandIt, class Compare, class Op>
+RandIt op_partial_merge_right_middle_buffer
+ ( RandIt const last1, RandIt first2, RandIt const last2
+ , Compare comp, Op op, bool is_stable)
+{
+ return is_stable ? op_partial_merge_right_middle_buffer_impl(last1, first2, last2, comp, op)
+ : op_partial_merge_right_middle_buffer_impl(last1, first2, last2, antistable<Compare>(comp), op);
+}
+
+// Partially merges two ordered ranges. Partially means that elements are merged
+// until one of two ranges is exhausted (M elements from ranges 1 y 2).
+// [last2, buf_last) -> buffer that can be overwritten
+// [first1, last1) merge [last1,last2) -> [buf_last - M, buf_last)
+// Note: distance(last2, buf_last) >= distance(first1, last1), so no overlapping occurs.
+template<class RandIt, class Compare, class Op>
+RandIt op_partial_merge_right_impl
+ ( RandIt const first1, RandIt last1, RandIt last2, RandIt buf_last, Compare comp, Op op)
+{
+ RandIt const first2 = last1;
+ while(first2 != last2){
+ if(last1 == first1){
+ return last2;
+ }
+ --last2;
+ --last1;
+ --buf_last;
+ if(comp(*last2, *last1)){
+ op(last1, buf_last);
+ ++last2;
+ }
+ else{
+ op(last2, buf_last);
+ ++last1;
+ }
+ }
+ return last1;
+}
+
+template<class RandIt, class Compare, class Op>
+RandIt op_partial_merge_right
+ ( RandIt first1, RandIt const last1, RandIt const last2, RandIt buf_last, Compare comp, Op op, bool is_stable)
+{
+ return is_stable ? op_partial_merge_right_impl(first1, last1, last2, buf_last, comp, op)
+ : op_partial_merge_right_impl(first1, last1, last2, buf_last, antistable<Compare>(comp), op);
+}
+
+
+// first - first element to merge.
+// last iterator is (first+l_block*(n_bef_irreg2+n_aft_irreg2)+l_irreg2)
+// [last, last+l_block) - buffer
+// l_block - length of regular blocks. Blocks are stable sorted by 1st elements and key-coded
+// key_first - sequence of keys, in same order as blocks. key<midkey means stream A
+// n_bef_irreg2/n_aft_irreg2 are regular blocks
+// l_irreg2 is a irregular block, that is to be merged after n_bef_irreg2 blocks and before n_aft_irreg2 blocks
+// If l_irreg2==0 then n_aft_irreg2==0 (no irregular blocks).
+template<class RandItKeys, class KeyCompare, class RandIt, class Compare, class Op>
+void op_merge_blocks_right
+ ( RandItKeys const key_first
+ , const typename iterator_traits<RandItKeys>::value_type &midkey
+ , KeyCompare key_comp
+ , RandIt const first
+ , typename iterator_traits<RandIt>::size_type const l_block
+ , typename iterator_traits<RandIt>::size_type const n_bef_irreg2
+ , typename iterator_traits<RandIt>::size_type const n_aft_irreg2
+ , typename iterator_traits<RandIt>::size_type const l_irreg2
+ , Compare comp, Op op)
+{
+ RandIt last1 = first + (n_bef_irreg2+n_aft_irreg2)*l_block;
+ RandIt first1 = last1-l_block;
+ RandIt first2 = last1;
+ RandIt last2 = first2 + l_irreg2;
+ RandIt buffer_end = last2 + l_block;
+ RandItKeys key_end (key_first+(n_bef_irreg2+n_aft_irreg2));
+
+ for(bool is_range2_A = false; key_first != key_end; last1 = first1, first1 -= l_block){
+ --key_end;
+ bool const is_range1_A = key_comp(*key_end, midkey);
+ bool const is_buffer_middle = first2 == buffer_end;
+
+ if(is_range1_A == is_range2_A){
+ if(!is_buffer_middle){
+ buffer_end = op(backward_t(), first2, last2, buffer_end);
+ }
+ //else //op forward already done on previous op_partial_merge_right
+
+ first2 = first1;
+ last2 = last1;
+ }
+ else {
+ if(is_buffer_middle){
+ //A previous op_partial_merge_right has right range2 elements after the buffer.
+ //In order to merge it with the next block, move them to the start of the buffer so that
+ //buffer is placed to the right. Move only the minimum elements as some range1 elements
+ //won't be moved in the merge.
+ last2 = op_partial_merge_right_middle_buffer(last1, first2, last2, comp, op, !is_range2_A);
+ first2 = last1;
+ buffer_end = last2 + l_block;
+ }
+
+ //op_partial_merge_right merges two ranges, but stops moving elements
+ //once one range is emptied to avoid moving data twice in the next iteration
+ last2 = op_partial_merge_right(first1, last1, last2, buffer_end, comp, op, !is_range2_A);
+ if(last2 > first2){ //is_buffer_middle == true for the next iteration
+ buffer_end = first2;
+ }
+ else{ //is_buffer_middle == false for the next iteration
+ is_range2_A = is_range1_A;
+ buffer_end = last2 + l_block;
+ first2 = first1;
+ }
+ }
+ }
+
+ if(first2 != buffer_end){
+ op(backward_t(), first2, last2, buffer_end);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// PARTIAL MERGE BUFFERLESS
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// [first1, last1) merge [last1,last2) -> [first1,last2)
+template<class RandIt, class Compare>
+RandIt partial_merge_bufferless_impl
+ (RandIt first1, RandIt last1, RandIt const last2, bool *const pis_range1_A, Compare comp)
+{
+ if(last1 == last2){
+ return first1;
+ }
+ bool const is_range1_A = *pis_range1_A;
+ if(first1 != last1 && comp(*last1, last1[-1])){
+ do{
+ RandIt const old_last1 = last1;
+ last1 = lower_bound(last1, last2, *first1, comp);
+ first1 = rotate_gcd(first1, old_last1, last1);//old_last1 == last1 supported
+ if(last1 == last2){
+ return first1;
+ }
+ do{
+ ++first1;
+ } while(last1 != first1 && !comp(*last1, *first1) );
+ } while(first1 != last1);
+ }
+ *pis_range1_A = !is_range1_A;
+ return last1;
+}
+
+// [first1, last1) merge [last1,last2) -> [first1,last2)
+template<class RandIt, class Compare>
+RandIt partial_merge_bufferless
+ (RandIt first1, RandIt last1, RandIt const last2, bool *const pis_range1_A, Compare comp)
+{
+ return *pis_range1_A ? partial_merge_bufferless_impl(first1, last1, last2, pis_range1_A, comp)
+ : partial_merge_bufferless_impl(first1, last1, last2, pis_range1_A, antistable<Compare>(comp));
+}
+
+
+
+// l_block - length of regular blocks. First nblocks are stable sorted by 1st elements and key-coded
+// keys - sequence of keys, in same order as blocks. key<midkey means stream A
+// n_aft_irreg2 are regular blocks from stream A. l_irreg2 is length of last (irregular) block from stream B, that should go before n_aft_irreg2 blocks.
+// l_irreg2=0 requires n_aft_irreg2=0 (no irregular blocks). l_irreg2>0, n_aft_irreg2=0 is possible.
+template<class RandItKeys, class KeyCompare, class RandIt, class Compare>
+void merge_blocks_bufferless
+ ( RandItKeys key_first
+ , const typename iterator_traits<RandItKeys>::value_type &midkey
+ , KeyCompare key_comp
+ , RandIt first
+ , typename iterator_traits<RandIt>::size_type const l_block
+ , typename iterator_traits<RandIt>::size_type const l_irreg1
+ , typename iterator_traits<RandIt>::size_type const n_bef_irreg2
+ , typename iterator_traits<RandIt>::size_type const n_aft_irreg2
+ , typename iterator_traits<RandIt>::size_type const l_irreg2
+ , Compare comp)
+{
+ if(n_bef_irreg2 == 0){
+ RandIt const last_reg(first+l_irreg1+n_aft_irreg2*l_block);
+ merge_bufferless(first, last_reg, last_reg+l_irreg2, comp);
+ }
+ else{
+ RandIt first1 = first;
+ RandIt last1 = l_irreg1 ? first + l_irreg1: first + l_block;
+ RandItKeys const key_end (key_first+n_bef_irreg2);
+ bool is_range1_A = l_irreg1 ? true : key_comp(*key_first++, midkey);
+
+ for( ; key_first != key_end; ++key_first){
+ bool is_range2_A = key_comp(*key_first, midkey);
+ if(is_range1_A == is_range2_A){
+ first1 = last1;
+ }
+ else{
+ first1 = partial_merge_bufferless(first1, last1, last1 + l_block, &is_range1_A, comp);
+ }
+ last1 += l_block;
+ }
+
+ if(l_irreg2){
+ if(!is_range1_A){
+ first1 = last1;
+ }
+ last1 += l_block*n_aft_irreg2;
+ merge_bufferless(first1, last1, last1+l_irreg2, comp);
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// BUFFERED MERGE
+//
+///////////////////////////////////////////////////////////////////////////////
+template<class RandIt, class Compare, class Op, class Buf>
+void op_buffered_merge
+ ( RandIt first, RandIt const middle, RandIt last
+ , Compare comp, Op op
+ , Buf &xbuf)
+{
+ if(first != middle && middle != last && comp(*middle, middle[-1])){
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type const len1 = size_type(middle-first);
+ size_type const len2 = size_type(last-middle);
+ if(len1 <= len2){
+ first = upper_bound(first, middle, *middle, comp);
+ xbuf.move_assign(first, size_type(middle-first));
+ op_merge_with_right_placed
+ (xbuf.data(), xbuf.end(), first, middle, last, comp, op);
+ }
+ else{
+ last = lower_bound(middle, last, middle[-1], comp);
+ xbuf.move_assign(middle, size_type(last-middle));
+ op_merge_with_left_placed
+ (first, middle, last, xbuf.data(), xbuf.end(), comp, op);
+ }
+ }
+}
+
+template<class RandIt, class Compare>
+void buffered_merge
+ ( RandIt first, RandIt const middle, RandIt last
+ , Compare comp
+ , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> &xbuf)
+{
+ op_buffered_merge(first, middle, last, comp, move_op(), xbuf);
+}
+
+// Complexity: 2*distance(first, last)+max_collected^2/2
+//
+// Tries to collect at most n_keys unique elements from [first, last),
+// in the begining of the range, and ordered according to comp
+//
+// Returns the number of collected keys
+template<class RandIt, class Compare>
+typename iterator_traits<RandIt>::size_type
+ collect_unique
+ ( RandIt const first, RandIt const last
+ , typename iterator_traits<RandIt>::size_type const max_collected, Compare comp
+ , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+ size_type h = 0;
+ if(max_collected){
+ ++h; // first key is always here
+ RandIt h0 = first;
+ RandIt u = first; ++u;
+ RandIt search_end = u;
+
+ if(xbuf.capacity() >= max_collected){
+ value_type *const ph0 = xbuf.add(first);
+ while(u != last && h < max_collected){
+ value_type * const r = lower_bound(ph0, xbuf.end(), *u, comp);
+ //If key not found add it to [h, h+h0)
+ if(r == xbuf.end() || comp(*u, *r) ){
+ RandIt const new_h0 = boost::move(search_end, u, h0);
+ search_end = u;
+ ++search_end;
+ ++h;
+ xbuf.insert(r, u);
+ h0 = new_h0;
+ }
+ ++u;
+ }
+ boost::move_backward(first, h0, h0+h);
+ boost::move(xbuf.data(), xbuf.end(), first);
+ }
+ else{
+ while(u != last && h < max_collected){
+ RandIt const r = lower_bound(h0, search_end, *u, comp);
+ //If key not found add it to [h, h+h0)
+ if(r == search_end || comp(*u, *r) ){
+ RandIt const new_h0 = rotate_gcd(h0, search_end, u);
+ search_end = u;
+ ++search_end;
+ ++h;
+ rotate_gcd(r+(new_h0-h0), u, search_end);
+ h0 = new_h0;
+ }
+ ++u;
+ }
+ rotate_gcd(first, h0, h0+h);
+ }
+ }
+ return h;
+}
+
+template<class Unsigned>
+Unsigned floor_sqrt(Unsigned const n)
+{
+ Unsigned x = n;
+ Unsigned y = x/2 + (x&1);
+ while (y < x){
+ x = y;
+ y = (x + n / x)/2;
+ }
+ return x;
+}
+
+template<class Unsigned>
+Unsigned ceil_sqrt(Unsigned const n)
+{
+ Unsigned r = floor_sqrt(n);
+ return r + Unsigned((n%r) != 0);
+}
+
+template<class Unsigned>
+Unsigned floor_merge_multiple(Unsigned const n, Unsigned &base, Unsigned &pow)
+{
+ Unsigned s = n;
+ Unsigned p = 0;
+ while(s > AdaptiveSortInsertionSortThreshold){
+ s /= 2;
+ ++p;
+ }
+ base = s;
+ pow = p;
+ return s << p;
+}
+
+template<class Unsigned>
+Unsigned ceil_merge_multiple(Unsigned const n, Unsigned &base, Unsigned &pow)
+{
+ Unsigned fm = floor_merge_multiple(n, base, pow);
+
+ if(fm != n){
+ if(base < AdaptiveSortInsertionSortThreshold){
+ ++base;
+ }
+ else{
+ base = AdaptiveSortInsertionSortThreshold/2 + 1;
+ ++pow;
+ }
+ }
+ return base << pow;
+}
+
+template<class Unsigned>
+Unsigned ceil_sqrt_multiple(Unsigned const n, Unsigned *pbase = 0)
+{
+ Unsigned const r = ceil_sqrt(n);
+ Unsigned pow = 0;
+ Unsigned base = 0;
+ Unsigned const res = ceil_merge_multiple(r, base, pow);
+ if(pbase) *pbase = base;
+ return res;
+}
+
+template<class Unsigned>
+Unsigned ceil_sqrt_pow2(Unsigned const n)
+{
+ Unsigned r=1;
+ Unsigned exp = 0;
+ Unsigned pow = 1u;
+ while(pow != 0 && pow < n){
+ r*=2;
+ ++exp;
+ pow = r << exp;
+ }
+ return r;
+}
+
+struct less
+{
+ template<class T>
+ bool operator()(const T &l, const T &r)
+ { return l < r; }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// MERGE BLOCKS
+//
+///////////////////////////////////////////////////////////////////////////////
+
+template<class RandIt, class Compare>
+void slow_stable_sort
+ ( RandIt const first, RandIt const last, Compare comp)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type L = size_type(last - first);
+ { //Use insertion sort to merge first elements
+ size_type m = 0;
+ while((L - m) > size_type(AdaptiveSortInsertionSortThreshold)){
+ insertion_sort(first+m, first+m+size_type(AdaptiveSortInsertionSortThreshold), comp);
+ m += AdaptiveSortInsertionSortThreshold;
+ }
+ insertion_sort(first+m, last, comp);
+ }
+
+ size_type h = AdaptiveSortInsertionSortThreshold;
+ for(bool do_merge = L > h; do_merge; h*=2){
+ do_merge = (L - h) > h;
+ size_type p0 = 0;
+ if(do_merge){
+ size_type const h_2 = 2*h;
+ while((L-p0) > h_2){
+ merge_bufferless(first+p0, first+p0+h, first+p0+h_2, comp);
+ p0 += h_2;
+ }
+ }
+ if((L-p0) > h){
+ merge_bufferless(first+p0, first+p0+h, last, comp);
+ }
+ }
+}
+
+//Returns new l_block and updates use_buf
+template<class Unsigned>
+Unsigned lblock_for_combine
+ (Unsigned const l_block, Unsigned const n_keys, Unsigned const l_data, bool &use_buf)
+{
+ BOOST_ASSERT(l_data > 1);
+
+ //We need to guarantee lblock >= l_merged/(n_keys/2) keys for the combination.
+ //We have at least 4 keys guaranteed (which are the minimum to merge 2 ranges)
+ //If l_block != 0, then n_keys is already enough to merge all blocks in all
+ //phases as we've found all needed keys for that buffer and length before.
+ //If l_block == 0 then see if half keys can be used as buffer and the rest
+ //as keys guaranteeing that n_keys >= (2*l_merged)/lblock =
+ if(!l_block){
+ //If l_block == 0 then n_keys is power of two
+ //(guaranteed by build_params(...))
+ BOOST_ASSERT(n_keys >= 4);
+ //BOOST_ASSERT(0 == (n_keys &(n_keys-1)));
+
+ //See if half keys are at least 4 and if half keys fulfill
+ Unsigned const new_buf = n_keys/2;
+ Unsigned const new_keys = n_keys-new_buf;
+ use_buf = new_keys >= 4 && new_keys >= l_data/new_buf;
+ if(use_buf){
+ return new_buf;
+ }
+ else{
+ return l_data/n_keys;
+ }
+ }
+ else{
+ use_buf = true;
+ return l_block;
+ }
+}
+
+
+//Although "cycle" sort is known to have the minimum number of writes to target
+//selection sort is more appropriate here as we want to minimize swaps.
+template<class RandItKeys, class KeyCompare, class RandIt, class Compare>
+void selection_sort_blocks
+ ( RandItKeys keys
+ , typename iterator_traits<RandIt>::size_type &midkey_idx //inout
+ , KeyCompare key_comp
+ , RandIt const first_block
+ , typename iterator_traits<RandIt>::size_type const l_block
+ , typename iterator_traits<RandIt>::size_type const n_blocks
+ , Compare comp
+ , bool use_first_element)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type ;
+ size_type const back_midkey_idx = midkey_idx;
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+
+ //Nothing to sort if 0 or 1 blocks or all belong to the first ordered half
+ if(n_blocks < 2 || back_midkey_idx >= n_blocks){
+ return;
+ }
+ //One-past the position of the first untouched element of the second half
+ size_type high_watermark = back_midkey_idx+1;
+ BOOST_ASSERT(high_watermark <= n_blocks);
+
+ //Sort by first element if left merging, last element otherwise
+ size_type const reg_off = use_first_element ? 0u: l_block-1;
+
+ for(size_type block=0; block < n_blocks-1; ++block){
+ size_type min_block = block;
+ //Since we are searching for the minimum value in two sorted halves:
+ //Optimization 1: If block belongs to first half, don't waste time comparing elements of the first half.
+ //Optimization 2: It is enough to compare until the first untouched element of the second half.
+ high_watermark = size_type(max_value(block+2, high_watermark));
+ BOOST_ASSERT(high_watermark <= n_blocks);
+ for(size_type next_block = size_type(max_value(block+1, back_midkey_idx)); next_block < high_watermark; ++next_block){
+ const value_type &v = first_block[next_block*l_block+reg_off];
+ const value_type &min = first_block[min_block*l_block+reg_off];
+ if( comp(v, min) || (!comp(min, v) && key_comp(keys[next_block], keys[min_block])) ){
+ min_block=next_block;
+ }
+ }
+
+ if(min_block != block){
+ BOOST_ASSERT(block >= back_midkey_idx || min_block >= back_midkey_idx);
+ BOOST_ASSERT(min_block < high_watermark);
+ //Update high watermark if n_blocks is not surpassed
+ high_watermark += size_type((min_block + 1) != n_blocks && (min_block + 1) == high_watermark);
+ BOOST_ASSERT(high_watermark <= n_blocks);
+ boost::adl_move_swap_ranges(first_block+block*l_block, first_block+(block+1)*l_block, first_block+min_block*l_block);
+ boost::adl_move_swap(keys[block], keys[min_block]);
+ if(midkey_idx == block)
+ midkey_idx = min_block;
+ else if(midkey_idx == min_block)
+ midkey_idx = block;
+ }
+ }
+}
+
+template<class RandIt, class Compare>
+void stable_sort( RandIt first, RandIt last, Compare comp
+ , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type const len = size_type(last - first);
+ size_type const half_len = len/2 + (len&1);
+ if(std::size_t(xbuf.capacity() - xbuf.size()) >= half_len) {
+ merge_sort(first, last, comp, xbuf.data()+xbuf.size());
+ }
+ else{
+ slow_stable_sort(first, last, comp);
+ }
+}
+
+template<class RandIt, class Comp>
+void initialize_keys( RandIt first, RandIt last
+ , Comp comp
+ , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf)
+{
+ stable_sort(first, last, comp, xbuf);
+}
+
+template<class RandIt, class U>
+void initialize_keys( RandIt first, RandIt last
+ , less
+ , U &)
+{
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+ std::size_t count = std::size_t(last - first);
+ for(std::size_t i = 0; i != count; ++i){
+ *first = value_type(i);
+ ++first;
+ }
+}
+
+template<class RandItKeys, class KeyCompare, class RandIt, class Compare>
+void combine_params
+ ( RandItKeys const keys
+ , KeyCompare key_comp
+ , RandIt const first
+ , typename iterator_traits<RandIt>::size_type l_combined
+ , typename iterator_traits<RandIt>::size_type const l_prev_merged
+ , typename iterator_traits<RandIt>::size_type const l_block
+ , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
+ , Compare comp
+ //Output
+ , typename iterator_traits<RandIt>::size_type &midkey_idx
+ , typename iterator_traits<RandIt>::size_type &l_irreg1
+ , typename iterator_traits<RandIt>::size_type &n_bef_irreg2
+ , typename iterator_traits<RandIt>::size_type &n_aft_irreg2
+ , typename iterator_traits<RandIt>::size_type &l_irreg2
+ , bool is_merge_left)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+
+ l_irreg1 = l_prev_merged%l_block;
+ l_irreg2 = (l_combined-l_irreg1)%l_block;
+ BOOST_ASSERT(((l_combined-l_irreg1-l_irreg2)%l_block) == 0);
+ size_type const n_reg_block = (l_combined-l_irreg1-l_irreg2)/l_block;
+ midkey_idx = l_prev_merged/l_block;
+ BOOST_ASSERT(n_reg_block>=midkey_idx);
+ initialize_keys(keys, keys+n_reg_block+(midkey_idx==n_reg_block), key_comp, xbuf);
+ selection_sort_blocks(keys, midkey_idx, key_comp, first+l_irreg1, l_block, n_reg_block, comp, is_merge_left);
+
+ n_aft_irreg2 = 0;
+ if(l_irreg2!=0){
+ size_type const reg_off = is_merge_left ? 0u: l_block-1;
+ size_type const irreg_off = is_merge_left ? 0u: l_irreg2-1;
+ RandIt prev_block_first = first + l_combined - l_irreg2;
+ const value_type &incomplete_block_first = prev_block_first[irreg_off];
+ while(n_aft_irreg2 != n_reg_block &&
+ comp(incomplete_block_first, (prev_block_first-= l_block)[reg_off]) ){
+ ++n_aft_irreg2;
+ }
+ }
+ n_bef_irreg2 = n_reg_block-n_aft_irreg2;
+}
+
+// first - first element to merge.
+// first[-l_block, 0) - buffer (if use_buf == true)
+// l_block - length of regular blocks. First nblocks are stable sorted by 1st elements and key-coded
+// keys - sequence of keys, in same order as blocks. key<midkey means stream A
+// n_bef_irreg2/n_aft_irreg2 are regular blocks
+// l_irreg2 is a irregular block, that is to be combined after n_bef_irreg2 blocks and before n_aft_irreg2 blocks
+// If l_irreg2==0 then n_aft_irreg2==0 (no irregular blocks).
+template<class RandItKeys, class KeyCompare, class RandIt, class Compare>
+void merge_blocks_left
+ ( RandItKeys const key_first
+ , const typename iterator_traits<RandItKeys>::value_type &midkey
+ , KeyCompare key_comp
+ , RandIt const first
+ , typename iterator_traits<RandIt>::size_type const l_block
+ , typename iterator_traits<RandIt>::size_type const l_irreg1
+ , typename iterator_traits<RandIt>::size_type const n_bef_irreg2
+ , typename iterator_traits<RandIt>::size_type const n_aft_irreg2
+ , typename iterator_traits<RandIt>::size_type const l_irreg2
+ , Compare comp
+ , bool const xbuf_used)
+{
+ if(xbuf_used){
+ op_merge_blocks_left
+ (key_first, midkey, key_comp, first, l_block, l_irreg1, n_bef_irreg2, n_aft_irreg2, l_irreg2, comp, move_op());
+ }
+ else{
+ op_merge_blocks_left
+ (key_first, midkey, key_comp, first, l_block, l_irreg1, n_bef_irreg2, n_aft_irreg2, l_irreg2, comp, swap_op());
+ }
+}
+
+
+// first - first element to merge.
+// [first+l_block*(n_bef_irreg2+n_aft_irreg2)+l_irreg2, first+l_block*(n_bef_irreg2+n_aft_irreg2+1)+l_irreg2) - buffer
+// l_block - length of regular blocks. First nblocks are stable sorted by 1st elements and key-coded
+// keys - sequence of keys, in same order as blocks. key<midkey means stream A
+// n_bef_irreg2/n_aft_irreg2 are regular blocks
+// l_irreg2 is a irregular block, that is to be combined after n_bef_irreg2 blocks and before n_aft_irreg2 blocks
+// If l_irreg2==0 then n_aft_irreg2==0 (no irregular blocks).
+template<class RandItKeys, class KeyCompare, class RandIt, class Compare>
+void merge_blocks_right
+ ( RandItKeys const key_first
+ , const typename iterator_traits<RandItKeys>::value_type &midkey
+ , KeyCompare key_comp
+ , RandIt const first
+ , typename iterator_traits<RandIt>::size_type const l_block
+ , typename iterator_traits<RandIt>::size_type const n_bef_irreg2
+ , typename iterator_traits<RandIt>::size_type const n_aft_irreg2
+ , typename iterator_traits<RandIt>::size_type const l_irreg2
+ , Compare comp
+ , bool const xbuf_used)
+{
+ if(xbuf_used){
+ op_merge_blocks_right
+ (key_first, midkey, key_comp, first, l_block, n_bef_irreg2, n_aft_irreg2, l_irreg2, comp, move_op());
+ }
+ else{
+ op_merge_blocks_right
+ (key_first, midkey, key_comp, first, l_block, n_bef_irreg2, n_aft_irreg2, l_irreg2, comp, swap_op());
+ }
+}
+
+
+template<class RandIt>
+void move_data_backward( RandIt cur_pos
+ , typename iterator_traits<RandIt>::size_type const l_data
+ , RandIt new_pos
+ , bool const xbuf_used)
+{
+ //Move buffer to the total combination right
+ if(xbuf_used){
+ boost::move_backward(cur_pos, cur_pos+l_data, new_pos+l_data);
+ }
+ else{
+ boost::adl_move_swap_ranges_backward(cur_pos, cur_pos+l_data, new_pos+l_data);
+ //Rotate does less moves but it seems slower due to cache issues
+ //rotate_gcd(first-l_block, first+len-l_block, first+len);
+ }
+}
+
+template<class RandIt>
+void move_data_forward( RandIt cur_pos
+ , typename iterator_traits<RandIt>::size_type const l_data
+ , RandIt new_pos
+ , bool const xbuf_used)
+{
+ //Move buffer to the total combination right
+ if(xbuf_used){
+ boost::move(cur_pos, cur_pos+l_data, new_pos);
+ }
+ else{
+ boost::adl_move_swap_ranges(cur_pos, cur_pos+l_data, new_pos);
+ //Rotate does less moves but it seems slower due to cache issues
+ //rotate_gcd(first-l_block, first+len-l_block, first+len);
+ }
+}
+
+template <class Unsigned>
+Unsigned calculate_total_combined(Unsigned const len, Unsigned const l_prev_merged, Unsigned *pl_irreg_combined = 0)
+{
+ typedef Unsigned size_type;
+
+ size_type const l_combined = 2*l_prev_merged;
+ size_type l_irreg_combined = len%l_combined;
+ size_type l_total_combined = len;
+ if(l_irreg_combined <= l_prev_merged){
+ l_total_combined -= l_irreg_combined;
+ l_irreg_combined = 0;
+ }
+ if(pl_irreg_combined)
+ *pl_irreg_combined = l_irreg_combined;
+ return l_total_combined;
+}
+
+// keys are on the left of first:
+// If use_buf: [first - l_block - n_keys, first - l_block).
+// Otherwise: [first - n_keys, first).
+// Buffer (if use_buf) is also on the left of first [first - l_block, first).
+// Blocks of length l_prev_merged combined. We'll combine them in pairs
+// l_prev_merged and n_keys are powers of 2. (2*l_prev_merged/l_block) keys are guaranteed
+// Returns the number of combined elements (some trailing elements might be left uncombined)
+template<class RandItKeys, class KeyCompare, class RandIt, class Compare>
+void combine_blocks
+ ( RandItKeys const keys
+ , KeyCompare key_comp
+ , RandIt const first
+ , typename iterator_traits<RandIt>::size_type const len
+ , typename iterator_traits<RandIt>::size_type const l_prev_merged
+ , typename iterator_traits<RandIt>::size_type const l_block
+ , bool const use_buf
+ , bool const xbuf_used
+ , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
+ , Compare comp
+ , bool merge_left)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+
+ size_type const l_combined = 2*l_prev_merged;
+ size_type l_irreg_combined = 0;
+ size_type const l_total_combined = calculate_total_combined(len, l_prev_merged, &l_irreg_combined);
+ size_type const n_reg_combined = len/l_combined;
+ RandIt combined_first = first;
+
+ (void)l_total_combined;
+ BOOST_ASSERT(l_total_combined <= len);
+
+ size_type n_bef_irreg2, n_aft_irreg2, midkey_idx, l_irreg1, l_irreg2;
+ 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_combined) {
+ bool const is_last = combined_i==n_reg_combined;
+ combine_params( keys, key_comp, combined_first, is_last ? l_irreg_combined : l_combined
+ , l_prev_merged, l_block, xbuf, comp
+ , midkey_idx, l_irreg1, n_bef_irreg2, n_aft_irreg2, l_irreg2, true); //Outputs
+ //BOOST_MOVE_ADAPTIVE_SORT_PRINT(" After combine_params: ", len + l_block);
+ BOOST_ASSERT(!l_irreg1);
+ if(use_buf){
+ merge_blocks_left
+ (keys, keys[midkey_idx], key_comp, combined_first, l_block, 0u, n_bef_irreg2, n_aft_irreg2, l_irreg2, comp, xbuf_used);
+ }
+ else{
+ merge_blocks_bufferless
+ (keys, keys[midkey_idx], key_comp, combined_first, l_block, 0u, n_bef_irreg2, n_aft_irreg2, l_irreg2, comp);
+ }
+ //BOOST_MOVE_ADAPTIVE_SORT_PRINT(" After merge_blocks_l: ", len + l_block);
+ }
+ else{
+ combined_first += l_combined*(max_i-1);
+ for( size_type combined_i = max_i; combined_i--; combined_first -= l_combined) {
+ bool const is_last = combined_i==n_reg_combined;
+ combine_params( keys, key_comp, combined_first, is_last ? l_irreg_combined : l_combined
+ , l_prev_merged, l_block, xbuf, comp
+ , midkey_idx, l_irreg1, n_bef_irreg2, n_aft_irreg2, l_irreg2, false); //Outputs
+ BOOST_ASSERT(!l_irreg1);
+ //BOOST_MOVE_ADAPTIVE_SORT_PRINT(" After combine_params: ", len + l_block);
+ merge_blocks_right
+ (keys, keys[midkey_idx], key_comp, combined_first, l_block, n_bef_irreg2, n_aft_irreg2, l_irreg2, comp, xbuf_used);
+ //BOOST_MOVE_ADAPTIVE_SORT_PRINT(" After merge_blocks_r: ", len + l_block);
+ }
+ }
+}
+
+
+template<class RandIt, class Compare>
+typename iterator_traits<RandIt>::size_type
+ buffered_merge_blocks
+ ( RandIt const first, RandIt const last
+ , typename iterator_traits<RandIt>::size_type const input_combined_size
+ , Compare comp
+ , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> &xbuf)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type combined_size = input_combined_size;
+
+ for( size_type const elements_in_blocks = size_type(last - first)
+ ; elements_in_blocks > combined_size && size_type(xbuf.capacity()) >= combined_size
+ ; combined_size *=2){
+ RandIt merge_point = first;
+ while(size_type(last - merge_point) > 2*combined_size) {
+ RandIt const second_half = merge_point+combined_size;
+ RandIt const next_merge_point = second_half+combined_size;
+ buffered_merge(merge_point, second_half, next_merge_point, comp, xbuf);
+ merge_point = next_merge_point;
+ }
+ if(size_type(last-merge_point) > combined_size){
+ buffered_merge(merge_point, merge_point+combined_size, last, comp, xbuf);
+ }
+ }
+ return combined_size;
+}
+
+template<class RandIt, class Compare, class Op>
+typename iterator_traits<RandIt>::size_type
+ op_insertion_sort_step_left
+ ( RandIt const first
+ , typename iterator_traits<RandIt>::size_type const length
+ , typename iterator_traits<RandIt>::size_type const step
+ , Compare comp, Op op)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type const s = min_value<size_type>(step, AdaptiveSortInsertionSortThreshold);
+ size_type m = 0;
+
+ while((length - m) > s){
+ insertion_sort_op(first+m, first+m+s, first+m-s, comp, op);
+ m += s;
+ }
+ insertion_sort_op(first+m, first+length, first+m-s, comp, op);
+ return s;
+}
+
+template<class RandIt, class Compare>
+typename iterator_traits<RandIt>::size_type
+ insertion_sort_step
+ ( RandIt const first
+ , typename iterator_traits<RandIt>::size_type const length
+ , typename iterator_traits<RandIt>::size_type const step
+ , Compare comp)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type const s = min_value<size_type>(step, AdaptiveSortInsertionSortThreshold);
+ size_type m = 0;
+
+ while((length - m) > s){
+ insertion_sort(first+m, first+m+s, comp);
+ m += s;
+ }
+ insertion_sort(first+m, first+length, comp);
+ return s;
+}
+
+template<class RandIt, class Compare, class Op>
+typename iterator_traits<RandIt>::size_type
+ op_merge_left_step
+ ( RandIt first_block
+ , typename iterator_traits<RandIt>::size_type const elements_in_blocks
+ , typename iterator_traits<RandIt>::size_type l_merged
+ , typename iterator_traits<RandIt>::size_type const l_build_buf
+ , typename iterator_traits<RandIt>::size_type l_left_space
+ , Compare comp
+ , Op op)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ for(; l_merged < l_build_buf && l_left_space >= l_merged; l_merged*=2){
+ size_type p0=0;
+ RandIt pos = first_block;
+ while((elements_in_blocks - p0) > 2*l_merged) {
+ op_merge_left(pos-l_merged, pos, pos+l_merged, pos+2*l_merged, comp, op);
+ p0 += 2*l_merged;
+ pos = first_block+p0;
+ }
+ if((elements_in_blocks-p0) > l_merged) {
+ op_merge_left(pos-l_merged, pos, pos+l_merged, first_block+elements_in_blocks, comp, op);
+ }
+ else {
+ op(forward_t(), pos, first_block+elements_in_blocks, pos-l_merged);
+ }
+ first_block -= l_merged;
+ l_left_space -= l_merged;
+ }
+ return l_merged;
+}
+
+template<class RandIt, class Compare, class Op>
+void op_merge_right_step
+ ( RandIt first_block
+ , typename iterator_traits<RandIt>::size_type const elements_in_blocks
+ , typename iterator_traits<RandIt>::size_type const l_build_buf
+ , Compare comp
+ , Op op)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type restk = elements_in_blocks%(2*l_build_buf);
+ size_type p = elements_in_blocks - restk;
+ BOOST_ASSERT(0 == (p%(2*l_build_buf)));
+
+ if(restk <= l_build_buf){
+ op(backward_t(),first_block+p, first_block+p+restk, first_block+p+restk+l_build_buf);
+ }
+ else{
+ op_merge_right(first_block+p, first_block+p+l_build_buf, first_block+p+restk, first_block+p+restk+l_build_buf, comp, op);
+ }
+ while(p>0){
+ p -= 2*l_build_buf;
+ op_merge_right(first_block+p, first_block+p+l_build_buf, first_block+p+2*l_build_buf, first_block+p+3*l_build_buf, comp, op);
+ }
+}
+
+
+// build blocks of length 2*l_build_buf. l_build_buf is power of two
+// input: [0, l_build_buf) elements are buffer, rest unsorted elements
+// output: [0, l_build_buf) elements are buffer, blocks 2*l_build_buf and last subblock sorted
+//
+// First elements are merged from right to left until elements start
+// at first. All old elements [first, first + l_build_buf) are placed at the end
+// [first+len-l_build_buf, first+len). To achieve this:
+// - If we have external memory to merge, we save elements from the buffer
+// so that a non-swapping merge is used. Buffer elements are restored
+// at the end of the buffer from the external memory.
+//
+// - When the external memory is not available or it is insufficient
+// for a merge operation, left swap merging is used.
+//
+// Once elements are merged left to right in blocks of l_build_buf, then a single left
+// to right merge step is performed to achieve merged blocks of size 2K.
+// If external memory is available, usual merge is used, swap merging otherwise.
+//
+// As a last step, if auxiliary memory is available in-place merge is performed.
+// until all is merged or auxiliary memory is not large enough.
+template<class RandIt, class Compare>
+typename iterator_traits<RandIt>::size_type
+ build_blocks
+ ( RandIt const first
+ , typename iterator_traits<RandIt>::size_type const len
+ , typename iterator_traits<RandIt>::size_type const l_base
+ , typename iterator_traits<RandIt>::size_type const l_build_buf
+ , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
+ , Compare comp)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ BOOST_ASSERT(l_build_buf <= len);
+ BOOST_ASSERT(0 == ((l_build_buf / l_base)&(l_build_buf/l_base-1)));
+
+ //Place the start pointer after the buffer
+ RandIt first_block = first + l_build_buf;
+ size_type const elements_in_blocks = len - l_build_buf;
+
+ //////////////////////////////////
+ // Start of merge to left step
+ //////////////////////////////////
+ size_type l_merged = 0u;
+
+// if(xbuf.capacity()>=2*l_build_buf){
+ if(!l_build_buf){
+ l_merged = insertion_sort_step(first_block, elements_in_blocks, l_base, comp);
+ //2*l_build_buf already merged, now try to merge further
+ //using classic in-place mergesort if enough auxiliary memory is available
+ return buffered_merge_blocks
+ (first_block, first_block + elements_in_blocks, l_merged, comp, xbuf);
+ }
+ else{
+ //If there is no enough buffer for the insertion sort step, just avoid the external buffer
+ size_type kbuf = min_value<size_type>(l_build_buf, size_type(xbuf.capacity()));
+ kbuf = kbuf < l_base ? 0 : kbuf;
+
+ if(kbuf){
+ //Backup internal buffer values in external buffer so they can be overwritten
+ xbuf.move_assign(first+l_build_buf-kbuf, kbuf);
+ l_merged = op_insertion_sort_step_left(first_block, elements_in_blocks, l_base, comp, move_op());
+
+ //Now combine them using the buffer. Elements from buffer can be
+ //overwritten since they've been saved to xbuf
+ l_merged = op_merge_left_step
+ ( first_block - l_merged, elements_in_blocks, l_merged, l_build_buf, kbuf - l_merged, comp, move_op());
+
+ //Restore internal buffer from external buffer unless kbuf was l_build_buf,
+ //in that case restoration will happen later
+ if(kbuf != l_build_buf){
+ boost::move(xbuf.data()+kbuf-l_merged, xbuf.data() + kbuf, first_block-l_merged+elements_in_blocks);
+ }
+ }
+ else{
+ l_merged = insertion_sort_step(first_block, elements_in_blocks, l_base, comp);
+ rotate_gcd(first_block - l_merged, first_block, first_block+elements_in_blocks);
+ }
+
+ //Now combine elements using the buffer. Elements from buffer can't be
+ //overwritten since xbuf was not big enough, so merge swapping elements.
+ l_merged = op_merge_left_step
+ (first_block - l_merged, elements_in_blocks, l_merged, l_build_buf, l_build_buf - l_merged, comp, swap_op());
+
+ BOOST_ASSERT(l_merged == l_build_buf);
+
+ //////////////////////////////////
+ // Start of merge to right step
+ //////////////////////////////////
+
+ //If kbuf is l_build_buf then we can merge right without swapping
+ //Saved data is still in xbuf
+ if(kbuf && kbuf == l_build_buf){
+ op_merge_right_step(first, elements_in_blocks, l_build_buf, comp, move_op());
+ //Restore internal buffer from external buffer if kbuf was l_build_buf.
+ //as this operation was previously delayed.
+ boost::move(xbuf.data(), xbuf.data() + kbuf, first);
+ }
+ else{
+ op_merge_right_step(first, elements_in_blocks, l_build_buf, comp, swap_op());
+ }
+ xbuf.clear();
+ //2*l_build_buf already merged, now try to merge further
+ //using classic in-place mergesort if enough auxiliary memory is available
+ return buffered_merge_blocks
+ (first_block, first_block + elements_in_blocks, l_build_buf*2, comp, xbuf);
+ }
+}
+
+//Returns true if buffer is placed in
+//[buffer+len-l_intbuf, buffer+len). Otherwise, buffer is
+//[buffer,buffer+l_intbuf)
+template<class RandIt, class Compare>
+bool combine_all_blocks
+ ( RandIt keys
+ , typename iterator_traits<RandIt>::size_type &n_keys
+ , RandIt const buffer
+ , typename iterator_traits<RandIt>::size_type const l_buf_plus_data
+ , typename iterator_traits<RandIt>::size_type l_merged
+ , typename iterator_traits<RandIt>::size_type &l_intbuf
+ , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
+ , Compare comp)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ RandIt const first = buffer + l_intbuf;
+ size_type const l_data = l_buf_plus_data - l_intbuf;
+ size_type const l_unique = l_intbuf+n_keys;
+ //Backup data to external buffer once if possible
+ bool const common_xbuf = l_data > l_merged && l_intbuf && l_intbuf <= xbuf.capacity();
+ if(common_xbuf){
+ if(n_keys){
+ xbuf.move_assign(buffer, l_intbuf);
+ }
+ else{
+ xbuf.clear();
+ merge_sort_uninitialized_copy(buffer, first, xbuf.data(), comp);
+ xbuf.set_size(l_intbuf);
+ }
+ }
+
+ bool prev_merge_left = true;
+ size_type l_prev_total_combined = 0u, l_prev_block = 0;
+ bool prev_use_internal_buf = true;
+
+ for( size_type n = 0; l_data > l_merged
+ ; l_merged*=2
+ , ++n){
+ //If l_intbuf is non-zero, use that internal buffer.
+ // Implies l_block == l_intbuf && use_internal_buf == true
+ //If l_intbuf is zero, see if half keys can be reused as a reduced emergency buffer,
+ // Implies l_block == n_keys/2 && use_internal_buf == true
+ //Otherwise, just give up and and use all keys to merge using rotations (use_internal_buf = false)
+ bool use_internal_buf = false;
+ size_type const l_block = lblock_for_combine(l_intbuf, n_keys, 2*l_merged, use_internal_buf);
+ BOOST_ASSERT(!l_intbuf || (l_block == l_intbuf));
+ BOOST_ASSERT(n == 0 || (!use_internal_buf || prev_use_internal_buf) );
+ BOOST_ASSERT(n == 0 || (!use_internal_buf || l_prev_block == l_block) );
+
+ bool const is_merge_left = (n&1) == 0;
+ size_type const l_total_combined = calculate_total_combined(l_data, l_merged);
+
+ if(prev_use_internal_buf && prev_merge_left){
+ if(is_merge_left || !use_internal_buf){
+ move_data_backward(first-l_prev_block, l_prev_total_combined, first, common_xbuf);
+ }
+ else{
+ //Put the buffer just after l_total_combined
+ RandIt const buf_end = first+l_prev_total_combined;
+ RandIt const buf_beg = buf_end-l_block;
+ if(l_prev_total_combined > l_total_combined){
+ size_type const l_diff = l_prev_total_combined - l_total_combined;
+ move_data_backward(buf_beg-l_diff, l_diff, buf_end-l_diff, common_xbuf);
+ }
+ else if(l_prev_total_combined < l_total_combined){
+ size_type const l_diff = l_total_combined - l_prev_total_combined;
+ move_data_forward(buf_end, l_diff, buf_beg, common_xbuf);
+ }
+ }
+ }
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT(" After move_data : ", l_data + l_intbuf);
+
+ //Combine to form l_merged*2 segments
+ if(n_keys){
+ combine_blocks
+ ( keys, comp, !use_internal_buf || is_merge_left ? first : first-l_block
+ , l_data, l_merged, l_block, use_internal_buf, common_xbuf, xbuf, comp, is_merge_left);
+ }
+ else{
+ size_type *const uint_keys = xbuf.template aligned_trailing<size_type>();
+ combine_blocks
+ ( uint_keys, less(), !use_internal_buf || is_merge_left ? first : first-l_block
+ , l_data, l_merged, l_block, use_internal_buf, common_xbuf, xbuf, comp, is_merge_left);
+ }
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT(" After combine_blocks: ", l_data + l_intbuf);
+ prev_merge_left = is_merge_left;
+ l_prev_total_combined = l_total_combined;
+ l_prev_block = l_block;
+ prev_use_internal_buf = use_internal_buf;
+ }
+ BOOST_ASSERT(l_prev_total_combined == l_data);
+ bool const buffer_right = prev_use_internal_buf && prev_merge_left;
+ l_intbuf = prev_use_internal_buf ? l_prev_block : 0u;
+ n_keys = l_unique - l_intbuf;
+ //Restore data from to external common buffer if used
+ if(common_xbuf){
+ if(buffer_right){
+ boost::move(xbuf.data(), xbuf.data() + l_intbuf, buffer+l_data);
+ }
+ else{
+ boost::move(xbuf.data(), xbuf.data() + l_intbuf, buffer);
+ }
+ }
+ return buffer_right;
+}
+
+template<class RandIt, class Compare>
+void stable_merge
+ ( RandIt first, RandIt const middle, RandIt last
+ , Compare comp
+ , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> &xbuf)
+{
+ BOOST_ASSERT(xbuf.empty());
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type const len1 = size_type(middle-first);
+ size_type const len2 = size_type(last-middle);
+ size_type const l_min = min_value(len1, len2);
+ if(xbuf.capacity() >= l_min){
+ buffered_merge(first, middle, last, comp, xbuf);
+ xbuf.clear();
+ }
+ else{
+ merge_bufferless(first, middle, last, comp);
+ }
+}
+
+
+template<class RandIt, class Compare>
+void final_merge( bool buffer_right
+ , RandIt const first
+ , typename iterator_traits<RandIt>::size_type const l_intbuf
+ , typename iterator_traits<RandIt>::size_type const n_keys
+ , typename iterator_traits<RandIt>::size_type const len
+ , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
+ , Compare comp)
+{
+ BOOST_ASSERT(n_keys || xbuf.size() == l_intbuf);
+ xbuf.clear();
+
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type const n_key_plus_buf = l_intbuf+n_keys;
+ if(buffer_right){
+ stable_sort(first+len-l_intbuf, first+len, comp, xbuf);
+ stable_merge(first+n_keys, first+len-l_intbuf, first+len, antistable<Compare>(comp), xbuf);
+ stable_sort(first, first+n_keys, comp, xbuf);
+ stable_merge(first, first+n_keys, first+len, comp, xbuf);
+ }
+ else{
+ stable_sort(first, first+n_key_plus_buf, comp, xbuf);
+ if(xbuf.capacity() >= n_key_plus_buf){
+ buffered_merge(first, first+n_key_plus_buf, first+len, comp, xbuf);
+ }
+ else if(xbuf.capacity() >= min_value<size_type>(l_intbuf, n_keys)){
+ stable_merge(first+n_keys, first+n_key_plus_buf, first+len, comp, xbuf);
+ stable_merge(first, first+n_keys, first+len, comp, xbuf);
+ }
+ else{
+ merge_bufferless(first, first+n_key_plus_buf, first+len, comp);
+ }
+ }
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT(" After final_merge : ", len);
+}
+
+template<class RandIt, class Compare, class Unsigned, class T>
+bool build_params
+ (RandIt first, Unsigned const len, Compare comp
+ , Unsigned &n_keys, Unsigned &l_intbuf, Unsigned &l_base, Unsigned &l_build_buf
+ , adaptive_xbuf<T> & xbuf
+ )
+{
+ typedef Unsigned size_type;
+
+ //Calculate ideal parameters and try to collect needed unique keys
+ l_base = 0u;
+
+ //Try to find a value near sqrt(len) that is 2^N*l_base where
+ //l_base <= AdaptiveSortInsertionSortThreshold. This property is important
+ //as build_blocks merges to the left iteratively duplicating the
+ //merged size and all the buffer must be used just before the final
+ //merge to right step. This guarantees "build_blocks" produces
+ //segments of size l_build_buf*2, maximizing the classic merge phase.
+ l_intbuf = size_type(ceil_sqrt_multiple(len, &l_base));
+
+ //This is the minimum number of case to implement the ideal algorithm
+ //
+ //l_intbuf is used as buffer plus the key count
+ size_type n_min_ideal_keys = l_intbuf-1u;
+ while(n_min_ideal_keys >= (len-l_intbuf-n_min_ideal_keys)/l_intbuf){
+ --n_min_ideal_keys;
+ }
+ ++n_min_ideal_keys;
+ BOOST_ASSERT(n_min_ideal_keys < l_intbuf);
+
+ if(xbuf.template supports_aligned_trailing<size_type>(l_intbuf, n_min_ideal_keys)){
+ n_keys = 0u;
+ l_build_buf = l_intbuf;
+ }
+ else{
+ //Try to achieve a l_build_buf of length l_intbuf*2, so that we can merge with that
+ //l_intbuf*2 buffer in "build_blocks" and use half of them as buffer and the other half
+ //as keys in combine_all_blocks. In that case n_keys >= n_min_ideal_keys but by a small margin.
+ //
+ //If available memory is 2*sqrt(l), then only sqrt(l) unique keys are needed,
+ //(to be used for keys in combine_all_blocks) as the whole l_build_buf
+ //we'll be backuped in the buffer during build_blocks.
+ bool const non_unique_buf = xbuf.capacity() >= 2*l_intbuf;
+ size_type const to_collect = non_unique_buf ? l_intbuf : l_intbuf*2;
+ size_type collected = collect_unique(first, first+len, to_collect, comp, xbuf);
+
+ //If available memory is 2*sqrt(l), then for "build_params"
+ //the situation is the same as if 2*l_intbuf were collected.
+ if(non_unique_buf && (collected >= n_min_ideal_keys))
+ collected += l_intbuf;
+
+ //If collected keys are not enough, try to fix n_keys and l_intbuf. If no fix
+ //is possible (due to very low unique keys), then go to a slow sort based on rotations.
+ if(collected < (n_min_ideal_keys+l_intbuf)){
+ if(collected < 4){ //No combination possible with less that 4 keys
+ return false;
+ }
+ n_keys = l_intbuf;
+ while(n_keys&(n_keys-1)){
+ n_keys &= n_keys-1; // make it power or 2
+ }
+ while(n_keys > collected){
+ n_keys/=2;
+ }
+ l_base = min_value<Unsigned>(n_keys, AdaptiveSortInsertionSortThreshold);
+ l_intbuf = 0;
+ l_build_buf = n_keys;
+ }
+ else if((collected - l_intbuf) >= l_intbuf){
+ //l_intbuf*2 elements found. Use all of them in the build phase
+ l_build_buf = l_intbuf*2;
+ n_keys = l_intbuf;
+ }
+ else{
+ l_build_buf = l_intbuf;
+ n_keys = n_min_ideal_keys;
+ }
+ BOOST_ASSERT((n_keys+l_intbuf) >= l_build_buf);
+ }
+
+ return true;
+}
+
+template<class RandIt, class Compare>
+void adaptive_sort_impl
+ ( RandIt first
+ , typename iterator_traits<RandIt>::size_type const len
+ , Compare comp
+ , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
+ )
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+
+ //Small sorts go directly to insertion sort
+ if(len <= size_type(AdaptiveSortInsertionSortThreshold)){
+ insertion_sort(first, first + len, comp);
+ return;
+ }
+
+ if((len-len/2) <= xbuf.capacity()){
+ merge_sort(first, first+len, comp, xbuf.data());
+ return;
+ }
+
+ //Make sure it is at least two
+ BOOST_STATIC_ASSERT(AdaptiveSortInsertionSortThreshold >= 4);
+
+ size_type l_base = 0;
+ size_type l_intbuf = 0;
+ size_type n_keys = 0;
+ size_type l_build_buf = 0;
+
+ if(!build_params(first, len, comp, n_keys, l_intbuf, l_base, l_build_buf, xbuf)){
+ stable_sort(first, first+len, comp, xbuf);
+ return;
+ }
+
+ //Otherwise, continue in adaptive_sort
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT("\n After collect_unique: ", len);
+ size_type const n_key_plus_buf = l_intbuf+n_keys;
+ //l_build_buf is always power of two if l_intbuf is zero
+ BOOST_ASSERT(l_intbuf || (0 == (l_build_buf & (l_build_buf-1))));
+
+ //Classic merge sort until internal buffer and xbuf are exhausted
+ size_type const l_merged = build_blocks
+ (first+n_key_plus_buf-l_build_buf, len-n_key_plus_buf+l_build_buf, l_base, l_build_buf, xbuf, comp);
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT(" After build_blocks: ", len);
+
+ //Non-trivial merge
+ bool const buffer_right = combine_all_blocks
+ (first, n_keys, first+n_keys, len-n_keys, l_merged, l_intbuf, xbuf, comp);
+
+ //Sort keys and buffer and merge the whole sequence
+ final_merge(buffer_right, first, l_intbuf, n_keys, len, xbuf, comp);
+}
+
+template<class RandIt, class Compare>
+void adaptive_merge_impl
+ ( RandIt first
+ , typename iterator_traits<RandIt>::size_type const len1
+ , typename iterator_traits<RandIt>::size_type const len2
+ , Compare comp
+ , adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
+ )
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+
+ if(xbuf.capacity() >= min_value<size_type>(len1, len2)){
+ buffered_merge(first, first+len1, first+(len1+len2), comp, xbuf);
+ }
+ else{
+ const size_type len = len1+len2;
+ //Calculate ideal parameters and try to collect needed unique keys
+ size_type l_block = size_type(ceil_sqrt(len));
+
+ if(len1 <= l_block*2 || len2 <= l_block*2){
+ merge_bufferless(first, first+len1, first+len1+len2, comp);
+ return;
+ }
+
+ size_type l_intbuf = xbuf.capacity() >= l_block ? 0u : l_block;
+
+ //This is the minimum number of case to implement the ideal algorithm
+ //ceil(len/l_block) - 1 (as the first block is used as buffer)
+ size_type n_keys = l_block;
+ while(n_keys >= (len-l_intbuf-n_keys)/l_block){
+ --n_keys;
+ }
+ ++n_keys;
+ BOOST_ASSERT(n_keys < l_block);
+
+ if(xbuf.template supports_aligned_trailing<size_type>(l_block, n_keys)){
+ n_keys = 0u;
+ }
+
+ size_type const to_collect = l_intbuf+n_keys;
+ size_type const collected = collect_unique(first, first+len1, to_collect, comp, xbuf);
+
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT("\n A collect: ", len);
+ if(collected != to_collect && collected < 4){
+ merge_bufferless(first, first+len1, first+len1+len2, comp);
+ }
+ else{
+ bool use_internal_buf = true;
+ if (collected != to_collect){
+ l_intbuf = 0u;
+ n_keys = collected;
+ use_internal_buf = false;
+ l_block = lblock_for_combine(l_intbuf, n_keys, len, use_internal_buf);
+ l_intbuf = use_internal_buf ? l_block : 0u;
+ }
+
+ bool xbuf_used = collected == to_collect && xbuf.capacity() >= l_block;
+ size_type const l_combine = len-collected;
+ size_type const l_combine1 = len1-collected;
+
+ size_type n_bef_irreg2, n_aft_irreg2, l_irreg1, l_irreg2, midkey_idx;
+ if(n_keys){
+ RandIt const first_data = first+collected;
+ RandIt const keys = first;
+ combine_params( keys, comp, first_data, l_combine
+ , l_combine1, l_block, xbuf, comp
+ , midkey_idx, l_irreg1, n_bef_irreg2, n_aft_irreg2, l_irreg2, true); //Outputs
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A combine: ", len);
+ if(xbuf_used){
+ merge_blocks_with_buf
+ (keys, keys[midkey_idx], comp, first_data, l_block, l_irreg1, n_bef_irreg2, n_aft_irreg2, l_irreg2, comp, xbuf, xbuf_used);
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A mrg xbf: ", len);
+ }
+ else if(use_internal_buf){
+ #define BOOST_MOVE_ADAPTIVE_MERGE_WITH_BUF
+ #ifdef BOOST_MOVE_ADAPTIVE_MERGE_WITH_BUF
+ range_xbuf<RandIt, swap_op> rbuf(first_data-l_block, first_data);
+ merge_blocks_with_buf
+ (keys, keys[midkey_idx], comp, first_data, l_block, l_irreg1, n_bef_irreg2, n_aft_irreg2, l_irreg2, comp, rbuf, xbuf_used);
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A mrg buf: ", len);
+ #else
+ merge_blocks_left
+ (keys, keys[midkey_idx], comp, first_data, l_block, l_irreg1, n_bef_irreg2, n_aft_irreg2, l_irreg2, comp, xbuf_used);
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A mrg lft: ", len);
+ #endif
+ }
+ else{
+ merge_blocks_bufferless
+ (keys, keys[midkey_idx], comp, first_data, l_block, l_irreg1, n_bef_irreg2, n_aft_irreg2, l_irreg2, comp);
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A mrg bfl: ", len);
+ }
+ }
+ else{
+ xbuf.clear();
+ size_type *const uint_keys = xbuf.template aligned_trailing<size_type>(l_block);
+ combine_params( uint_keys, less(), first, l_combine
+ , l_combine1, l_block, xbuf, comp
+ , midkey_idx, l_irreg1, n_bef_irreg2, n_aft_irreg2, l_irreg2, true); //Outputs
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A combine: ", len);
+ merge_blocks_with_buf
+ (uint_keys, uint_keys[midkey_idx], less(), first, l_block, l_irreg1, n_bef_irreg2, n_aft_irreg2, l_irreg2, comp, xbuf, true);
+ xbuf.clear();
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A mrg lft: ", len);
+ }
+
+ n_keys = collected-l_intbuf;
+ if(use_internal_buf){
+ if(xbuf_used){
+ xbuf.clear();
+ //Nothing to do
+ if(n_keys){
+ stable_sort(first, first+n_keys, comp, xbuf);
+ stable_merge(first, first+n_keys, first+len, comp, xbuf);
+ }
+ }
+ else{
+ #ifdef BOOST_MOVE_ADAPTIVE_MERGE_WITH_BUF
+ xbuf.clear();
+ stable_sort(first, first+collected, comp, xbuf);
+ stable_merge(first, first+collected, first+len, comp, xbuf);
+ #else
+ xbuf.clear();
+ stable_sort(first+len-l_block, first+len, comp, xbuf);
+ RandIt const pos1 = lower_bound(first+n_keys, first+len-l_block, first[len-1], comp);
+ RandIt const pos2 = rotate_gcd(pos1, first+len-l_block, first+len);
+ stable_merge(first+n_keys, pos1, pos2, antistable<Compare>(comp), xbuf);
+ if(n_keys){
+ stable_sort(first, first+n_keys, comp, xbuf);
+ stable_merge(first, first+n_keys, first+len, comp, xbuf);
+ }
+ #endif
+ }
+
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A buf mrg: ", len);
+ }
+ else{
+ stable_sort(first, first+collected, comp, xbuf);
+ xbuf.clear();
+ if(xbuf.capacity() >= collected){
+ buffered_merge(first, first+collected, first+len1+len2, comp, xbuf);
+ }
+ else{
+ merge_bufferless(first, first+collected, first+len1+len2, comp);
+ }
+ }
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A key mrg: ", len);
+ }
+ }
+}
+
+} //namespace detail_adaptive {
+} //namespace movelib {
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#define BOOST_MOVE_ADAPTIVE_SORT_MERGE_HPP
diff --git a/boost/move/algo/detail/basic_op.hpp b/boost/move/algo/detail/basic_op.hpp
new file mode 100644
index 0000000000..936f7a2a3d
--- /dev/null
+++ b/boost/move/algo/detail/basic_op.hpp
@@ -0,0 +1,63 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_MOVE_ALGO_BASIC_OP
+#define BOOST_MOVE_ALGO_BASIC_OP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/utility_core.hpp>
+#include <boost/move/adl_move_swap.hpp>
+
+namespace boost {
+namespace movelib {
+
+struct forward_t{};
+struct backward_t{};
+
+struct move_op
+{
+ template <class SourceIt, class DestinationIt>
+ void operator()(SourceIt source, DestinationIt dest)
+ { *dest = ::boost::move(*source); }
+
+ template <class SourceIt, class DestinationIt>
+ DestinationIt operator()(forward_t, SourceIt first, SourceIt last, DestinationIt dest_begin)
+ { return ::boost::move(first, last, dest_begin); }
+
+ template <class SourceIt, class DestinationIt>
+ DestinationIt operator()(backward_t, SourceIt first, SourceIt last, DestinationIt dest_last)
+ { return ::boost::move_backward(first, last, dest_last); }
+};
+
+struct swap_op
+{
+ template <class SourceIt, class DestinationIt>
+ void operator()(SourceIt source, DestinationIt dest)
+ { boost::adl_move_swap(*dest, *source); }
+
+ template <class SourceIt, class DestinationIt>
+ DestinationIt operator()(forward_t, SourceIt first, SourceIt last, DestinationIt dest_begin)
+ { return boost::adl_move_swap_ranges(first, last, dest_begin); }
+
+ template <class SourceIt, class DestinationIt>
+ DestinationIt operator()(backward_t, SourceIt first, SourceIt last, DestinationIt dest_begin)
+ { return boost::adl_move_swap_ranges_backward(first, last, dest_begin); }
+};
+
+}} //namespace boost::movelib
+
+#endif //BOOST_MOVE_ALGO_BASIC_OP
diff --git a/boost/move/algo/detail/bufferless_merge_sort.hpp b/boost/move/algo/detail/bufferless_merge_sort.hpp
new file mode 100644
index 0000000000..a8e2763d7c
--- /dev/null
+++ b/boost/move/algo/detail/bufferless_merge_sort.hpp
@@ -0,0 +1,120 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_ALGO_BUFFERLESS_MERGE_SORT_HPP
+#define BOOST_MOVE_ALGO_BUFFERLESS_MERGE_SORT_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp>
+
+#include <boost/move/utility_core.hpp>
+#include <boost/move/adl_move_swap.hpp>
+
+#include <boost/move/algo/move.hpp>
+#include <boost/move/algo/detail/merge.hpp>
+
+#include <boost/move/detail/iterator_traits.hpp>
+#include <boost/move/algo/detail/insertion_sort.hpp>
+#include <cassert>
+
+namespace boost {
+namespace movelib {
+// @cond
+namespace detail_bufferless_mergesort {
+
+static const std::size_t UnbufferedMergeSortInsertionSortThreshold = 16;
+
+//A in-placed version based on:
+//Jyrki Katajainen, Tomi Pasanen, Jukka Teuhola.
+//``Practical in-place mergesort''. Nordic Journal of Computing, 1996.
+
+template<class RandIt, class Compare>
+void bufferless_merge_sort(RandIt first, RandIt last, Compare comp);
+
+template<class RandIt, class Compare>
+void swap_sort(RandIt const first, RandIt const last, RandIt const buffer_first, RandIt const buffer_last, Compare comp, bool buffer_at_right)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ if (size_type(last - first) > UnbufferedMergeSortInsertionSortThreshold) {
+ RandIt m = first + (last - first) / 2;
+ bufferless_merge_sort(first, m, comp);
+ bufferless_merge_sort(m, last, comp);
+ if(buffer_at_right){
+ //Use antistable to minimize movements (if equal, move first half elements
+ //to maximize the chance last half elements are already in place.
+ boost::movelib::swap_merge_right(first, m, last, buffer_last, boost::movelib::antistable<Compare>(comp));
+ }
+ else{
+ boost::movelib::swap_merge_left(buffer_first, first, m, last, comp);
+ }
+ }
+ else
+ boost::movelib::insertion_sort_swap(first, last, buffer_first, comp);
+}
+
+template<class RandIt, class Compare>
+void bufferless_merge_sort(RandIt const first, RandIt const last, Compare comp)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type len = size_type(last - first);
+ if (len > size_type(UnbufferedMergeSortInsertionSortThreshold)) {
+ len /= 2;
+ RandIt h = last - len; //ceil(half)
+ RandIt f = h - len; //ceil(first)
+ swap_sort(f, h, h, last, comp, true); //[h, last) contains sorted elements
+
+ //Divide unsorted first half in two
+ len = size_type(h - first);
+ while (len > size_type(UnbufferedMergeSortInsertionSortThreshold)) {
+ len /= 2;
+ RandIt n = h; //new end
+ h = n - len; //ceil(half')
+ f = h - len; //ceil(first')
+ swap_sort(h, n, f, h, comp, false); // the first half of the previous working area [f, h)
+ //contains sorted elements: working area in the middle [h, n)
+ //Now merge small (left) sorted with big (right) sorted (buffer is between them)
+ swap_merge_with_right_placed(f, h, h, n, last, comp);
+ }
+
+ boost::movelib::insertion_sort(first, h, comp);
+ boost::movelib::merge_bufferless(first, h, last, comp);
+ }
+ else{
+ boost::movelib::insertion_sort(first, last, comp);
+ }
+}
+
+} //namespace detail_bufferless_mergesort {
+
+// @endcond
+
+//Unstable bufferless merge sort
+template<class RandIt, class Compare>
+void bufferless_merge_sort(RandIt first, RandIt last, Compare comp)
+{
+ detail_bufferless_mergesort::bufferless_merge_sort(first, last, comp);
+}
+
+}} //namespace boost::movelib
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_ALGO_BUFFERLESS_MERGE_SORT_HPP
diff --git a/boost/move/algo/detail/insertion_sort.hpp b/boost/move/algo/detail/insertion_sort.hpp
new file mode 100644
index 0000000000..15df35d9d6
--- /dev/null
+++ b/boost/move/algo/detail/insertion_sort.hpp
@@ -0,0 +1,127 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2014-2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_DETAIL_INSERT_SORT_HPP
+#define BOOST_MOVE_DETAIL_INSERT_SORT_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/utility_core.hpp>
+#include <boost/move/algo/move.hpp>
+#include <boost/move/detail/iterator_traits.hpp>
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/detail/placement_new.hpp>
+#include <boost/move/detail/destruct_n.hpp>
+#include <boost/move/algo/detail/basic_op.hpp>
+#include <boost/move/detail/placement_new.hpp>
+
+namespace boost { namespace movelib{
+
+// @cond
+
+template <class Compare, class ForwardIterator, class BirdirectionalIterator, class Op>
+void insertion_sort_op(ForwardIterator first1, ForwardIterator last1, BirdirectionalIterator first2, Compare comp, Op op)
+{
+ if (first1 != last1){
+ BirdirectionalIterator last2 = first2;
+ op(first1, last2);
+ for (++last2; ++first1 != last1; ++last2){
+ BirdirectionalIterator j2 = last2;
+ BirdirectionalIterator i2 = j2;
+ if (comp(*first1, *--i2)){
+ op(i2, j2);
+ for (--j2; i2 != first2 && comp(*first1, *--i2); --j2) {
+ op(i2, j2);
+ }
+ }
+ op(first1, j2);
+ }
+ }
+}
+
+template <class Compare, class ForwardIterator, class BirdirectionalIterator>
+void insertion_sort_swap(ForwardIterator first1, ForwardIterator last1, BirdirectionalIterator first2, Compare comp)
+{
+ insertion_sort_op(first1, last1, first2, comp, swap_op());
+}
+
+
+template <class Compare, class ForwardIterator, class BirdirectionalIterator>
+void insertion_sort_copy(ForwardIterator first1, ForwardIterator last1, BirdirectionalIterator first2, Compare comp)
+{
+ insertion_sort_op(first1, last1, first2, comp, move_op());
+}
+
+// @endcond
+
+template <class Compare, class BirdirectionalIterator>
+void insertion_sort(BirdirectionalIterator first, BirdirectionalIterator last, Compare comp)
+{
+ typedef typename boost::movelib::iterator_traits<BirdirectionalIterator>::value_type value_type;
+ if (first != last){
+ BirdirectionalIterator i = first;
+ for (++i; i != last; ++i){
+ BirdirectionalIterator j = i;
+ if (comp(*i, *--j)) {
+ value_type tmp(::boost::move(*i));
+ *i = ::boost::move(*j);
+ for (BirdirectionalIterator k = j; k != first && comp(tmp, *--k); --j) {
+ *j = ::boost::move(*k);
+ }
+ *j = ::boost::move(tmp);
+ }
+ }
+ }
+}
+
+template <class Compare, class BirdirectionalIterator>
+void insertion_sort_uninitialized_copy
+ (BirdirectionalIterator first1, BirdirectionalIterator const last1
+ , typename iterator_traits<BirdirectionalIterator>::value_type* const first2
+ , Compare comp)
+{
+ typedef typename iterator_traits<BirdirectionalIterator>::value_type value_type;
+ if (first1 != last1){
+ value_type* last2 = first2;
+ ::new(last2, boost_move_new_t()) value_type(move(*first1));
+ destruct_n<value_type> d(first2);
+ d.incr();
+ for (++last2; ++first1 != last1; ++last2){
+ value_type* j2 = last2;
+ value_type* k2 = j2;
+ if (comp(*first1, *--k2)){
+ ::new(j2, boost_move_new_t()) value_type(move(*k2));
+ d.incr();
+ for (--j2; k2 != first2 && comp(*first1, *--k2); --j2)
+ *j2 = move(*k2);
+ *j2 = move(*first1);
+ }
+ else{
+ ::new(j2, boost_move_new_t()) value_type(move(*first1));
+ d.incr();
+ }
+ }
+ d.release();
+ }
+}
+
+}} //namespace boost { namespace movelib{
+
+#endif //#ifndef BOOST_MOVE_DETAIL_INSERT_SORT_HPP
diff --git a/boost/move/algo/detail/merge.hpp b/boost/move/algo/detail/merge.hpp
new file mode 100644
index 0000000000..a0a5afa3e6
--- /dev/null
+++ b/boost/move/algo/detail/merge.hpp
@@ -0,0 +1,444 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_MOVE_MERGE_HPP
+#define BOOST_MOVE_MERGE_HPP
+
+#include <boost/move/algo/move.hpp>
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/move/algo/detail/basic_op.hpp>
+#include <boost/move/detail/iterator_traits.hpp>
+#include <boost/move/detail/destruct_n.hpp>
+#include <boost/assert.hpp>
+
+namespace boost {
+namespace movelib {
+
+// @cond
+
+/*
+template<typename Unsigned>
+inline Unsigned gcd(Unsigned x, Unsigned y)
+{
+ if(0 == ((x &(x-1)) | (y & (y-1)))){
+ return x < y ? x : y;
+ }
+ else{
+ do
+ {
+ Unsigned t = x % y;
+ x = y;
+ y = t;
+ } while (y);
+ return x;
+ }
+}
+*/
+
+//Modified version from "An Optimal In-Place Array Rotation Algorithm", Ching-Kuang Shene
+template<typename Unsigned>
+Unsigned gcd(Unsigned x, Unsigned y)
+{
+ if(0 == ((x &(x-1)) | (y & (y-1)))){
+ return x < y ? x : y;
+ }
+ else{
+ Unsigned z = 1;
+ while((!(x&1)) & (!(y&1))){
+ z <<=1, x>>=1, y>>=1;
+ }
+ while(x && y){
+ if(!(x&1))
+ x >>=1;
+ else if(!(y&1))
+ y >>=1;
+ else if(x >=y)
+ x = (x-y) >> 1;
+ else
+ y = (y-x) >> 1;
+ }
+ return z*(x+y);
+ }
+}
+
+template<typename RandIt>
+RandIt rotate_gcd(RandIt first, RandIt middle, RandIt last)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+
+ if(first == middle)
+ return last;
+ if(middle == last)
+ return first;
+ const size_type middle_pos = size_type(middle - first);
+ RandIt ret = last - middle_pos;
+ if (middle == ret){
+ boost::adl_move_swap_ranges(first, middle, middle);
+ }
+ else{
+ const size_type length = size_type(last - first);
+ for( RandIt it_i(first), it_gcd(it_i + gcd(length, middle_pos))
+ ; it_i != it_gcd
+ ; ++it_i){
+ value_type temp(boost::move(*it_i));
+ RandIt it_j = it_i;
+ RandIt it_k = it_j+middle_pos;
+ do{
+ *it_j = boost::move(*it_k);
+ it_j = it_k;
+ size_type const left = size_type(last - it_j);
+ it_k = left > middle_pos ? it_j + middle_pos : first + (middle_pos - left);
+ } while(it_k != it_i);
+ *it_j = boost::move(temp);
+ }
+ }
+ return ret;
+}
+
+template <class RandIt, class T, class Compare>
+RandIt lower_bound
+ (RandIt first, const RandIt last, const T& key, Compare comp)
+{
+ typedef typename iterator_traits
+ <RandIt>::size_type size_type;
+ size_type len = size_type(last - first);
+ RandIt middle;
+
+ while (len) {
+ size_type step = len >> 1;
+ middle = first;
+ middle += step;
+
+ if (comp(*middle, key)) {
+ first = ++middle;
+ len -= step + 1;
+ }
+ else{
+ len = step;
+ }
+ }
+ return first;
+}
+
+template <class RandIt, class T, class Compare>
+RandIt upper_bound
+ (RandIt first, const RandIt last, const T& key, Compare comp)
+{
+ typedef typename iterator_traits
+ <RandIt>::size_type size_type;
+ size_type len = size_type(last - first);
+ RandIt middle;
+
+ while (len) {
+ size_type step = len >> 1;
+ middle = first;
+ middle += step;
+
+ if (!comp(key, *middle)) {
+ first = ++middle;
+ len -= step + 1;
+ }
+ else{
+ len = step;
+ }
+ }
+ return first;
+}
+
+
+template<class RandIt, class Compare, class Op>
+void op_merge_left( RandIt buf_first
+ , RandIt first1
+ , RandIt const last1
+ , RandIt const last2
+ , Compare comp
+ , Op op)
+{
+ for(RandIt first2=last1; first2 != last2; ++buf_first){
+ if(first1 == last1){
+ op(forward_t(), first2, last2, buf_first);
+ return;
+ }
+ else if(comp(*first2, *first1)){
+ op(first2, buf_first);
+ ++first2;
+ }
+ else{
+ op(first1, buf_first);
+ ++first1;
+ }
+ }
+ if(buf_first != first1){//In case all remaining elements are in the same place
+ //(e.g. buffer is exactly the size of the second half
+ //and all elements from the second half are less)
+ op(forward_t(), first1, last1, buf_first);
+ }
+ else{
+ buf_first = buf_first;
+ }
+}
+
+// [buf_first, first1) -> buffer
+// [first1, last1) merge [last1,last2) -> [buf_first,buf_first+(last2-first1))
+// Elements from buffer are moved to [last2 - (first1-buf_first), last2)
+// Note: distance(buf_first, first1) >= distance(last1, last2), so no overlapping occurs
+template<class RandIt, class Compare>
+void merge_left
+ (RandIt buf_first, RandIt first1, RandIt const last1, RandIt const last2, Compare comp)
+{
+ op_merge_left(buf_first, first1, last1, last2, comp, move_op());
+}
+
+// [buf_first, first1) -> buffer
+// [first1, last1) merge [last1,last2) -> [buf_first,buf_first+(last2-first1))
+// Elements from buffer are swapped to [last2 - (first1-buf_first), last2)
+// Note: distance(buf_first, first1) >= distance(last1, last2), so no overlapping occurs
+template<class RandIt, class Compare>
+void swap_merge_left
+ (RandIt buf_first, RandIt first1, RandIt const last1, RandIt const last2, Compare comp)
+{
+ op_merge_left(buf_first, first1, last1, last2, comp, swap_op());
+}
+
+template<class RandIt, class Compare, class Op>
+void op_merge_right
+ (RandIt const first1, RandIt last1, RandIt last2, RandIt buf_last, Compare comp, Op op)
+{
+ RandIt const first2 = last1;
+ while(first1 != last1){
+ if(last2 == first2){
+ op(backward_t(), first1, last1, buf_last);
+ return;
+ }
+ --last2;
+ --last1;
+ --buf_last;
+ if(comp(*last2, *last1)){
+ op(last1, buf_last);
+ ++last2;
+ }
+ else{
+ op(last2, buf_last);
+ ++last1;
+ }
+ }
+ if(last2 != buf_last){ //In case all remaining elements are in the same place
+ //(e.g. buffer is exactly the size of the first half
+ //and all elements from the second half are less)
+ op(backward_t(), first2, last2, buf_last);
+ }
+}
+
+// [last2, buf_last) - buffer
+// [first1, last1) merge [last1,last2) -> [first1+(buf_last-last2), buf_last)
+// Note: distance[last2, buf_last) >= distance[first1, last1), so no overlapping occurs
+template<class RandIt, class Compare>
+void merge_right
+ (RandIt first1, RandIt last1, RandIt last2, RandIt buf_last, Compare comp)
+{
+ op_merge_right(first1, last1, last2, buf_last, comp, move_op());
+}
+
+// [last2, buf_last) - buffer
+// [first1, last1) merge [last1,last2) -> [first1+(buf_last-last2), buf_last)
+// Note: distance[last2, buf_last) >= distance[first1, last1), so no overlapping occurs
+template<class RandIt, class Compare>
+void swap_merge_right
+ (RandIt first1, RandIt last1, RandIt last2, RandIt buf_last, Compare comp)
+{
+ op_merge_right(first1, last1, last2, buf_last, comp, swap_op());
+}
+
+// cost: min(L1,L2)^2+max(L1,L2)
+template<class RandIt, class Compare>
+void merge_bufferless(RandIt first, RandIt middle, RandIt last, Compare comp)
+{
+ if((middle - first) < (last - middle)){
+ while(first != middle){
+ RandIt const old_last1 = middle;
+ middle = lower_bound(middle, last, *first, comp);
+ first = rotate_gcd(first, old_last1, middle);
+ if(middle == last){
+ break;
+ }
+ do{
+ ++first;
+ } while(first != middle && !comp(*middle, *first));
+ }
+ }
+ else{
+ while(middle != last){
+ RandIt p = upper_bound(first, middle, last[-1], comp);
+ last = rotate_gcd(p, middle, last);
+ middle = p;
+ if(middle == first){
+ break;
+ }
+ --p;
+ do{
+ --last;
+ } while(middle != last && !comp(last[-1], *p));
+ }
+ }
+}
+
+template<class Comp>
+struct antistable
+{
+ antistable(Comp &comp)
+ : m_comp(comp)
+ {}
+
+ template<class U, class V>
+ bool operator()(const U &u, const V & v)
+ { return !m_comp(v, u); }
+
+ private:
+ antistable & operator=(const antistable &);
+ Comp &m_comp;
+};
+
+// [r_first, r_last) are already in the right part of the destination range.
+template <class Compare, class InputIterator, class InputOutIterator, class Op>
+void op_merge_with_right_placed
+ ( InputIterator first, InputIterator last
+ , InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
+ , Compare comp, Op op)
+{
+ BOOST_ASSERT((last - first) == (r_first - dest_first));
+ while ( first != last ) {
+ if (r_first == r_last) {
+ InputOutIterator end = op(forward_t(), first, last, dest_first);
+ BOOST_ASSERT(end == r_last);
+ (void)end;
+ return;
+ }
+ else if (comp(*r_first, *first)) {
+ op(r_first, dest_first);
+ ++r_first;
+ }
+ else {
+ op(first, dest_first);
+ ++first;
+ }
+ ++dest_first;
+ }
+ // Remaining [r_first, r_last) already in the correct place
+}
+
+template <class Compare, class InputIterator, class InputOutIterator>
+void swap_merge_with_right_placed
+ ( InputIterator first, InputIterator last
+ , InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
+ , Compare comp)
+{
+ op_merge_with_right_placed(first, last, dest_first, r_first, r_last, comp, swap_op());
+}
+
+// [r_first, r_last) are already in the right part of the destination range.
+template <class Compare, class Op, class BidirIterator, class BidirOutIterator>
+void op_merge_with_left_placed
+ ( BidirOutIterator const first, BidirOutIterator last, BidirOutIterator dest_last
+ , BidirIterator const r_first, BidirIterator r_last
+ , Compare comp, Op op)
+{
+ BOOST_ASSERT((dest_last - last) == (r_last - r_first));
+ while( r_first != r_last ) {
+ if(first == last) {
+ BidirOutIterator res = op(backward_t(), r_first, r_last, dest_last);
+ BOOST_ASSERT(last == res);
+ (void)res;
+ return;
+ }
+ --r_last;
+ --last;
+ if(comp(*r_last, *last)){
+ ++r_last;
+ --dest_last;
+ op(last, dest_last);
+ }
+ else{
+ ++last;
+ --dest_last;
+ op(r_last, dest_last);
+ }
+ }
+ // Remaining [first, last) already in the correct place
+}
+
+// @endcond
+
+// [r_first, r_last) are already in the right part of the destination range.
+template <class Compare, class BidirIterator, class BidirOutIterator>
+void merge_with_left_placed
+ ( BidirOutIterator const first, BidirOutIterator last, BidirOutIterator dest_last
+ , BidirIterator const r_first, BidirIterator r_last
+ , Compare comp)
+{
+ op_merge_with_left_placed(first, last, dest_last, r_first, r_last, comp, move_op());
+}
+
+// [r_first, r_last) are already in the right part of the destination range.
+template <class Compare, class InputIterator, class InputOutIterator>
+void merge_with_right_placed
+ ( InputIterator first, InputIterator last
+ , InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
+ , Compare comp)
+{
+ op_merge_with_right_placed(first, last, dest_first, r_first, r_last, comp, move_op());
+}
+
+// [r_first, r_last) are already in the right part of the destination range.
+// [dest_first, r_first) is uninitialized memory
+template <class Compare, class InputIterator, class InputOutIterator>
+void uninitialized_merge_with_right_placed
+ ( InputIterator first, InputIterator last
+ , InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
+ , Compare comp)
+{
+ BOOST_ASSERT((last - first) == (r_first - dest_first));
+ typedef typename iterator_traits<InputOutIterator>::value_type value_type;
+ InputOutIterator const original_r_first = r_first;
+
+ destruct_n<value_type> d(&*dest_first);
+
+ while ( first != last && dest_first != original_r_first ) {
+ if (r_first == r_last) {
+ for(; dest_first != original_r_first; ++dest_first, ++first){
+ ::new(&*dest_first) value_type(::boost::move(*first));
+ d.incr();
+ }
+ d.release();
+ InputOutIterator end = ::boost::move(first, last, original_r_first);
+ BOOST_ASSERT(end == r_last);
+ (void)end;
+ return;
+ }
+ else if (comp(*r_first, *first)) {
+ ::new(&*dest_first) value_type(::boost::move(*r_first));
+ d.incr();
+ ++r_first;
+ }
+ else {
+ ::new(&*dest_first) value_type(::boost::move(*first));
+ d.incr();
+ ++first;
+ }
+ ++dest_first;
+ }
+ d.release();
+ merge_with_right_placed(first, last, original_r_first, r_first, r_last, comp);
+}
+
+} //namespace movelib {
+} //namespace boost {
+
+#endif //#define BOOST_MOVE_MERGE_HPP
diff --git a/boost/move/algo/detail/merge_sort.hpp b/boost/move/algo/detail/merge_sort.hpp
new file mode 100644
index 0000000000..8101fce654
--- /dev/null
+++ b/boost/move/algo/detail/merge_sort.hpp
@@ -0,0 +1,124 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_DETAIL_MERGE_SORT_HPP
+#define BOOST_MOVE_DETAIL_MERGE_SORT_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp>
+
+#include <boost/move/utility_core.hpp>
+#include <boost/move/algo/move.hpp>
+#include <boost/move/algo/detail/merge.hpp>
+#include <boost/move/detail/iterator_traits.hpp>
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/move/detail/destruct_n.hpp>
+#include <boost/move/algo/detail/insertion_sort.hpp>
+#include <cassert>
+
+namespace boost {
+namespace movelib {
+
+// @cond
+
+static const unsigned MergeSortInsertionSortThreshold = 16;
+
+// @endcond
+
+template<class RandIt, class RandIt2, class Compare>
+void merge_sort_copy( RandIt first, RandIt last
+ , RandIt2 dest, Compare comp)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+
+ size_type const count = size_type(last - first);
+ if(count <= MergeSortInsertionSortThreshold){
+ insertion_sort_copy(first, last, dest, comp);
+ }
+ else{
+ size_type const half = count/2;
+ merge_sort_copy(first + half, last , dest+half , comp);
+ merge_sort_copy(first , first + half, first + half, comp);
+ merge_with_right_placed
+ ( first + half, first + half + half
+ , dest, dest+half, dest + count
+ , comp);
+ }
+}
+
+template<class RandIt, class Compare>
+void merge_sort_uninitialized_copy( RandIt first, RandIt last
+ , typename iterator_traits<RandIt>::value_type* uninitialized
+ , Compare comp)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+
+ size_type const count = size_type(last - first);
+ if(count <= MergeSortInsertionSortThreshold){
+ insertion_sort_uninitialized_copy(first, last, uninitialized, comp);
+ }
+ else{
+ size_type const half = count/2;
+ merge_sort_uninitialized_copy(first + half, last, uninitialized + half, comp);
+ destruct_n<value_type> d(uninitialized+half);
+ d.incr(count-half);
+ merge_sort_copy(first, first + half, first + half, comp);
+ uninitialized_merge_with_right_placed
+ ( first + half, first + half + half
+ , uninitialized, uninitialized+half, uninitialized+count
+ , comp);
+ d.release();
+ }
+}
+
+template<class RandIt, class Compare>
+void merge_sort( RandIt first, RandIt last, Compare comp
+ , typename iterator_traits<RandIt>::value_type* uninitialized)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+
+ size_type const count = size_type(last - first);
+ if(count <= MergeSortInsertionSortThreshold){
+ insertion_sort(first, last, comp);
+ }
+ else{
+ size_type const half = count/2;
+ size_type const rest = count - half;
+ RandIt const half_it = first + half;
+ RandIt const rest_it = first + rest;
+
+ merge_sort_uninitialized_copy(half_it, last, uninitialized, comp);
+ destruct_n<value_type> d(uninitialized);
+ d.incr(rest);
+ merge_sort_copy(first, half_it, rest_it, comp);
+ merge_with_right_placed
+ ( uninitialized, uninitialized + rest
+ , first, rest_it, last, antistable<Compare>(comp));
+ }
+}
+
+}} //namespace boost { namespace movelib{
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_DETAIL_MERGE_SORT_HPP
diff --git a/boost/move/algo/move.hpp b/boost/move/algo/move.hpp
new file mode 100644
index 0000000000..943f286c94
--- /dev/null
+++ b/boost/move/algo/move.hpp
@@ -0,0 +1,155 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_ALGO_MOVE_HPP
+#define BOOST_MOVE_ALGO_MOVE_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+
+#include <boost/move/utility_core.hpp>
+#include <boost/move/detail/iterator_traits.hpp>
+#include <boost/detail/no_exceptions_support.hpp>
+
+namespace boost {
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#if !defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
+
+ //! <b>Effects</b>: Moves elements in the range [first,last) into the range [result,result + (last -
+ //! first)) starting from first and proceeding to last. For each non-negative integer n < (last-first),
+ //! performs *(result + n) = ::boost::move (*(first + n)).
+ //!
+ //! <b>Effects</b>: result + (last - first).
+ //!
+ //! <b>Requires</b>: result shall not be in the range [first,last).
+ //!
+ //! <b>Complexity</b>: Exactly last - first move assignments.
+ template <typename I, // I models InputIterator
+ typename O> // O models OutputIterator
+ O move(I f, I l, O result)
+ {
+ while (f != l) {
+ *result = ::boost::move(*f);
+ ++f; ++result;
+ }
+ return result;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // move_backward
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+ //! <b>Effects</b>: Moves elements in the range [first,last) into the range
+ //! [result - (last-first),result) starting from last - 1 and proceeding to
+ //! first. For each positive integer n <= (last - first),
+ //! performs *(result - n) = ::boost::move(*(last - n)).
+ //!
+ //! <b>Requires</b>: result shall not be in the range [first,last).
+ //!
+ //! <b>Returns</b>: result - (last - first).
+ //!
+ //! <b>Complexity</b>: Exactly last - first assignments.
+ template <typename I, // I models BidirectionalIterator
+ typename O> // O models BidirectionalIterator
+ O move_backward(I f, I l, O result)
+ {
+ while (f != l) {
+ --l; --result;
+ *result = ::boost::move(*l);
+ }
+ return result;
+ }
+
+#else
+
+ using ::std::move_backward;
+
+#endif //!defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_move
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! <b>Effects</b>:
+//! \code
+//! for (; first != last; ++result, ++first)
+//! new (static_cast<void*>(&*result))
+//! typename iterator_traits<ForwardIterator>::value_type(boost::move(*first));
+//! \endcode
+//!
+//! <b>Returns</b>: result
+template
+ <typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+F uninitialized_move(I f, I l, F r
+ /// @cond
+// ,typename ::boost::move_detail::enable_if<has_move_emulation_enabled<typename boost::movelib::iterator_traits<I>::value_type> >::type* = 0
+ /// @endcond
+ )
+{
+ typedef typename boost::movelib::iterator_traits<I>::value_type input_value_type;
+
+ F back = r;
+ BOOST_TRY{
+ while (f != l) {
+ void * const addr = static_cast<void*>(::boost::move_detail::addressof(*r));
+ ::new(addr) input_value_type(::boost::move(*f));
+ ++f; ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ back->~input_value_type();
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return r;
+}
+
+/// @cond
+/*
+template
+ <typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+F uninitialized_move(I f, I l, F r,
+ typename ::boost::move_detail::disable_if<has_move_emulation_enabled<typename boost::movelib::iterator_traits<I>::value_type> >::type* = 0)
+{
+ return std::uninitialized_copy(f, l, r);
+}
+*/
+
+/// @endcond
+
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_ALGO_MOVE_HPP
diff --git a/boost/move/algorithm.hpp b/boost/move/algorithm.hpp
index fbda0f40d1..825d7716c2 100644
--- a/boost/move/algorithm.hpp
+++ b/boost/move/algorithm.hpp
@@ -26,6 +26,7 @@
#include <boost/move/utility_core.hpp>
#include <boost/move/iterator.hpp>
+#include <boost/move/algo/move.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <algorithm> //copy, copy_backward
@@ -35,122 +36,6 @@ namespace boost {
//////////////////////////////////////////////////////////////////////////////
//
-// move
-//
-//////////////////////////////////////////////////////////////////////////////
-
-#if !defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
-
- //! <b>Effects</b>: Moves elements in the range [first,last) into the range [result,result + (last -
- //! first)) starting from first and proceeding to last. For each non-negative integer n < (last-first),
- //! performs *(result + n) = ::boost::move (*(first + n)).
- //!
- //! <b>Effects</b>: result + (last - first).
- //!
- //! <b>Requires</b>: result shall not be in the range [first,last).
- //!
- //! <b>Complexity</b>: Exactly last - first move assignments.
- template <typename I, // I models InputIterator
- typename O> // O models OutputIterator
- O move(I f, I l, O result)
- {
- while (f != l) {
- *result = ::boost::move(*f);
- ++f; ++result;
- }
- return result;
- }
-
- //////////////////////////////////////////////////////////////////////////////
- //
- // move_backward
- //
- //////////////////////////////////////////////////////////////////////////////
-
- //! <b>Effects</b>: Moves elements in the range [first,last) into the range
- //! [result - (last-first),result) starting from last - 1 and proceeding to
- //! first. For each positive integer n <= (last - first),
- //! performs *(result - n) = ::boost::move(*(last - n)).
- //!
- //! <b>Requires</b>: result shall not be in the range [first,last).
- //!
- //! <b>Returns</b>: result - (last - first).
- //!
- //! <b>Complexity</b>: Exactly last - first assignments.
- template <typename I, // I models BidirectionalIterator
- typename O> // O models BidirectionalIterator
- O move_backward(I f, I l, O result)
- {
- while (f != l) {
- --l; --result;
- *result = ::boost::move(*l);
- }
- return result;
- }
-
-#else
-
- using ::std::move_backward;
-
-#endif //!defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// uninitialized_move
-//
-//////////////////////////////////////////////////////////////////////////////
-
-//! <b>Effects</b>:
-//! \code
-//! for (; first != last; ++result, ++first)
-//! new (static_cast<void*>(&*result))
-//! typename iterator_traits<ForwardIterator>::value_type(boost::move(*first));
-//! \endcode
-//!
-//! <b>Returns</b>: result
-template
- <typename I, // I models InputIterator
- typename F> // F models ForwardIterator
-F uninitialized_move(I f, I l, F r
- /// @cond
-// ,typename ::boost::move_detail::enable_if<has_move_emulation_enabled<typename std::iterator_traits<I>::value_type> >::type* = 0
- /// @endcond
- )
-{
- typedef typename std::iterator_traits<I>::value_type input_value_type;
-
- F back = r;
- BOOST_TRY{
- while (f != l) {
- void * const addr = static_cast<void*>(::boost::move_detail::addressof(*r));
- ::new(addr) input_value_type(::boost::move(*f));
- ++f; ++r;
- }
- }
- BOOST_CATCH(...){
- for (; back != r; ++back){
- back->~input_value_type();
- }
- BOOST_RETHROW;
- }
- BOOST_CATCH_END
- return r;
-}
-
-/// @cond
-/*
-template
- <typename I, // I models InputIterator
- typename F> // F models ForwardIterator
-F uninitialized_move(I f, I l, F r,
- typename ::boost::move_detail::disable_if<has_move_emulation_enabled<typename std::iterator_traits<I>::value_type> >::type* = 0)
-{
- return std::uninitialized_copy(f, l, r);
-}
-*/
-
-//////////////////////////////////////////////////////////////////////////////
-//
// uninitialized_copy_or_move
//
//////////////////////////////////////////////////////////////////////////////
diff --git a/boost/move/core.hpp b/boost/move/core.hpp
index 54aece0b71..c9cbec23a1 100644
--- a/boost/move/core.hpp
+++ b/boost/move/core.hpp
@@ -197,7 +197,7 @@
namespace move_detail {
template <class Ret, class T>
- inline typename ::boost::move_detail::enable_if_c
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
< ::boost::move_detail::is_lvalue_reference<Ret>::value ||
!::boost::has_move_emulation_enabled<T>::value
, T&>::type
@@ -207,7 +207,7 @@
}
template <class Ret, class T>
- inline typename ::boost::move_detail::enable_if_c
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
< !::boost::move_detail::is_lvalue_reference<Ret>::value &&
::boost::has_move_emulation_enabled<T>::value
, ::boost::rv<T>&>::type
@@ -217,7 +217,7 @@
}
template <class Ret, class T>
- inline typename ::boost::move_detail::enable_if_c
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
< !::boost::move_detail::is_lvalue_reference<Ret>::value &&
::boost::has_move_emulation_enabled<T>::value
, ::boost::rv<T>&>::type
@@ -245,9 +245,9 @@
#define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\
BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE)\
public:\
- operator ::boost::rv<TYPE>&() \
+ BOOST_MOVE_FORCEINLINE operator ::boost::rv<TYPE>&() \
{ return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\
- operator const ::boost::rv<TYPE>&() const \
+ BOOST_MOVE_FORCEINLINE operator const ::boost::rv<TYPE>&() const \
{ return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\
private:\
//
@@ -263,18 +263,18 @@
TYPE& operator=(TYPE &t)\
{ this->operator=(const_cast<const TYPE &>(t)); return *this;}\
public:\
- operator ::boost::rv<TYPE>&() \
+ BOOST_MOVE_FORCEINLINE operator ::boost::rv<TYPE>&() \
{ return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\
- operator const ::boost::rv<TYPE>&() const \
+ BOOST_MOVE_FORCEINLINE operator const ::boost::rv<TYPE>&() const \
{ return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\
private:\
//
#define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\
public:\
- operator ::boost::rv<TYPE>&() \
+ BOOST_MOVE_FORCEINLINE operator ::boost::rv<TYPE>&() \
{ return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\
- operator const ::boost::rv<TYPE>&() const \
+ BOOST_MOVE_FORCEINLINE operator const ::boost::rv<TYPE>&() const \
{ return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\
private:\
//
@@ -301,6 +301,7 @@
BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE)\
public:\
typedef int boost_move_emulation_t;\
+ private:\
//
//! This macro marks a type as copyable and movable.
@@ -450,7 +451,7 @@
namespace move_detail {
template <class Ret, class T>
- inline typename ::boost::move_detail::enable_if_c
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
< ::boost::move_detail::is_lvalue_reference<Ret>::value
, T&>::type
move_return(T& x) BOOST_NOEXCEPT
@@ -459,7 +460,7 @@
}
template <class Ret, class T>
- inline typename ::boost::move_detail::enable_if_c
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
< !::boost::move_detail::is_lvalue_reference<Ret>::value
, Ret && >::type
move_return(T&& t) BOOST_NOEXCEPT
diff --git a/boost/move/detail/config_begin.hpp b/boost/move/detail/config_begin.hpp
index 342390b816..637eb158bd 100644
--- a/boost/move/detail/config_begin.hpp
+++ b/boost/move/detail/config_begin.hpp
@@ -16,4 +16,6 @@
# pragma warning (disable : 4324) // structure was padded due to __declspec(align())
# pragma warning (disable : 4675) // "function": resolved overload was found by argument-dependent lookup
# pragma warning (disable : 4996) // "function": was declared deprecated (_CRT_SECURE_NO_DEPRECATE/_SCL_SECURE_NO_WARNINGS)
+# pragma warning (disable : 4714) // "function": marked as __forceinline not inlined
+# pragma warning (disable : 4127) // conditional expression is constant
#endif
diff --git a/boost/move/detail/destruct_n.hpp b/boost/move/detail/destruct_n.hpp
new file mode 100644
index 0000000000..06f1f589ed
--- /dev/null
+++ b/boost/move/detail/destruct_n.hpp
@@ -0,0 +1,67 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2016.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_DETAIL_DESTRUCT_N_HPP
+#define BOOST_MOVE_DETAIL_DESTRUCT_N_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <cstddef>
+
+namespace boost {
+namespace movelib{
+
+template<class T>
+class destruct_n
+{
+ public:
+ explicit destruct_n(T *raw)
+ : m_ptr(raw), m_size()
+ {}
+
+ void incr()
+ {
+ ++m_size;
+ }
+
+ void incr(std::size_t n)
+ {
+ m_size += n;
+ }
+
+ void release()
+ {
+ m_size = 0u;
+ m_ptr = 0;
+ }
+
+ ~destruct_n()
+ {
+ while(m_size--){
+ m_ptr[m_size].~T();
+ }
+ }
+ private:
+ T *m_ptr;
+ std::size_t m_size;
+};
+
+}} //namespace boost { namespace movelib{
+
+#endif //#ifndef BOOST_MOVE_DETAIL_DESTRUCT_N_HPP
diff --git a/boost/move/detail/iterator_traits.hpp b/boost/move/detail/iterator_traits.hpp
index a75ee03827..5ffcb2cf05 100644
--- a/boost/move/detail/iterator_traits.hpp
+++ b/boost/move/detail/iterator_traits.hpp
@@ -23,6 +23,7 @@
#endif
#include <cstddef>
+#include <boost/move/detail/type_traits.hpp>
#include <boost/move/detail/std_ns_begin.hpp>
BOOST_MOVE_STD_NS_BEG
@@ -46,6 +47,7 @@ struct iterator_traits
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
typedef typename Iterator::iterator_category iterator_category;
+ typedef typename boost::move_detail::make_unsigned<difference_type>::type size_type;
};
template<class T>
@@ -56,6 +58,7 @@ struct iterator_traits<T*>
typedef T* pointer;
typedef T& reference;
typedef std::random_access_iterator_tag iterator_category;
+ typedef typename boost::move_detail::make_unsigned<difference_type>::type size_type;
};
template<class T>
@@ -66,6 +69,7 @@ struct iterator_traits<const T*>
typedef const T* pointer;
typedef const T& reference;
typedef std::random_access_iterator_tag iterator_category;
+ typedef typename boost::move_detail::make_unsigned<difference_type>::type size_type;
};
}} //namespace boost { namespace movelib{
diff --git a/boost/move/detail/meta_utils.hpp b/boost/move/detail/meta_utils.hpp
index 323c13af10..e45394c97d 100644
--- a/boost/move/detail/meta_utils.hpp
+++ b/boost/move/detail/meta_utils.hpp
@@ -14,13 +14,11 @@
#ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP
#define BOOST_MOVE_DETAIL_META_UTILS_HPP
-#ifndef BOOST_CONFIG_HPP
-# include <boost/config.hpp>
-#endif
-#
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp> //forceinline
#include <boost/move/detail/meta_utils_core.hpp>
#include <cstddef> //for std::size_t
@@ -245,8 +243,8 @@ template<class T>
struct addr_impl_ref
{
T & v_;
- inline addr_impl_ref( T & v ): v_( v ) {}
- inline operator T& () const { return v_; }
+ BOOST_MOVE_FORCEINLINE addr_impl_ref( T & v ): v_( v ) {}
+ BOOST_MOVE_FORCEINLINE operator T& () const { return v_; }
private:
addr_impl_ref & operator=(const addr_impl_ref &);
@@ -255,18 +253,18 @@ struct addr_impl_ref
template<class T>
struct addressof_impl
{
- static inline T * f( T & v, long )
+ BOOST_MOVE_FORCEINLINE static T * f( T & v, long )
{
return reinterpret_cast<T*>(
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
}
- static inline T * f( T * v, int )
+ BOOST_MOVE_FORCEINLINE static T * f( T * v, int )
{ return v; }
};
template<class T>
-inline T * addressof( T & v )
+BOOST_MOVE_FORCEINLINE T * addressof( T & v )
{
return ::boost::move_detail::addressof_impl<T>::f
( ::boost::move_detail::addr_impl_ref<T>( v ), 0 );
@@ -314,6 +312,17 @@ class is_convertible
#endif
+template <class T, class U, bool IsSame = is_same<T, U>::value>
+struct is_same_or_convertible
+ : is_convertible<T, U>
+{};
+
+template <class T, class U>
+struct is_same_or_convertible<T, U, true>
+{
+ static const bool value = true;
+};
+
template<
bool C
, typename F1
@@ -347,6 +356,16 @@ struct disable_if_convertible
: disable_if< is_convertible<T, U>, R>
{};
+template<class T, class U, class R = void>
+struct enable_if_same_or_convertible
+ : enable_if< is_same_or_convertible<T, U>, R>
+{};
+
+template<class T, class U, class R = void>
+struct disable_if_same_or_convertible
+ : disable_if< is_same_or_convertible<T, U>, R>
+{};
+
//////////////////////////////////////////////////////////////////////////////
//
// and_
@@ -561,4 +580,6 @@ template< class T > struct remove_rvalue_reference { typedef T type; };
} //namespace move_detail {
} //namespace boost {
+#include <boost/move/detail/config_end.hpp>
+
#endif //#ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP
diff --git a/boost/move/detail/move_helpers.hpp b/boost/move/detail/move_helpers.hpp
index 7b62e26994..a2502bf7dc 100644
--- a/boost/move/detail/move_helpers.hpp
+++ b/boost/move/detail/move_helpers.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2010-2012.
+// (C) Copyright Ion Gaztanaga 2010-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -20,8 +20,9 @@
# pragma once
#endif
+#include <boost/move/core.hpp>
#include <boost/move/utility_core.hpp>
-#include <boost/move/detail/meta_utils.hpp>
+#include <boost/move/detail/type_traits.hpp>
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
@@ -43,6 +44,30 @@
////////////////////////////////////////
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+ template<class RETURN_VALUE, class BOOST_MOVE_TEMPL_PARAM, class TYPE>
+ struct boost_move_conversion_aware_catch_1
+ : public ::boost::move_detail::enable_if_and
+ < RETURN_VALUE
+ , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>
+ , ::boost::move_detail::is_class<TYPE>
+ , ::boost::has_move_emulation_disabled<BOOST_MOVE_TEMPL_PARAM>
+ >
+ {};
+
+ template<class RETURN_VALUE, class BOOST_MOVE_TEMPL_PARAM, class TYPE>
+ struct boost_move_conversion_aware_catch_2
+ : public ::boost::move_detail::disable_if_or
+ < RETURN_VALUE
+ , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>
+ , ::boost::move_detail::is_rv_impl<BOOST_MOVE_TEMPL_PARAM>
+ , ::boost::move_detail::and_
+ < ::boost::move_detail::is_rv_impl<BOOST_MOVE_TEMPL_PARAM>
+ , ::boost::move_detail::is_class<BOOST_MOVE_TEMPL_PARAM>
+ >
+ >
+ {};
+
#define BOOST_MOVE_CONVERSION_AWARE_CATCH_COMMON(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION)\
RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_CONST(TYPE) x)\
{ return FWD_FUNCTION(static_cast<const TYPE&>(x)); }\
@@ -59,26 +84,14 @@
\
template<class BOOST_MOVE_TEMPL_PARAM>\
RETURN_VALUE PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u,\
- typename ::boost::move_detail::enable_if_and\
- < ::boost::move_detail::nat \
- , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>\
- , ::boost::move_detail::is_class<TYPE>\
- , ::boost::has_move_emulation_disabled<BOOST_MOVE_TEMPL_PARAM>\
- >::type* = 0)\
+ typename boost_move_conversion_aware_catch_1< ::boost::move_detail::nat, BOOST_MOVE_TEMPL_PARAM, TYPE>::type* = 0)\
{ return FWD_FUNCTION(u); }\
\
template<class BOOST_MOVE_TEMPL_PARAM>\
RETURN_VALUE PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u,\
- typename ::boost::move_detail::disable_if_or\
- < ::boost::move_detail::nat \
- , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM> \
- , ::boost::move_detail::and_ \
- < ::boost::move_detail::is_rv<BOOST_MOVE_TEMPL_PARAM> \
- , ::boost::move_detail::is_class<BOOST_MOVE_TEMPL_PARAM> \
- > \
- >::type* = 0)\
+ typename boost_move_conversion_aware_catch_2< ::boost::move_detail::nat, BOOST_MOVE_TEMPL_PARAM, TYPE>::type* = 0)\
{\
- TYPE t(u);\
+ TYPE t((u));\
return FWD_FUNCTION(::boost::move(t));\
}\
//
@@ -87,27 +100,15 @@
BOOST_MOVE_CONVERSION_AWARE_CATCH_COMMON(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION)\
\
template<class BOOST_MOVE_TEMPL_PARAM>\
- typename ::boost::move_detail::enable_if_and\
- < RETURN_VALUE \
- , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>\
- , ::boost::move_detail::is_class<TYPE>\
- , ::boost::has_move_emulation_disabled<BOOST_MOVE_TEMPL_PARAM>\
- >::type\
+ typename boost_move_conversion_aware_catch_1<RETURN_VALUE, BOOST_MOVE_TEMPL_PARAM, TYPE>::type\
PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u)\
{ return FWD_FUNCTION(u); }\
\
template<class BOOST_MOVE_TEMPL_PARAM>\
- typename ::boost::move_detail::disable_if_or\
- < RETURN_VALUE \
- , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM> \
- , ::boost::move_detail::and_ \
- < ::boost::move_detail::is_rv<BOOST_MOVE_TEMPL_PARAM> \
- , ::boost::move_detail::is_class<BOOST_MOVE_TEMPL_PARAM> \
- > \
- >::type\
+ typename boost_move_conversion_aware_catch_2<RETURN_VALUE, BOOST_MOVE_TEMPL_PARAM, TYPE>::type\
PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u)\
{\
- TYPE t(u);\
+ TYPE t((u));\
return FWD_FUNCTION(::boost::move(t));\
}\
//
@@ -127,7 +128,7 @@
, RETURN_VALUE >::type\
PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u)\
{\
- TYPE t(u);\
+ TYPE t((u));\
return FWD_FUNCTION(::boost::move(t));\
}\
//
@@ -151,6 +152,27 @@
////////////////////////////////////////
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+ template<class RETURN_VALUE, class BOOST_MOVE_TEMPL_PARAM, class UNLESS_CONVERTIBLE_TO, class TYPE>
+ struct boost_move_conversion_aware_catch_1arg_1
+ : public ::boost::move_detail::enable_if_and
+ < RETURN_VALUE
+ , ::boost::move_detail::not_< ::boost::move_detail::is_same_or_convertible<BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO> >
+ , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>
+ , ::boost::has_move_emulation_disabled<BOOST_MOVE_TEMPL_PARAM>
+ >
+ {};
+
+ template<class RETURN_VALUE, class BOOST_MOVE_TEMPL_PARAM, class UNLESS_CONVERTIBLE_TO, class TYPE>
+ struct boost_move_conversion_aware_catch_1arg_2
+ : public ::boost::move_detail::disable_if_or
+ < RETURN_VALUE
+ , ::boost::move_detail::is_same_or_convertible< BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO>
+ , ::boost::move_detail::is_rv_impl<BOOST_MOVE_TEMPL_PARAM>
+ , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>
+ >
+ {};
+
#define BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG_COMMON(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\
RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_CONST(TYPE) x)\
{ return FWD_FUNCTION(arg1, static_cast<const TYPE&>(x)); }\
@@ -167,23 +189,14 @@
\
template<class BOOST_MOVE_TEMPL_PARAM>\
RETURN_VALUE PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u,\
- typename ::boost::move_detail::enable_if_and\
- < ::boost::move_detail::nat \
- , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>\
- , ::boost::has_move_emulation_disabled<BOOST_MOVE_TEMPL_PARAM>\
- >::type* = 0)\
+ typename boost_move_conversion_aware_catch_1arg_1<void, BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO, TYPE>::type* = 0)\
{ return FWD_FUNCTION(arg1, u); }\
\
template<class BOOST_MOVE_TEMPL_PARAM>\
RETURN_VALUE PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u,\
- typename ::boost::move_detail::disable_if_or\
- < void \
- , ::boost::move_detail::is_rv<BOOST_MOVE_TEMPL_PARAM>\
- , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>\
- , ::boost::move_detail::is_convertible<BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO>\
- >::type* = 0)\
+ typename boost_move_conversion_aware_catch_1arg_2<void, BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO, TYPE>::type* = 0)\
{\
- TYPE t(u);\
+ TYPE t((u));\
return FWD_FUNCTION(arg1, ::boost::move(t));\
}\
//
@@ -192,24 +205,15 @@
BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG_COMMON(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\
\
template<class BOOST_MOVE_TEMPL_PARAM>\
- typename ::boost::move_detail::enable_if_and\
- < RETURN_VALUE \
- , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>\
- , ::boost::has_move_emulation_disabled<BOOST_MOVE_TEMPL_PARAM>\
- >::type\
+ typename boost_move_conversion_aware_catch_1arg_1<RETURN_VALUE, BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO, TYPE>::type\
PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u)\
{ return FWD_FUNCTION(arg1, u); }\
\
template<class BOOST_MOVE_TEMPL_PARAM>\
- typename ::boost::move_detail::disable_if_or\
- < RETURN_VALUE \
- , ::boost::move_detail::is_rv<BOOST_MOVE_TEMPL_PARAM>\
- , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>\
- , ::boost::move_detail::is_convertible<BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO>\
- >::type\
+ typename boost_move_conversion_aware_catch_1arg_2<RETURN_VALUE, BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO, TYPE>::type\
PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u)\
{\
- TYPE t(u);\
+ TYPE t((u));\
return FWD_FUNCTION(arg1, ::boost::move(t));\
}\
//
@@ -228,11 +232,11 @@
typename ::boost::move_detail::disable_if_or\
< RETURN_VALUE \
, ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM> \
- , ::boost::move_detail::is_convertible<BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO> \
+ , ::boost::move_detail::is_same_or_convertible<BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO> \
>::type\
PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u)\
{\
- TYPE t(u);\
+ TYPE t((u));\
return FWD_FUNCTION(arg1, ::boost::move(t));\
}\
//
diff --git a/boost/move/detail/placement_new.hpp b/boost/move/detail/placement_new.hpp
new file mode 100644
index 0000000000..69d33328cf
--- /dev/null
+++ b/boost/move/detail/placement_new.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_MOVE_DETAIL_PLACEMENT_NEW_HPP
+#define BOOST_MOVE_DETAIL_PLACEMENT_NEW_HPP
+///////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2014-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+struct boost_move_new_t{};
+
+//avoid including <new>
+inline void *operator new(std::size_t, void *p, boost_move_new_t)
+{ return p; }
+
+inline void operator delete(void *, void *, boost_move_new_t)
+{}
+
+#endif //BOOST_MOVE_DETAIL_PLACEMENT_NEW_HPP
diff --git a/boost/move/detail/workaround.hpp b/boost/move/detail/workaround.hpp
index b3f81b117f..befe141e96 100644
--- a/boost/move/detail/workaround.hpp
+++ b/boost/move/detail/workaround.hpp
@@ -52,4 +52,17 @@
#define BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG
#endif
+#define BOOST_MOVE_DISABLE_FORCEINLINE
+
+#if defined(BOOST_MOVE_DISABLE_FORCEINLINE)
+ #define BOOST_MOVE_FORCEINLINE inline
+#elif defined(BOOST_MOVE_FORCEINLINE_IS_BOOST_FORCELINE)
+ #define BOOST_MOVE_FORCEINLINE BOOST_FORCEINLINE
+#elif defined(BOOST_MSVC) && defined(_DEBUG)
+ //"__forceinline" and MSVC seems to have some bugs in debug mode
+ #define BOOST_MOVE_FORCEINLINE inline
+#else
+ #define BOOST_MOVE_FORCEINLINE BOOST_FORCEINLINE
+#endif
+
#endif //#ifndef BOOST_MOVE_DETAIL_WORKAROUND_HPP
diff --git a/boost/move/iterator.hpp b/boost/move/iterator.hpp
index 1b39e267ec..f36df23c0c 100644
--- a/boost/move/iterator.hpp
+++ b/boost/move/iterator.hpp
@@ -23,6 +23,7 @@
#endif
#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp> //forceinline
#include <boost/move/detail/iterator_traits.hpp>
#include <boost/move/utility_core.hpp>
@@ -57,22 +58,20 @@ class move_iterator
typedef typename boost::movelib::iterator_traits<iterator_type>::difference_type difference_type;
typedef typename boost::movelib::iterator_traits<iterator_type>::iterator_category iterator_category;
- move_iterator()
+ BOOST_MOVE_FORCEINLINE move_iterator()
+ : m_it()
{}
- explicit move_iterator(It i)
+ BOOST_MOVE_FORCEINLINE explicit move_iterator(const It &i)
: m_it(i)
{}
template <class U>
- move_iterator(const move_iterator<U>& u)
- : m_it(u.base())
+ BOOST_MOVE_FORCEINLINE move_iterator(const move_iterator<U>& u)
+ : m_it(u.m_it)
{}
- iterator_type base() const
- { return m_it; }
-
- reference operator*() const
+ BOOST_MOVE_FORCEINLINE reference operator*() const
{
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
return *m_it;
@@ -81,34 +80,34 @@ class move_iterator
#endif
}
- pointer operator->() const
+ BOOST_MOVE_FORCEINLINE pointer operator->() const
{ return m_it; }
- move_iterator& operator++()
+ BOOST_MOVE_FORCEINLINE move_iterator& operator++()
{ ++m_it; return *this; }
- move_iterator<iterator_type> operator++(int)
+ BOOST_MOVE_FORCEINLINE move_iterator<iterator_type> operator++(int)
{ move_iterator<iterator_type> tmp(*this); ++(*this); return tmp; }
- move_iterator& operator--()
+ BOOST_MOVE_FORCEINLINE move_iterator& operator--()
{ --m_it; return *this; }
- move_iterator<iterator_type> operator--(int)
+ BOOST_MOVE_FORCEINLINE move_iterator<iterator_type> operator--(int)
{ move_iterator<iterator_type> tmp(*this); --(*this); return tmp; }
move_iterator<iterator_type> operator+ (difference_type n) const
{ return move_iterator<iterator_type>(m_it + n); }
- move_iterator& operator+=(difference_type n)
+ BOOST_MOVE_FORCEINLINE move_iterator& operator+=(difference_type n)
{ m_it += n; return *this; }
- move_iterator<iterator_type> operator- (difference_type n) const
+ BOOST_MOVE_FORCEINLINE move_iterator<iterator_type> operator- (difference_type n) const
{ return move_iterator<iterator_type>(m_it - n); }
- move_iterator& operator-=(difference_type n)
+ BOOST_MOVE_FORCEINLINE move_iterator& operator-=(difference_type n)
{ m_it -= n; return *this; }
- reference operator[](difference_type n) const
+ BOOST_MOVE_FORCEINLINE reference operator[](difference_type n) const
{
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
return m_it[n];
@@ -117,29 +116,29 @@ class move_iterator
#endif
}
- friend bool operator==(const move_iterator& x, const move_iterator& y)
- { return x.base() == y.base(); }
+ BOOST_MOVE_FORCEINLINE friend bool operator==(const move_iterator& x, const move_iterator& y)
+ { return x.m_it == y.m_it; }
- friend bool operator!=(const move_iterator& x, const move_iterator& y)
- { return x.base() != y.base(); }
+ BOOST_MOVE_FORCEINLINE friend bool operator!=(const move_iterator& x, const move_iterator& y)
+ { return x.m_it != y.m_it; }
- friend bool operator< (const move_iterator& x, const move_iterator& y)
- { return x.base() < y.base(); }
+ BOOST_MOVE_FORCEINLINE friend bool operator< (const move_iterator& x, const move_iterator& y)
+ { return x.m_it < y.m_it; }
- friend bool operator<=(const move_iterator& x, const move_iterator& y)
- { return x.base() <= y.base(); }
+ BOOST_MOVE_FORCEINLINE friend bool operator<=(const move_iterator& x, const move_iterator& y)
+ { return x.m_it <= y.m_it; }
- friend bool operator> (const move_iterator& x, const move_iterator& y)
- { return x.base() > y.base(); }
+ BOOST_MOVE_FORCEINLINE friend bool operator> (const move_iterator& x, const move_iterator& y)
+ { return x.m_it > y.m_it; }
- friend bool operator>=(const move_iterator& x, const move_iterator& y)
- { return x.base() >= y.base(); }
+ BOOST_MOVE_FORCEINLINE friend bool operator>=(const move_iterator& x, const move_iterator& y)
+ { return x.m_it >= y.m_it; }
- friend difference_type operator-(const move_iterator& x, const move_iterator& y)
- { return x.base() - y.base(); }
+ BOOST_MOVE_FORCEINLINE friend difference_type operator-(const move_iterator& x, const move_iterator& y)
+ { return x.m_it - y.m_it; }
- friend move_iterator operator+(difference_type n, const move_iterator& x)
- { return move_iterator(x.base() + n); }
+ BOOST_MOVE_FORCEINLINE friend move_iterator operator+(difference_type n, const move_iterator& x)
+ { return move_iterator(x.m_it + n); }
private:
It m_it;
diff --git a/boost/move/unique_ptr.hpp b/boost/move/unique_ptr.hpp
index 5b067436af..2d794e8ed5 100644
--- a/boost/move/unique_ptr.hpp
+++ b/boost/move/unique_ptr.hpp
@@ -20,7 +20,7 @@
#endif
#include <boost/move/detail/config_begin.hpp>
-#include <boost/move/detail/workaround.hpp>
+#include <boost/move/detail/workaround.hpp> //forceinline
#include <boost/move/detail/unique_ptr_meta_utils.hpp>
#include <boost/move/default_delete.hpp>
#include <boost/move/utility_core.hpp>
@@ -93,25 +93,25 @@ struct unique_ptr_data
typedef typename deleter_types<D>::del_ref del_ref;
typedef typename deleter_types<D>::del_cref del_cref;
- unique_ptr_data() BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE unique_ptr_data() BOOST_NOEXCEPT
: m_p(), d()
{}
- explicit unique_ptr_data(P p) BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE explicit unique_ptr_data(P p) BOOST_NOEXCEPT
: m_p(p), d()
{}
- unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT
: m_p(p), d(d1)
{}
template <class U>
- unique_ptr_data(P p, BOOST_FWD_REF(U) d1) BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE unique_ptr_data(P p, BOOST_FWD_REF(U) d1) BOOST_NOEXCEPT
: m_p(p), d(::boost::forward<U>(d1))
{}
- del_ref deleter() { return d; }
- del_cref deleter() const{ return d; }
+ BOOST_MOVE_FORCEINLINE del_ref deleter() { return d; }
+ BOOST_MOVE_FORCEINLINE del_cref deleter() const{ return d; }
P m_p;
D d;
@@ -129,25 +129,25 @@ struct unique_ptr_data<P, D, false>
typedef typename deleter_types<D>::del_ref del_ref;
typedef typename deleter_types<D>::del_cref del_cref;
- unique_ptr_data() BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE unique_ptr_data() BOOST_NOEXCEPT
: D(), m_p()
{}
- explicit unique_ptr_data(P p) BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE explicit unique_ptr_data(P p) BOOST_NOEXCEPT
: D(), m_p(p)
{}
- unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT
: D(d1), m_p(p)
{}
template <class U>
- unique_ptr_data(P p, BOOST_FWD_REF(U) d) BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE unique_ptr_data(P p, BOOST_FWD_REF(U) d) BOOST_NOEXCEPT
: D(::boost::forward<U>(d)), m_p(p)
{}
- del_ref deleter() BOOST_NOEXCEPT { return static_cast<del_ref>(*this); }
- del_cref deleter() const BOOST_NOEXCEPT { return static_cast<del_cref>(*this); }
+ BOOST_MOVE_FORCEINLINE del_ref deleter() BOOST_NOEXCEPT { return static_cast<del_ref>(*this); }
+ BOOST_MOVE_FORCEINLINE del_cref deleter() const BOOST_NOEXCEPT { return static_cast<del_cref>(*this); }
P m_p;
@@ -389,7 +389,7 @@ class unique_ptr
//!
//! <b>Remarks</b>: If this constructor is instantiated with a pointer type or reference type
//! for the template argument D, the program is ill-formed.
- BOOST_CONSTEXPR unique_ptr() BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE BOOST_CONSTEXPR unique_ptr() BOOST_NOEXCEPT
: m_data()
{
//If this constructor is instantiated with a pointer type or reference type
@@ -400,7 +400,7 @@ class unique_ptr
//! <b>Effects</b>: Same as <tt>unique_ptr()</tt> (default constructor).
//!
- BOOST_CONSTEXPR unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE BOOST_CONSTEXPR unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
: m_data()
{
//If this constructor is instantiated with a pointer type or reference type
@@ -423,7 +423,7 @@ class unique_ptr
//! - If T is not an array type and Pointer is implicitly convertible to pointer.
//! - If T is an array type and Pointer is a more CV qualified pointer to element_type.
template<class Pointer>
- explicit unique_ptr(Pointer p
+ BOOST_MOVE_FORCEINLINE explicit unique_ptr(Pointer p
BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer>::type* =0)
) BOOST_NOEXCEPT
: m_data(p)
@@ -461,7 +461,7 @@ class unique_ptr
//! - If T is not an array type and Pointer is implicitly convertible to pointer.
//! - If T is an array type and Pointer is a more CV qualified pointer to element_type.
template<class Pointer>
- unique_ptr(Pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type1) d1
+ BOOST_MOVE_FORCEINLINE unique_ptr(Pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type1) d1
BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer>::type* =0)
) BOOST_NOEXCEPT
: m_data(p, d1)
@@ -474,7 +474,7 @@ class unique_ptr
//! <b>Effects</b>: Same effects as <tt>template<class Pointer> unique_ptr(Pointer p, deleter_arg_type1 d1)</tt>
//! and additionally <tt>get() == nullptr</tt>
- unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type1) d1) BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type1) d1) BOOST_NOEXCEPT
: m_data(pointer(), d1)
{}
@@ -499,7 +499,7 @@ class unique_ptr
//! - If T is not an array type and Pointer is implicitly convertible to pointer.
//! - If T is an array type and Pointer is a more CV qualified pointer to element_type.
template<class Pointer>
- unique_ptr(Pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type2) d2
+ BOOST_MOVE_FORCEINLINE unique_ptr(Pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type2) d2
BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer>::type* =0)
) BOOST_NOEXCEPT
: m_data(p, ::boost::move(d2))
@@ -512,7 +512,7 @@ class unique_ptr
//! <b>Effects</b>: Same effects as <tt>template<class Pointer> unique_ptr(Pointer p, deleter_arg_type2 d2)</tt>
//! and additionally <tt>get() == nullptr</tt>
- unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type2) d2) BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type2) d2) BOOST_NOEXCEPT
: m_data(pointer(), ::boost::move(d2))
{}
@@ -526,7 +526,7 @@ class unique_ptr
//! <b>Postconditions</b>: <tt>get()</tt> yields the value u.get() yielded before the construction. <tt>get_deleter()</tt>
//! returns a reference to the stored deleter that was constructed from u.get_deleter(). If D is a
//! reference type then <tt>get_deleter()</tt> and <tt>u.get_deleter()</tt> both reference the same lvalue deleter.
- unique_ptr(BOOST_RV_REF(unique_ptr) u) BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE unique_ptr(BOOST_RV_REF(unique_ptr) u) BOOST_NOEXCEPT
: m_data(u.release(), ::boost::move_if_not_lvalue_reference<D>(u.get_deleter()))
{}
@@ -546,7 +546,7 @@ class unique_ptr
//! <b>Postconditions</b>: <tt>get()</tt> yields the value <tt>u.get()</tt> yielded before the construction. <tt>get_deleter()</tt>
//! returns a reference to the stored deleter that was constructed from <tt>u.get_deleter()</tt>.
template <class U, class E>
- unique_ptr( BOOST_RV_REF_BEG_IF_CXX11 unique_ptr<U, E> BOOST_RV_REF_END_IF_CXX11 u
+ BOOST_MOVE_FORCEINLINE unique_ptr( BOOST_RV_REF_BEG_IF_CXX11 unique_ptr<U, E> BOOST_RV_REF_END_IF_CXX11 u
BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_moveconv_constr<T BOOST_MOVE_I D BOOST_MOVE_I U BOOST_MOVE_I E>::type* =0)
) BOOST_NOEXCEPT
: m_data(u.release(), ::boost::move_if_not_lvalue_reference<E>(u.get_deleter()))
@@ -629,7 +629,7 @@ class unique_ptr
//! <b>Returns</b>: <tt>get()[i]</tt>.
//!
//! <b>Remarks</b: If T is not an array type, the program is ill-formed.
- BOOST_MOVE_DOC1ST(element_type&, typename bmupmu::add_lvalue_reference<element_type>::type)
+ BOOST_MOVE_FORCEINLINE BOOST_MOVE_DOC1ST(element_type&, typename bmupmu::add_lvalue_reference<element_type>::type)
operator[](std::size_t i) const BOOST_NOEXCEPT
{
BOOST_ASSERT( bmupmu::extent<T>::value == 0 || i < bmupmu::extent<T>::value );
@@ -644,7 +644,7 @@ class unique_ptr
//! <b>Note</b>: use typically requires that T be a complete type.
//!
//! <b>Remarks</b: If T is an array type, the program is ill-formed.
- pointer operator->() const BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT((!bmupmu::is_array<T>::value));
BOOST_ASSERT(m_data.m_p);
@@ -653,27 +653,27 @@ class unique_ptr
//! <b>Returns</b>: The stored pointer.
//!
- pointer get() const BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE pointer get() const BOOST_NOEXCEPT
{ return m_data.m_p; }
//! <b>Returns</b>: A reference to the stored deleter.
//!
- BOOST_MOVE_DOC1ST(D&, typename bmupmu::add_lvalue_reference<D>::type)
+ BOOST_MOVE_FORCEINLINE BOOST_MOVE_DOC1ST(D&, typename bmupmu::add_lvalue_reference<D>::type)
get_deleter() BOOST_NOEXCEPT
{ return m_data.deleter(); }
//! <b>Returns</b>: A reference to the stored deleter.
//!
- BOOST_MOVE_DOC1ST(const D&, typename bmupmu::add_const_lvalue_reference<D>::type)
+ BOOST_MOVE_FORCEINLINE BOOST_MOVE_DOC1ST(const D&, typename bmupmu::add_const_lvalue_reference<D>::type)
get_deleter() const BOOST_NOEXCEPT
{ return m_data.deleter(); }
#ifdef BOOST_MOVE_DOXYGEN_INVOKED
//! <b>Returns</b>: Returns: get() != nullptr.
//!
- explicit operator bool
+ BOOST_MOVE_FORCEINLINE explicit operator bool
#else
- operator bmupd::explicit_bool_arg
+ BOOST_MOVE_FORCEINLINE operator bmupd::explicit_bool_arg
#endif
()const BOOST_NOEXCEPT
{
@@ -685,7 +685,7 @@ class unique_ptr
//! <b>Postcondition</b>: <tt>get() == nullptr</tt>.
//!
//! <b>Returns</b>: The value <tt>get()</tt> had at the start of the call to release.
- pointer release() BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE pointer release() BOOST_NOEXCEPT
{
const pointer tmp = m_data.m_p;
m_data.m_p = pointer();
@@ -748,19 +748,19 @@ class unique_ptr
//! <b>Effects</b>: Calls <tt>x.swap(y)</tt>.
//!
template <class T, class D>
-inline void swap(unique_ptr<T, D> &x, unique_ptr<T, D> &y) BOOST_NOEXCEPT
+BOOST_MOVE_FORCEINLINE void swap(unique_ptr<T, D> &x, unique_ptr<T, D> &y) BOOST_NOEXCEPT
{ x.swap(y); }
//! <b>Returns</b>: <tt>x.get() == y.get()</tt>.
//!
template <class T1, class D1, class T2, class D2>
-inline bool operator==(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
+BOOST_MOVE_FORCEINLINE bool operator==(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
{ return x.get() == y.get(); }
//! <b>Returns</b>: <tt>x.get() != y.get()</tt>.
//!
template <class T1, class D1, class T2, class D2>
-inline bool operator!=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
+BOOST_MOVE_FORCEINLINE bool operator!=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
{ return x.get() != y.get(); }
//! <b>Returns</b>: x.get() < y.get().
@@ -768,99 +768,99 @@ inline bool operator!=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
//! <b>Remarks</b>: This comparison shall induce a
//! strict weak ordering betwen pointers.
template <class T1, class D1, class T2, class D2>
-inline bool operator<(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
+BOOST_MOVE_FORCEINLINE bool operator<(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
{ return x.get() < y.get(); }
//! <b>Returns</b>: !(y < x).
//!
template <class T1, class D1, class T2, class D2>
-inline bool operator<=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
+BOOST_MOVE_FORCEINLINE bool operator<=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
{ return !(y < x); }
//! <b>Returns</b>: y < x.
//!
template <class T1, class D1, class T2, class D2>
-inline bool operator>(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
+BOOST_MOVE_FORCEINLINE bool operator>(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
{ return y < x; }
//! <b>Returns</b>:!(x < y).
//!
template <class T1, class D1, class T2, class D2>
-inline bool operator>=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
+BOOST_MOVE_FORCEINLINE bool operator>=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
{ return !(x < y); }
//! <b>Returns</b>:!x.
//!
template <class T, class D>
-inline bool operator==(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
+BOOST_MOVE_FORCEINLINE bool operator==(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
{ return !x; }
//! <b>Returns</b>:!x.
//!
template <class T, class D>
-inline bool operator==(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x) BOOST_NOEXCEPT
+BOOST_MOVE_FORCEINLINE bool operator==(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x) BOOST_NOEXCEPT
{ return !x; }
//! <b>Returns</b>: (bool)x.
//!
template <class T, class D>
-inline bool operator!=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
+BOOST_MOVE_FORCEINLINE bool operator!=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
{ return !!x; }
//! <b>Returns</b>: (bool)x.
//!
template <class T, class D>
-inline bool operator!=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x) BOOST_NOEXCEPT
+BOOST_MOVE_FORCEINLINE bool operator!=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x) BOOST_NOEXCEPT
{ return !!x; }
//! <b>Requires</b>: <tt>operator </tt> shall induce a strict weak ordering on unique_ptr<T, D>::pointer values.
//!
//! <b>Returns</b>: Returns <tt>x.get() < pointer()</tt>.
template <class T, class D>
-inline bool operator<(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
+BOOST_MOVE_FORCEINLINE bool operator<(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
{ return x.get() < typename unique_ptr<T, D>::pointer(); }
//! <b>Requires</b>: <tt>operator </tt> shall induce a strict weak ordering on unique_ptr<T, D>::pointer values.
//!
//! <b>Returns</b>: Returns <tt>pointer() < x.get()</tt>.
template <class T, class D>
-inline bool operator<(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
+BOOST_MOVE_FORCEINLINE bool operator<(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
{ return typename unique_ptr<T, D>::pointer() < x.get(); }
//! <b>Returns</b>: <tt>nullptr < x</tt>.
//!
template <class T, class D>
-inline bool operator>(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
+BOOST_MOVE_FORCEINLINE bool operator>(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
{ return x.get() > typename unique_ptr<T, D>::pointer(); }
//! <b>Returns</b>: <tt>x < nullptr</tt>.
//!
template <class T, class D>
-inline bool operator>(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
+BOOST_MOVE_FORCEINLINE bool operator>(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
{ return typename unique_ptr<T, D>::pointer() > x.get(); }
//! <b>Returns</b>: <tt>!(nullptr < x)</tt>.
//!
template <class T, class D>
-inline bool operator<=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
+BOOST_MOVE_FORCEINLINE bool operator<=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
{ return !(bmupd::nullptr_type() < x); }
//! <b>Returns</b>: <tt>!(x < nullptr)</tt>.
//!
template <class T, class D>
-inline bool operator<=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
+BOOST_MOVE_FORCEINLINE bool operator<=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
{ return !(x < bmupd::nullptr_type()); }
//! <b>Returns</b>: <tt>!(x < nullptr)</tt>.
//!
template <class T, class D>
-inline bool operator>=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
+BOOST_MOVE_FORCEINLINE bool operator>=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
{ return !(x < bmupd::nullptr_type()); }
//! <b>Returns</b>: <tt>!(nullptr < x)</tt>.
//!
template <class T, class D>
-inline bool operator>=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
+BOOST_MOVE_FORCEINLINE bool operator>=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
{ return !(bmupd::nullptr_type() < x); }
} //namespace movelib {
diff --git a/boost/move/utility.hpp b/boost/move/utility.hpp
index 8f9c20b65f..28de7935c8 100644
--- a/boost/move/utility.hpp
+++ b/boost/move/utility.hpp
@@ -25,6 +25,7 @@
#endif
#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp> //forceinline
#include <boost/move/utility_core.hpp>
#include <boost/move/traits.hpp>
@@ -39,7 +40,7 @@
//////////////////////////////////////////////////////////////////////////////
template <class T>
- inline typename ::boost::move_detail::enable_if_c
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
< enable_move_utility_emulation<T>::value && !has_move_emulation_enabled<T>::value
, typename ::boost::move_detail::add_const<T>::type &
>::type
@@ -49,7 +50,7 @@
}
template <class T>
- inline typename ::boost::move_detail::enable_if_c
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
< enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value
&& ::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value, rv<T>&>::type
move_if_noexcept(T& x) BOOST_NOEXCEPT
@@ -58,7 +59,7 @@
}
template <class T>
- inline typename ::boost::move_detail::enable_if_c
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
< enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value
&& ::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value
, rv<T>&
@@ -69,7 +70,7 @@
}
template <class T>
- inline typename ::boost::move_detail::enable_if_c
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
< enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value
&& !::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value
, typename ::boost::move_detail::add_const<T>::type &
@@ -80,7 +81,7 @@
}
template <class T>
- inline typename ::boost::move_detail::enable_if_c
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
< enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value
&& !::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value
, typename ::boost::move_detail::add_const<T>::type &
@@ -125,13 +126,13 @@
#else //BOOST_MOVE_DOXYGEN_INVOKED
template <class T>
- typename ::boost::move_detail::enable_if_c
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
< ::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value, T&&>::type
move_if_noexcept(T& x) BOOST_NOEXCEPT
{ return ::boost::move(x); }
template <class T>
- typename ::boost::move_detail::enable_if_c
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
< !::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value, const T&>::type
move_if_noexcept(T& x) BOOST_NOEXCEPT
{ return x; }
diff --git a/boost/move/utility_core.hpp b/boost/move/utility_core.hpp
index 7fd1ea1443..55042a9bb1 100644
--- a/boost/move/utility_core.hpp
+++ b/boost/move/utility_core.hpp
@@ -26,6 +26,7 @@
#endif
#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp> //forceinline
#include <boost/move/core.hpp>
#include <boost/move/detail/meta_utils.hpp>
#include <boost/static_assert.hpp>
@@ -47,7 +48,7 @@
//////////////////////////////////////////////////////////////////////////////
template <class T>
- inline typename ::boost::move_detail::enable_if_and
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
< T &
, enable_move_utility_emulation<T>
, has_move_emulation_disabled<T>
@@ -58,7 +59,7 @@
}
template <class T>
- inline typename ::boost::move_detail::enable_if_and
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
< rv<T>&
, enable_move_utility_emulation<T>
, has_move_emulation_enabled<T>
@@ -69,7 +70,7 @@
}
template <class T>
- inline typename ::boost::move_detail::enable_if_and
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
< rv<T>&
, enable_move_utility_emulation<T>
, has_move_emulation_enabled<T>
@@ -86,7 +87,7 @@
//////////////////////////////////////////////////////////////////////////////
template <class T>
- inline typename ::boost::move_detail::enable_if_and
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
< T &
, enable_move_utility_emulation<T>
, ::boost::move_detail::is_rv<T>
@@ -97,7 +98,7 @@
}
template <class T>
- inline typename ::boost::move_detail::enable_if_and
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
< const T &
, enable_move_utility_emulation<T>
, ::boost::move_detail::is_not_rv<T>
@@ -114,7 +115,7 @@
//////////////////////////////////////////////////////////////////////////////
template <class T>
- inline typename ::boost::move_detail::enable_if_and
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
< T &
, enable_move_utility_emulation<T>
, ::boost::move_detail::is_rv<T>
@@ -125,7 +126,7 @@
}
template <class T>
- inline typename ::boost::move_detail::enable_if_and
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
< typename ::boost::move_detail::add_lvalue_reference<T>::type
, enable_move_utility_emulation<T>
, ::boost::move_detail::is_not_rv<T>
@@ -140,7 +141,7 @@
}
template <class T>
- inline typename ::boost::move_detail::enable_if_and
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
< rv<T>&
, enable_move_utility_emulation<T>
, ::boost::move_detail::is_not_rv<T>
@@ -202,13 +203,13 @@
//Old move approach, lvalues could bind to rvalue references
template <class T>
- inline typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
{ return t; }
#else //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
template <class T>
- inline typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
{ return static_cast<typename ::boost::move_detail::remove_reference<T>::type &&>(t); }
#endif //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
@@ -238,17 +239,17 @@
//Old move approach, lvalues could bind to rvalue references
template <class T>
- inline T&& forward(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE T&& forward(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT
{ return t; }
#else //Old move
template <class T>
- inline T&& forward(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE T&& forward(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
{ return static_cast<T&&>(t); }
template <class T>
- inline T&& forward(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE T&& forward(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
{
//"boost::forward<T> error: 'T' is a lvalue reference, can't forward as rvalue.";
BOOST_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference<T>::value);
@@ -273,17 +274,17 @@
//Old move approach, lvalues could bind to rvalue references
template <class T>
- inline T&& move_if_not_lvalue_reference(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE T&& move_if_not_lvalue_reference(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT
{ return t; }
#else //Old move
template <class T>
- inline T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
{ return static_cast<T&&>(t); }
template <class T>
- inline T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
+ BOOST_MOVE_FORCEINLINE T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
{
//"boost::forward<T> error: 'T' is a lvalue reference, can't forward as rvalue.";
BOOST_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference<T>::value);
diff --git a/boost/mpi/communicator.hpp b/boost/mpi/communicator.hpp
index fcef0866a9..46f7375d6f 100644
--- a/boost/mpi/communicator.hpp
+++ b/boost/mpi/communicator.hpp
@@ -1257,7 +1257,7 @@ communicator::array_recv_impl(int source, int tag, T* values, int n,
ia >> count;
// Deserialize the data in the message
- boost::serialization::array<T> arr(values, count > n? n : count);
+ boost::serialization::array_wrapper<T> arr(values, count > n? n : count);
ia >> arr;
if (count > n) {
@@ -1459,7 +1459,7 @@ namespace detail {
ia >> count;
// Deserialize the data in the message
- boost::serialization::array<T> arr(values, count > n? n : count);
+ boost::serialization::array_wrapper<T> arr(values, count > n? n : count);
ia >> arr;
if (count > n) {
diff --git a/boost/mpi/detail/binary_buffer_iprimitive.hpp b/boost/mpi/detail/binary_buffer_iprimitive.hpp
index f499d0d5a8..388cd44c14 100644
--- a/boost/mpi/detail/binary_buffer_iprimitive.hpp
+++ b/boost/mpi/detail/binary_buffer_iprimitive.hpp
@@ -66,7 +66,7 @@ public:
// fast saving of arrays of fundamental types
template<class T>
- void load_array(serialization::array<T> const& x, unsigned int /* file_version */)
+ void load_array(serialization::array_wrapper<T> const& x, unsigned int /* file_version */)
{
BOOST_MPL_ASSERT((serialization::is_bitwise_serializable<BOOST_DEDUCED_TYPENAME remove_const<T>::type>));
if (x.count())
@@ -76,7 +76,7 @@ public:
typedef serialization::is_bitwise_serializable<mpl::_1> use_array_optimization;
template<class T>
- void load(serialization::array<T> const& x)
+ void load(serialization::array_wrapper<T> const& x)
{
load_array(x,0u);
}
diff --git a/boost/mpi/detail/binary_buffer_oprimitive.hpp b/boost/mpi/detail/binary_buffer_oprimitive.hpp
index facf36067b..1de441d26b 100644
--- a/boost/mpi/detail/binary_buffer_oprimitive.hpp
+++ b/boost/mpi/detail/binary_buffer_oprimitive.hpp
@@ -55,7 +55,7 @@ public:
// fast saving of arrays
template<class T>
- void save_array(serialization::array<T> const& x, unsigned int /* file_version */)
+ void save_array(serialization::array_wrapper<T> const& x, unsigned int /* file_version */)
{
BOOST_MPL_ASSERT((serialization::is_bitwise_serializable<BOOST_DEDUCED_TYPENAME remove_const<T>::type>));
@@ -64,7 +64,7 @@ public:
}
template<class T>
- void save(serialization::array<T> const& x)
+ void save(serialization::array_wrapper<T> const& x)
{
save_array(x,0u);
}
diff --git a/boost/mpi/detail/forward_iprimitive.hpp b/boost/mpi/detail/forward_iprimitive.hpp
index 44e7100093..33d39fd580 100644
--- a/boost/mpi/detail/forward_iprimitive.hpp
+++ b/boost/mpi/detail/forward_iprimitive.hpp
@@ -42,7 +42,7 @@ public:
/// loading of arrays is forwarded to the implementation archive
template<class T>
- void load_array(serialization::array<T> & x, unsigned int file_version )
+ void load_array(serialization::array_wrapper<T> & x, unsigned int file_version )
{
implementation_archive.load_array(x,file_version);
}
diff --git a/boost/mpi/detail/forward_oprimitive.hpp b/boost/mpi/detail/forward_oprimitive.hpp
index cd232ae5ad..78f7ca02f6 100644
--- a/boost/mpi/detail/forward_oprimitive.hpp
+++ b/boost/mpi/detail/forward_oprimitive.hpp
@@ -43,7 +43,7 @@ public:
/// saving of arrays is forwarded to the implementation archive
template<class T>
- void save_array(serialization::array<T> const& x, unsigned int file_version )
+ void save_array(serialization::array_wrapper<T> const& x, unsigned int file_version )
{
implementation_archive.save_array(x,file_version);
}
diff --git a/boost/mpi/detail/ignore_iprimitive.hpp b/boost/mpi/detail/ignore_iprimitive.hpp
index eb3d2b78fb..151ed0b348 100644
--- a/boost/mpi/detail/ignore_iprimitive.hpp
+++ b/boost/mpi/detail/ignore_iprimitive.hpp
@@ -37,7 +37,7 @@ public:
/// don't do anything when loading arrays
template<class T>
- void load_array(serialization::array<T> &, unsigned int )
+ void load_array(serialization::array_wrapper<T> &, unsigned int )
{}
typedef is_mpi_datatype<mpl::_1> use_array_optimization;
diff --git a/boost/mpi/detail/ignore_oprimitive.hpp b/boost/mpi/detail/ignore_oprimitive.hpp
index 23375cad7b..4f2994bfc7 100644
--- a/boost/mpi/detail/ignore_oprimitive.hpp
+++ b/boost/mpi/detail/ignore_oprimitive.hpp
@@ -36,7 +36,7 @@ public:
/// don't do anything when saving arrays
template<class T>
- void save_array(serialization::array<T> const&, unsigned int )
+ void save_array(serialization::array_wrapper<T> const&, unsigned int )
{
}
diff --git a/boost/mpi/detail/mpi_datatype_primitive.hpp b/boost/mpi/detail/mpi_datatype_primitive.hpp
index 0a6078548f..c230055ab5 100644
--- a/boost/mpi/detail/mpi_datatype_primitive.hpp
+++ b/boost/mpi/detail/mpi_datatype_primitive.hpp
@@ -63,7 +63,7 @@ public:
// fast saving of arrays of MPI types
template<class T>
- void save_array(serialization::array<T> const& x, unsigned int /* version */)
+ void save_array(serialization::array_wrapper<T> const& x, unsigned int /* version */)
{
if (x.count())
save_impl(x.address(), boost::mpi::get_mpi_datatype(*x.address()), x.count());
diff --git a/boost/mpi/detail/packed_iprimitive.hpp b/boost/mpi/detail/packed_iprimitive.hpp
index bb471a7c66..7080cbf53b 100644
--- a/boost/mpi/detail/packed_iprimitive.hpp
+++ b/boost/mpi/detail/packed_iprimitive.hpp
@@ -64,7 +64,7 @@ public:
// fast saving of arrays of fundamental types
template<class T>
- void load_array(serialization::array<T> const& x, unsigned int /* file_version */)
+ void load_array(serialization::array_wrapper<T> const& x, unsigned int /* file_version */)
{
if (x.count())
load_impl(x.address(), get_mpi_datatype(*x.address()), x.count());
@@ -72,7 +72,7 @@ public:
/*
template<class T>
- void load(serialization::array<T> const& x)
+ void load(serialization::array_wrapper<T> const& x)
{
load_array(x,0u);
}
diff --git a/boost/mpi/detail/packed_oprimitive.hpp b/boost/mpi/detail/packed_oprimitive.hpp
index 5ac6835e15..5b6b3b2708 100644
--- a/boost/mpi/detail/packed_oprimitive.hpp
+++ b/boost/mpi/detail/packed_oprimitive.hpp
@@ -54,7 +54,7 @@ public:
// fast saving of arrays
template<class T>
- void save_array(serialization::array<T> const& x, unsigned int /* file_version */)
+ void save_array(serialization::array_wrapper<T> const& x, unsigned int /* file_version */)
{
if (x.count())
save_impl(x.address(), get_mpi_datatype(*x.address()), x.count());
diff --git a/boost/multiprecision/concepts/mp_number_archetypes.hpp b/boost/multiprecision/concepts/mp_number_archetypes.hpp
index 9a5f15962b..f26e0e0d18 100644
--- a/boost/multiprecision/concepts/mp_number_archetypes.hpp
+++ b/boost/multiprecision/concepts/mp_number_archetypes.hpp
@@ -66,14 +66,18 @@ struct number_backend_float_architype
}
number_backend_float_architype& operator = (const char* s)
{
+#ifndef BOOST_NO_EXCEPTIONS
try
{
+#endif
m_value = boost::lexical_cast<long double>(s);
+#ifndef BOOST_NO_EXCEPTIONS
}
catch(const std::exception&)
{
BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Unable to parse input string: \"") + s + std::string("\" as a valid floating point number.")));
}
+#endif
std::cout << "const char* Assignment (" << s << ")" << std::endl;
return *this;
}
diff --git a/boost/multiprecision/cpp_bin_float.hpp b/boost/multiprecision/cpp_bin_float.hpp
index bdf6a6308b..92b73c5715 100644
--- a/boost/multiprecision/cpp_bin_float.hpp
+++ b/boost/multiprecision/cpp_bin_float.hpp
@@ -74,24 +74,15 @@ public:
template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
cpp_bin_float(const cpp_bin_float<D, B, A, E, MinE, MaxE> &o, typename boost::enable_if_c<(bit_count >= cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count)>::type const* = 0)
- : m_exponent(o.exponent()), m_sign(o.sign())
{
- typename cpp_bin_float<D, B, A, E, MinE, MaxE>::rep_type b(o.bits());
- this->sign() = o.sign();
- this->exponent() = o.exponent() + (int)bit_count - (int)cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count;
- copy_and_round(*this, b);
+ *this = o;
}
-
template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
explicit cpp_bin_float(const cpp_bin_float<D, B, A, E, MinE, MaxE> &o, typename boost::disable_if_c<(bit_count >= cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count)>::type const* = 0)
: m_exponent(o.exponent()), m_sign(o.sign())
{
- typename cpp_bin_float<D, B, A, E, MinE, MaxE>::rep_type b(o.bits());
- this->sign() = o.sign();
- this->exponent() = o.exponent() - (int)(cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count - bit_count);
- copy_and_round(*this, b);
+ *this = o;
}
-
template <class Float>
cpp_bin_float(const Float& f,
typename boost::enable_if_c<
@@ -125,12 +116,31 @@ public:
}
template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
- cpp_bin_float& operator=(const cpp_bin_float<D, B, A, E, MinE, MaxE> &o)
+ cpp_bin_float& operator=(const cpp_bin_float<D, B, A, E, MinE, MaxE> &f)
{
- typename cpp_bin_float<D, B, A, E, MinE, MaxE>::rep_type b(o.bits());
- this->exponent() = o.exponent() + (int)bit_count - (int)cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count;
- this->sign() = o.sign();
- copy_and_round(*this, b);
+ switch(eval_fpclassify(f))
+ {
+ case FP_ZERO:
+ m_data = limb_type(0);
+ m_sign = false;
+ m_exponent = exponent_zero;
+ break;
+ case FP_NAN:
+ m_data = limb_type(0);
+ m_sign = false;
+ m_exponent = exponent_nan;
+ break;;
+ case FP_INFINITE:
+ m_data = limb_type(0);
+ m_sign = f.sign();
+ m_exponent = exponent_infinity;
+ break;
+ default:
+ typename cpp_bin_float<D, B, A, E, MinE, MaxE>::rep_type b(f.bits());
+ this->exponent() = f.exponent() + (int)bit_count - (int)cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count;
+ this->sign() = f.sign();
+ copy_and_round(*this, b);
+ }
return *this;
}
@@ -164,7 +174,7 @@ public:
return *this;
case FP_INFINITE:
m_data = limb_type(0);
- m_sign = false;
+ m_sign = (f < 0);
m_exponent = exponent_infinity;
return *this;
}
@@ -232,7 +242,7 @@ public:
return *this;
case FP_INFINITE:
m_data = limb_type(0);
- m_sign = false;
+ m_sign = (f < 0);
m_exponent = exponent_infinity;
return *this;
}
@@ -581,8 +591,8 @@ inline void do_eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponen
res = a;
return;
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
- res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan;
- res.sign() = false;
+ res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
+ res.sign() = true;
res.bits() = static_cast<limb_type>(0u);
return; // result is a NaN.
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
@@ -595,7 +605,7 @@ inline void do_eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponen
if((e_diff > 0) || ((e_diff == 0) && a.bits().compare(b.bits()) >= 0))
{
dt = a.bits();
- if(e_diff < (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
+ if(e_diff <= (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
{
eval_left_shift(dt, e_diff);
res.exponent() = a.exponent() - e_diff;
@@ -607,7 +617,7 @@ inline void do_eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponen
else
{
dt = b.bits();
- if(-e_diff < (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
+ if(-e_diff <= (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
{
eval_left_shift(dt, -e_diff);
res.exponent() = b.exponent() + e_diff;
@@ -1144,30 +1154,34 @@ inline void eval_convert_to(boost::ulong_long_type *res, const cpp_bin_float<Dig
eval_convert_to(res, man);
}
-template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
-inline void eval_convert_to(long double *res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
+template <class Float, unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
+inline typename boost::enable_if_c<boost::is_float<Float>::value>::type eval_convert_to(Float *res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &original_arg)
{
+ //
+ // Perform rounding first, then afterwards extract the digits:
+ //
+ cpp_bin_float<std::numeric_limits<Float>::digits, digit_base_2, void, Exponent, MinE, MaxE> arg(original_arg);
switch(arg.exponent())
{
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
*res = 0;
return;
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
- *res = std::numeric_limits<long double>::quiet_NaN();
+ *res = std::numeric_limits<Float>::quiet_NaN();
return;
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
- *res = (std::numeric_limits<long double>::infinity)();
+ *res = (std::numeric_limits<Float>::infinity)();
if(arg.sign())
*res = -*res;
return;
}
typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type e = arg.exponent();
- e -= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1;
- *res = std::ldexp(static_cast<long double>(*arg.bits().limbs()), e);
+ e -= cpp_bin_float<std::numeric_limits<Float>::digits, digit_base_2, void, Exponent, MinE, MaxE>::bit_count - 1;
+ *res = std::ldexp(static_cast<Float>(*arg.bits().limbs()), e);
for(unsigned i = 1; i < arg.bits().size(); ++i)
{
e += sizeof(*arg.bits().limbs()) * CHAR_BIT;
- *res += std::ldexp(static_cast<long double>(arg.bits().limbs()[i]), e);
+ *res += std::ldexp(static_cast<Float>(arg.bits().limbs()[i]), e);
}
if(arg.sign())
*res = -*res;
diff --git a/boost/multiprecision/cpp_dec_float.hpp b/boost/multiprecision/cpp_dec_float.hpp
index 737f925067..057095e2b4 100644
--- a/boost/multiprecision/cpp_dec_float.hpp
+++ b/boost/multiprecision/cpp_dec_float.hpp
@@ -662,6 +662,12 @@ cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, Expone
return operator=(v);
}
+ if((v.isnan)() || (v.isinf)())
+ {
+ *this = v;
+ return *this;
+ }
+
// Get the offset for the add/sub operation.
static const ExponentType max_delta_exp = static_cast<ExponentType>((cpp_dec_float_elem_number - 1) * cpp_dec_float_elem_digits10);
@@ -1888,7 +1894,9 @@ std::string cpp_dec_float<Digits10, ExponentType, Allocator>::str(boost::intmax_
template <unsigned Digits10, class ExponentType, class Allocator>
bool cpp_dec_float<Digits10, ExponentType, Allocator>::rd_string(const char* const s)
{
+#ifndef BOOST_NO_EXCEPTIONS
try{
+#endif
std::string str(s);
@@ -2146,6 +2154,7 @@ bool cpp_dec_float<Digits10, ExponentType, Allocator>::rd_string(const char* con
}
}
+#ifndef BOOST_NO_EXCEPTIONS
}
catch(const bad_lexical_cast&)
{
@@ -2155,7 +2164,7 @@ bool cpp_dec_float<Digits10, ExponentType, Allocator>::rd_string(const char* con
msg += "\" as a floating point value.";
throw std::runtime_error(msg);
}
-
+#endif
return true;
}
@@ -2227,7 +2236,12 @@ cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, Expone
return *this = one();
if((boost::math::isinf)(a))
- return *this = inf();
+ {
+ *this = inf();
+ if(a < 0)
+ this->negate();
+ return *this;
+ }
if((boost::math::isnan)(a))
return *this = nan();
diff --git a/boost/multiprecision/cpp_int.hpp b/boost/multiprecision/cpp_int.hpp
index 60ad87676c..b8681677e2 100644
--- a/boost/multiprecision/cpp_int.hpp
+++ b/boost/multiprecision/cpp_int.hpp
@@ -190,7 +190,7 @@ private:
public:
BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT);
BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast<limb_type>(0u));
- BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = 1u << (limb_bits - 1));
+ BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = static_cast<limb_type>(1u) << (limb_bits - 1));
BOOST_STATIC_CONSTANT(unsigned, internal_limb_count =
MinBits
? (MinBits / limb_bits + ((MinBits % limb_bits) ? 1 : 0))
@@ -413,7 +413,7 @@ struct cpp_int_base<MinBits, MinBits, signed_magnitude, Checked, void, false>
public:
BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT);
BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast<limb_type>(0u));
- BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = 1u << (limb_bits - 1));
+ BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = static_cast<limb_type>(1u) << (limb_bits - 1));
BOOST_STATIC_CONSTANT(unsigned, internal_limb_count = MinBits / limb_bits + ((MinBits % limb_bits) ? 1 : 0));
BOOST_STATIC_CONSTANT(bool, variable = false);
BOOST_STATIC_CONSTANT(limb_type, upper_limb_mask = (MinBits % limb_bits) ? (limb_type(1) << (MinBits % limb_bits)) -1 : (~limb_type(0)));
@@ -565,7 +565,7 @@ struct cpp_int_base<MinBits, MinBits, unsigned_magnitude, Checked, void, false>
public:
BOOST_STATIC_CONSTANT(unsigned, limb_bits = sizeof(limb_type) * CHAR_BIT);
BOOST_STATIC_CONSTANT(limb_type, max_limb_value = ~static_cast<limb_type>(0u));
- BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = 1u << (limb_bits - 1));
+ BOOST_STATIC_CONSTANT(limb_type, sign_bit_mask = static_cast<limb_type>(1u) << (limb_bits - 1));
BOOST_STATIC_CONSTANT(unsigned, internal_limb_count = MinBits / limb_bits + ((MinBits % limb_bits) ? 1 : 0));
BOOST_STATIC_CONSTANT(bool, variable = false);
BOOST_STATIC_CONSTANT(limb_type, upper_limb_mask = (MinBits % limb_bits) ? (limb_type(1) << (MinBits % limb_bits)) -1 : (~limb_type(0)));
diff --git a/boost/multiprecision/cpp_int/bitwise.hpp b/boost/multiprecision/cpp_int/bitwise.hpp
index dd6ba9d191..e39be3d12c 100644
--- a/boost/multiprecision/cpp_int/bitwise.hpp
+++ b/boost/multiprecision/cpp_int/bitwise.hpp
@@ -306,30 +306,86 @@ BOOST_MP_FORCEINLINE typename enable_if_c<is_unsigned_number<cpp_int_backend<Min
result.normalize();
}
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
-inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_left_shift(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- double_limb_type s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+template <class Int>
+inline void left_shift_byte(Int& result, double_limb_type s)
{
- is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
- if(!s)
+ limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
+ limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
+ unsigned ors = result.size();
+ if((ors == 1) && (!*result.limbs()))
+ return; // shifting zero yields zero.
+ unsigned rs = ors;
+ if(shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift)))
+ ++rs; // Most significant limb will overflow when shifted
+ rs += offset;
+ result.resize(rs, rs);
+ rs = result.size();
+
+ typename Int::limb_pointer pr = result.limbs();
+
+ if(rs != ors)
+ pr[rs - 1] = 0u;
+ std::size_t bytes = static_cast<std::size_t>(s / CHAR_BIT);
+ std::size_t len = std::min(ors * sizeof(limb_type), rs * sizeof(limb_type) - bytes);
+ if(bytes >= rs * sizeof(limb_type))
+ result = static_cast<limb_type>(0u);
+ else
+ {
+ unsigned char* pc = reinterpret_cast<unsigned char*>(pr);
+ std::memmove(pc + bytes, pc, len);
+ std::memset(pc, 0, bytes);
+ }
+}
+
+template <class Int>
+inline void left_shift_limb(Int& result, double_limb_type s)
+{
+ limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
+ limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
+
+ unsigned ors = result.size();
+ if((ors == 1) && (!*result.limbs()))
+ return; // shifting zero yields zero.
+ unsigned rs = ors;
+ if(shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift)))
+ ++rs; // Most significant limb will overflow when shifted
+ rs += offset;
+ result.resize(rs, rs);
+ bool truncated = result.size() != rs;
+
+ typename Int::limb_pointer pr = result.limbs();
+
+ if(offset > rs)
+ {
+ // The result is shifted past the end of the result:
+ result = static_cast<limb_type>(0);
return;
+ }
- limb_type offset = static_cast<limb_type>(s / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits);
- limb_type shift = static_cast<limb_type>(s % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits);
+ unsigned i = rs - result.size();
+ for(; i < ors; ++i)
+ pr[rs - 1 - i] = pr[ors - 1 - i];
+ for(; i < rs; ++i)
+ pr[rs - 1 - i] = 0;
+}
+
+template <class Int>
+inline void left_shift_generic(Int& result, double_limb_type s)
+{
+ limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
+ limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
unsigned ors = result.size();
if((ors == 1) && (!*result.limbs()))
return; // shifting zero yields zero.
unsigned rs = ors;
- if(shift && (result.limbs()[ors - 1] >> (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - shift)))
+ if(shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift)))
++rs; // Most significant limb will overflow when shifted
rs += offset;
result.resize(rs, rs);
bool truncated = result.size() != rs;
- typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_pointer pr = result.limbs();
+ typename Int::limb_pointer pr = result.limbs();
if(offset > rs)
{
@@ -339,53 +395,40 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
}
unsigned i = rs - result.size();
- if(shift)
+ // This code only works when shift is non-zero, otherwise we invoke undefined behaviour!
+ BOOST_ASSERT(shift);
+ if(!truncated)
{
- // This code only works when shift is non-zero, otherwise we invoke undefined behaviour!
- if(!truncated)
- {
- if(rs > ors + offset)
- {
- pr[rs - 1 - i] = pr[ors - 1 - i] >> (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - shift);
- --rs;
- }
- else
- {
- pr[rs - 1 - i] = pr[ors - 1 - i] << shift;
- if(ors > 1)
- pr[rs - 1 - i] |= pr[ors - 2 - i] >> (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - shift);
- ++i;
- }
- }
- for(; ors > 1 + i; ++i)
+ if(rs > ors + offset)
{
- pr[rs - 1 - i] = pr[ors - 1 - i] << shift;
- pr[rs - 1 - i] |= pr[ors - 2 - i] >> (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - shift);
+ pr[rs - 1 - i] = pr[ors - 1 - i] >> (Int::limb_bits - shift);
+ --rs;
}
- if(ors >= 1 + i)
+ else
{
pr[rs - 1 - i] = pr[ors - 1 - i] << shift;
+ if(ors > 1)
+ pr[rs - 1 - i] |= pr[ors - 2 - i] >> (Int::limb_bits - shift);
++i;
}
- for(; i < rs; ++i)
- pr[rs - 1 - i] = 0;
}
- else
+ for(; ors > 1 + i; ++i)
{
- for(; i < ors; ++i)
- pr[rs - 1 - i] = pr[ors - 1 - i];
- for(; i < rs; ++i)
- pr[rs - 1 - i] = 0;
+ pr[rs - 1 - i] = pr[ors - 1 - i] << shift;
+ pr[rs - 1 - i] |= pr[ors - 2 - i] >> (Int::limb_bits - shift);
}
- //
- // We may have shifted off the end and have leading zeros:
- //
- result.normalize();
+ if(ors >= 1 + i)
+ {
+ pr[rs - 1 - i] = pr[ors - 1 - i] << shift;
+ ++i;
+ }
+ for(; i < rs; ++i)
+ pr[rs - 1 - i] = 0;
}
template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
- eval_right_shift(
+ eval_left_shift(
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
double_limb_type s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
@@ -393,51 +436,184 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
if(!s)
return;
- bool is_neg = result.sign();
- if(is_neg)
- eval_increment(result);
+#if defined(BOOST_LITTLE_ENDIAN) && defined(BOOST_MP_USE_LIMB_SHIFT)
+ static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1;
+ static const limb_type byte_shift_mask = CHAR_BIT - 1;
+ if((s & limb_shift_mask) == 0)
+ {
+ left_shift_limb(result, s);
+ }
+ else if((s & byte_shift_mask) == 0)
+ {
+ left_shift_byte(result, s);
+ }
+#elif defined(BOOST_LITTLE_ENDIAN)
+ static const limb_type byte_shift_mask = CHAR_BIT - 1;
+ if((s & byte_shift_mask) == 0)
+ {
+ left_shift_byte(result, s);
+ }
+#else
+ static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1;
+ if((s & limb_shift_mask) == 0)
+ {
+ left_shift_limb(result, s);
+ }
+#endif
+ else
+ {
+ left_shift_generic(result, s);
+ }
+ //
+ // We may have shifted off the end and have leading zeros:
+ //
+ result.normalize();
+}
- limb_type offset = static_cast<limb_type>(s / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits);
- limb_type shift = static_cast<limb_type>(s % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits);
+template <class Int>
+inline void right_shift_byte(Int& result, double_limb_type s)
+{
+ limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
+ limb_type shift;
+ BOOST_ASSERT((s % CHAR_BIT) == 0);
unsigned ors = result.size();
unsigned rs = ors;
if(offset >= rs)
{
- if(is_neg)
- result = signed_limb_type(-1);
- else
- result = limb_type(0);
+ result = limb_type(0);
return;
}
rs -= offset;
- typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_pointer pr = result.limbs();
- if((pr[ors - 1] >> shift) == 0)
- --rs;
- if(rs == 0)
+ typename Int::limb_pointer pr = result.limbs();
+ unsigned char* pc = reinterpret_cast<unsigned char*>(pr);
+ shift = static_cast<limb_type>(s / CHAR_BIT);
+ std::memmove(pc, pc + shift, ors * sizeof(pr[0]) - shift);
+ shift = (sizeof(limb_type) - shift % sizeof(limb_type)) * CHAR_BIT;
+ if(shift < Int::limb_bits)
{
- if(is_neg)
- result = signed_limb_type(-1);
- else
- result = limb_type(0);
+ pr[ors - offset - 1] &= (static_cast<limb_type>(1u) << shift) - 1;
+ if(!pr[ors - offset - 1] && (rs > 1))
+ --rs;
+ }
+ result.resize(rs, rs);
+}
+
+template <class Int>
+inline void right_shift_limb(Int& result, double_limb_type s)
+{
+ limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
+ BOOST_ASSERT((s % Int::limb_bits) == 0);
+ unsigned ors = result.size();
+ unsigned rs = ors;
+ if(offset >= rs)
+ {
+ result = limb_type(0);
return;
}
+ rs -= offset;
+ typename Int::limb_pointer pr = result.limbs();
unsigned i = 0;
- if(shift)
+ for(; i < rs; ++i)
+ pr[i] = pr[i + offset];
+ result.resize(rs, rs);
+}
+
+template <class Int>
+inline void right_shift_generic(Int& result, double_limb_type s)
+{
+ limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
+ limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
+ unsigned ors = result.size();
+ unsigned rs = ors;
+ if(offset >= rs)
+ {
+ result = limb_type(0);
+ return;
+ }
+ rs -= offset;
+ typename Int::limb_pointer pr = result.limbs();
+ if((pr[ors - 1] >> shift) == 0)
{
- // This code only works for non-zero shift, otherwise we invoke undefined behaviour!
- for(; i + offset + 1 < ors; ++i)
+ if(--rs == 0)
{
- pr[i] = pr[i + offset] >> shift;
- pr[i] |= pr[i + offset + 1] << (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - shift);
+ result = limb_type(0);
+ return;
}
- pr[i] = pr[i + offset] >> shift;
}
- else
+ unsigned i = 0;
+
+ // This code only works for non-zero shift, otherwise we invoke undefined behaviour!
+ BOOST_ASSERT(shift);
+ for(; i + offset + 1 < ors; ++i)
{
- for(; i < rs; ++i)
- pr[i] = pr[i + offset];
+ pr[i] = pr[i + offset] >> shift;
+ pr[i] |= pr[i + offset + 1] << (Int::limb_bits - shift);
}
+ pr[i] = pr[i + offset] >> shift;
result.resize(rs, rs);
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
+inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
+ eval_right_shift(
+ cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
+ double_limb_type s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value))
+{
+ is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>::checked_type());
+ if(!s)
+ return;
+
+#if defined(BOOST_LITTLE_ENDIAN) && defined(BOOST_MP_USE_LIMB_SHIFT)
+ static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
+ static const limb_type byte_shift_mask = CHAR_BIT - 1;
+ if((s & limb_shift_mask) == 0)
+ right_shift_limb(result, s);
+ else if((s & byte_shift_mask) == 0)
+ right_shift_byte(result, s);
+#elif defined(BOOST_LITTLE_ENDIAN)
+ static const limb_type byte_shift_mask = CHAR_BIT - 1;
+ if((s & byte_shift_mask) == 0)
+ right_shift_byte(result, s);
+#else
+ static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
+ if((s & limb_shift_mask) == 0)
+ right_shift_limb(result, s);
+#endif
+ else
+ right_shift_generic(result, s);
+}
+template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1>
+inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1> >::value>::type
+ eval_right_shift(
+ cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>& result,
+ double_limb_type s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1> >::value))
+{
+ is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::checked_type());
+ if(!s)
+ return;
+
+ bool is_neg = result.sign();
+ if(is_neg)
+ eval_increment(result);
+
+#if defined(BOOST_LITTLE_ENDIAN) && defined(BOOST_MP_USE_LIMB_SHIFT)
+ static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
+ static const limb_type byte_shift_mask = CHAR_BIT - 1;
+ if((s & limb_shift_mask) == 0)
+ right_shift_limb(result, s);
+ else if((s & byte_shift_mask) == 0)
+ right_shift_byte(result, s);
+#elif defined(BOOST_LITTLE_ENDIAN)
+ static const limb_type byte_shift_mask = CHAR_BIT - 1;
+ if((s & byte_shift_mask) == 0)
+ right_shift_byte(result, s);
+#else
+ static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
+ if((s & limb_shift_mask) == 0)
+ right_shift_limb(result, s);
+#endif
+ else
+ right_shift_generic(result, s);
if(is_neg)
eval_decrement(result);
}
@@ -460,7 +636,9 @@ BOOST_MP_FORCEINLINE typename enable_if<is_trivial_cpp_int<cpp_int_backend<MinBi
{
// Nothing to check here... just make sure we don't invoke undefined behavior:
is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
- *result.limbs() = (static_cast<unsigned>(s) >= sizeof(*result.limbs()) * CHAR_BIT) ? 0 : *result.limbs() >> s;
+ *result.limbs() = (static_cast<unsigned>(s) >= sizeof(*result.limbs()) * CHAR_BIT) ? 0 : (result.sign() ? ((--*result.limbs()) >> s) + 1 : *result.limbs() >> s);
+ if(result.sign() && (*result.limbs() == 0))
+ result = static_cast<signed_limb_type>(-1);
}
template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
@@ -469,34 +647,40 @@ inline typename enable_if_c<
&& is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
&& (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)
>::type
- eval_bitwise_and(
+ eval_complement(
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
- is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
-
- using default_ops::eval_bit_test;
- using default_ops::eval_increment;
-
- if(result.sign() || o.sign())
+ BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), "Attempt to take the complement of a signed type results in undefined behavior.");
+ //
+ // If we're not checked then emulate 2's complement behavior:
+ //
+ if(o.sign())
{
- static const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
- cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
- cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
- eval_bitwise_and(t1, t2);
- bool s = eval_bit_test(t1, m + 1);
- if(s)
- {
- eval_complement(t1, t1);
- eval_increment(t1);
- }
- result = t1;
- result.sign(s);
+ *result.limbs() = *o.limbs() - 1;
+ result.sign(false);
}
else
{
- *result.limbs() &= *o.limbs();
+ *result.limbs() = 1 + *o.limbs();
+ result.sign(true);
}
+ result.normalize();
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+inline typename enable_if_c<
+ is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
+ && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
+ && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
+ && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
+ >::type
+ eval_complement(
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
+ const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
+{
+ *result.limbs() = ~*o.limbs();
+ result.normalize();
}
template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
@@ -519,7 +703,7 @@ inline typename enable_if_c<
&& is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
&& (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)
>::type
- eval_bitwise_or(
+ eval_bitwise_and(
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
@@ -533,7 +717,7 @@ inline typename enable_if_c<
static const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
- eval_bitwise_or(t1, t2);
+ eval_bitwise_and(t1, t2);
bool s = eval_bit_test(t1, m + 1);
if(s)
{
@@ -545,8 +729,7 @@ inline typename enable_if_c<
}
else
{
- *result.limbs() |= *o.limbs();
- result.normalize();
+ *result.limbs() &= *o.limbs();
}
}
@@ -570,7 +753,7 @@ inline typename enable_if_c<
&& is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
&& (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)
>::type
- eval_bitwise_xor(
+ eval_bitwise_or(
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
@@ -584,7 +767,7 @@ inline typename enable_if_c<
static const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
- eval_bitwise_xor(t1, t2);
+ eval_bitwise_or(t1, t2);
bool s = eval_bit_test(t1, m + 1);
if(s)
{
@@ -596,7 +779,8 @@ inline typename enable_if_c<
}
else
{
- *result.limbs() ^= *o.limbs();
+ *result.limbs() |= *o.limbs();
+ result.normalize();
}
}
@@ -620,40 +804,34 @@ inline typename enable_if_c<
&& is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
&& (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value)
>::type
- eval_complement(
+ eval_bitwise_xor(
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
- BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), "Attempt to take the complement of a signed type results in undefined behavior.");
- //
- // If we're not checked then emulate 2's complement behavior:
- //
- if(o.sign())
+ is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
+
+ using default_ops::eval_bit_test;
+ using default_ops::eval_increment;
+
+ if(result.sign() || o.sign())
{
- *result.limbs() = *o.limbs() - 1;
- result.sign(false);
+ static const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
+ cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
+ cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
+ eval_bitwise_xor(t1, t2);
+ bool s = eval_bit_test(t1, m + 1);
+ if(s)
+ {
+ eval_complement(t1, t1);
+ eval_increment(t1);
+ }
+ result = t1;
+ result.sign(s);
}
else
{
- *result.limbs() = 1 + *o.limbs();
- result.sign(true);
+ *result.limbs() ^= *o.limbs();
}
- result.normalize();
-}
-
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
-inline typename enable_if_c<
- is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
- && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
- && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value
- >::type
- eval_complement(
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
- const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
-{
- *result.limbs() = ~*o.limbs();
- result.normalize();
}
}}} // namespaces
diff --git a/boost/multiprecision/cpp_int/import_export.hpp b/boost/multiprecision/cpp_int/import_export.hpp
index f2f15f6421..3a2473b0b2 100644
--- a/boost/multiprecision/cpp_int/import_export.hpp
+++ b/boost/multiprecision/cpp_int/import_export.hpp
@@ -85,46 +85,97 @@ namespace boost {
*newval.limbs() = 0;
}
- }
+ template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class Iterator>
+ number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&
+ import_bits_generic(
+ number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, Iterator i, Iterator j, unsigned chunk_size = 0, bool msv_first = true)
+ {
+ typename number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>::backend_type newval;
+ typedef typename std::iterator_traits<Iterator>::value_type value_type;
+ typedef typename boost::make_unsigned<value_type>::type unsigned_value_type;
+ typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
+ typedef typename boost::make_unsigned<difference_type>::type size_type;
+ typedef typename cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>::trivial_tag tag_type;
- template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class Iterator>
- number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&
- import_bits(
- number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, Iterator i, Iterator j, unsigned chunk_size = 0, bool msv_first = true)
- {
- typename number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>::backend_type newval;
+ if(!chunk_size)
+ chunk_size = std::numeric_limits<value_type>::digits;
- typedef typename std::iterator_traits<Iterator>::value_type value_type;
- typedef typename boost::make_unsigned<value_type>::type unsigned_value_type;
- typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
- typedef typename boost::make_unsigned<difference_type>::type size_type;
- typedef typename cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>::trivial_tag tag_type;
+ size_type limbs = std::distance(i, j);
+ size_type bits = limbs * chunk_size;
+
+ detail::resize_to_bit_size(newval, static_cast<unsigned>(bits), tag_type());
- if(!chunk_size)
- chunk_size = std::numeric_limits<value_type>::digits;
+ difference_type bit_location = msv_first ? bits - chunk_size : 0;
+ difference_type bit_location_change = msv_first ? -static_cast<difference_type>(chunk_size) : chunk_size;
- size_type limbs = std::distance(i, j);
- size_type bits = limbs * chunk_size;
+ while(i != j)
+ {
+ detail::assign_bits(newval, static_cast<unsigned_value_type>(*i), static_cast<unsigned>(bit_location), chunk_size, tag_type());
+ ++i;
+ bit_location += bit_location_change;
+ }
- detail::resize_to_bit_size(newval, static_cast<unsigned>(bits), tag_type());
+ newval.normalize();
- difference_type bit_location = msv_first ? bits - chunk_size : 0;
- difference_type bit_location_change = msv_first ? -static_cast<difference_type>(chunk_size) : chunk_size;
+ val.backend().swap(newval);
+ return val;
+ }
- while(i != j)
+ template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class T>
+ inline typename boost::disable_if_c<boost::multiprecision::backends::is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value, number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&>::type
+ import_bits_fast(
+ number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, T* i, T* j, unsigned chunk_size = 0)
{
- detail::assign_bits(newval, static_cast<unsigned_value_type>(*i), static_cast<unsigned>(bit_location), chunk_size, tag_type());
- ++i;
- bit_location += bit_location_change;
+ std::size_t byte_len = (j - i) * (chunk_size ? chunk_size / CHAR_BIT : sizeof(*i));
+ std::size_t limb_len = byte_len / sizeof(limb_type);
+ if(byte_len % sizeof(limb_type))
+ ++limb_len;
+ cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& result = val.backend();
+ result.resize(limb_len, limb_len); // checked types may throw here if they're not large enough to hold the data!
+ result.limbs()[result.size() - 1] = 0u;
+ std::memcpy(result.limbs(), i, std::min(byte_len, result.size() * sizeof(limb_type)));
+ result.normalize(); // In case data has leading zeros.
+ return val;
}
+ template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class T>
+ inline typename boost::enable_if_c<boost::multiprecision::backends::is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value, number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&>::type
+ import_bits_fast(
+ number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, T* i, T* j, unsigned chunk_size = 0)
+ {
+ cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& result = val.backend();
+ std::size_t byte_len = (j - i) * (chunk_size ? chunk_size / CHAR_BIT : sizeof(*i));
+ std::size_t limb_len = byte_len / sizeof(result.limbs()[0]);
+ if(byte_len % sizeof(result.limbs()[0]))
+ ++limb_len;
+ result.limbs()[0] = 0u;
+ result.resize(limb_len, limb_len); // checked types may throw here if they're not large enough to hold the data!
+ std::memcpy(result.limbs(), i, std::min(byte_len, result.size() * sizeof(result.limbs()[0])));
+ result.normalize(); // In case data has leading zeros.
+ return val;
+ }
+ }
- newval.normalize();
- val.backend().swap(newval);
- return val;
+ template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class Iterator>
+ inline number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&
+ import_bits(
+ number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, Iterator i, Iterator j, unsigned chunk_size = 0, bool msv_first = true)
+ {
+ return detail::import_bits_generic(val, i, j, chunk_size, msv_first);
}
+ template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class T>
+ inline number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&
+ import_bits(
+ number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, T* i, T* j, unsigned chunk_size = 0, bool msv_first = true)
+ {
+#ifdef BOOST_LITTLE_ENDIAN
+ if(((chunk_size % CHAR_BIT) == 0) && !msv_first)
+ return detail::import_bits_fast(val, i, j, chunk_size);
+#endif
+ return detail::import_bits_generic(val, i, j, chunk_size, msv_first);
+ }
namespace detail {
@@ -152,6 +203,7 @@ namespace boost {
boost::uintmax_t mask = count == std::numeric_limits<boost::uintmax_t>::digits ? ~static_cast<boost::uintmax_t>(0) : (static_cast<boost::uintmax_t>(1u) << count) - 1;
return (result >> location) & mask;
}
+
}
template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class OutputIterator>
diff --git a/boost/multiprecision/debug_adaptor.hpp b/boost/multiprecision/debug_adaptor.hpp
index 6eb5a04616..a6ed903c44 100644
--- a/boost/multiprecision/debug_adaptor.hpp
+++ b/boost/multiprecision/debug_adaptor.hpp
@@ -28,9 +28,12 @@ private:
public:
void update_view()
{
+#ifndef BOOST_NO_EXCEPTIONS
try
{
+#endif
debug_value = m_value.str(0, static_cast<std::ios_base::fmtflags>(0));
+#ifndef BOOST_NO_EXCEPTIONS
}
catch(const std::exception& e)
{
@@ -38,6 +41,7 @@ public:
debug_value += e.what();
debug_value += "\"";
}
+#endif
}
debug_adaptor()
{
diff --git a/boost/multiprecision/detail/bitscan.hpp b/boost/multiprecision/detail/bitscan.hpp
index ce1cdc8d18..a21fd58651 100644
--- a/boost/multiprecision/detail/bitscan.hpp
+++ b/boost/multiprecision/detail/bitscan.hpp
@@ -8,8 +8,8 @@
#ifndef BOOST_MP_DETAIL_BITSCAN_HPP
#define BOOST_MP_DETAIL_BITSCAN_HPP
-#if defined(BOOST_MSVC) && (defined(_M_IX86) || defined(_M_X64))
-#include <Intrin.h>
+#if (defined(BOOST_MSVC) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
+#include <intrin.h>
#endif
namespace boost{ namespace multiprecision{ namespace detail{
@@ -38,7 +38,7 @@ inline unsigned find_msb(Unsigned mask, const mpl::int_<0>&)
return --index;
}
-#if defined(BOOST_MSVC) && (defined(_M_IX86) || defined(_M_X64))
+#if (defined(BOOST_MSVC) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
#pragma intrinsic(_BitScanForward,_BitScanReverse)
diff --git a/boost/multiprecision/detail/default_ops.hpp b/boost/multiprecision/detail/default_ops.hpp
index f76addb350..59d098ba0d 100644
--- a/boost/multiprecision/detail/default_ops.hpp
+++ b/boost/multiprecision/detail/default_ops.hpp
@@ -2191,6 +2191,10 @@ inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multi
//
#include <boost/multiprecision/detail/no_et_ops.hpp>
#include <boost/multiprecision/detail/et_ops.hpp>
+//
+// min/max overloads:
+//
+#include <boost/multiprecision/detail/min_max.hpp>
#endif
diff --git a/boost/multiprecision/detail/functions/pow.hpp b/boost/multiprecision/detail/functions/pow.hpp
index b58d6b07be..e51df69d4a 100644
--- a/boost/multiprecision/detail/functions/pow.hpp
+++ b/boost/multiprecision/detail/functions/pow.hpp
@@ -459,26 +459,31 @@ inline void eval_pow(T& result, const T& x, const T& a)
typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type an;
T fa;
+#ifndef BOOST_NO_EXCEPTIONS
try
{
+#endif
eval_convert_to(&an, a);
if(a.compare(an) == 0)
{
detail::pow_imp(result, x, an, mpl::true_());
return;
}
+#ifndef BOOST_NO_EXCEPTIONS
}
catch(const std::exception&)
{
// conversion failed, just fall through, value is not an integer.
an = (std::numeric_limits<boost::intmax_t>::max)();
}
-
+#endif
if((eval_get_sign(x) < 0))
{
typename boost::multiprecision::detail::canonical<boost::uintmax_t, T>::type aun;
+#ifndef BOOST_NO_EXCEPTIONS
try
{
+#endif
eval_convert_to(&aun, a);
if(a.compare(aun) == 0)
{
@@ -489,11 +494,13 @@ inline void eval_pow(T& result, const T& x, const T& a)
result.negate();
return;
}
+#ifndef BOOST_NO_EXCEPTIONS
}
catch(const std::exception&)
{
// conversion failed, just fall through, value is not an integer.
}
+#endif
if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
else
diff --git a/boost/multiprecision/detail/min_max.hpp b/boost/multiprecision/detail/min_max.hpp
new file mode 100644
index 0000000000..56ac5346cf
--- /dev/null
+++ b/boost/multiprecision/detail/min_max.hpp
@@ -0,0 +1,114 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright 2016 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_0.txt)
+
+#ifndef BOOST_MP_MIN_MAX_HPP
+#define BOOST_MP_MIN_MAX_HPP
+
+#include <boost/multiprecision/traits/is_backend.hpp>
+
+namespace boost{ namespace multiprecision{
+
+//
+// Expression template overloads for (min) and (max):
+//
+// Introduced in response to https://svn.boost.org/trac/boost/ticket/11149
+// note that these can not legally be injected into namespace std, and that doing so
+// may break future enhancements to the standard. None the less adding
+// namespace std{ using boost::multiprecision::(min); using boost::multiprecision::(max); }
+// to your code may get some generic code working that wouldn't work otherwise.
+//
+// The use of enable_if on the return type is to avoid poisoning std::min/max,
+// otherwise attempting to make an explicit call to min<long>(a, b) when these and std
+// versions are in scope, will cause the compiler to try to instantiate the signatures
+// for our versions as well as the std ones, which in turn instantiates number<long>
+// which fails to compile as "long" is not a valid backend type.
+//
+template <class Backend>
+inline typename boost::enable_if_c < boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on>&>::type
+ (min)(const number<Backend, et_on>& a, const number<Backend, et_on>& b)
+{
+ return a < b ? a : b;
+}
+template <class Backend, class tag, class A1, class A2, class A3, class A4>
+inline typename boost::enable_if_c < boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on> >::type
+ (min)(const number<Backend, et_on>& a, const detail::expression<tag, A1, A2, A3, A4>& b)
+{
+ number<Backend, et_on> t(b);
+ if(a < t)
+ return a;
+ return BOOST_MP_MOVE(t);
+}
+template <class tag, class A1, class A2, class A3, class A4, class Backend>
+inline typename boost::enable_if_c < boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on> >::type
+ (min)(const detail::expression<tag, A1, A2, A3, A4>& a, const number<Backend, et_on>& b)
+{
+ number<Backend, et_on> t(a);
+ if(t < b)
+ return BOOST_MP_MOVE(t);
+ return b;
+}
+template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
+inline typename detail::expression<tag, A1, A2, A3, A4>::result_type
+ (min)(const detail::expression<tag, A1, A2, A3, A4>& a, const detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
+{
+ typename detail::expression<tag, A1, A2, A3, A4>::result_type t1(a), t2(b);
+ if(t1 < t2)
+ return BOOST_MP_MOVE(t1);
+ return BOOST_MP_MOVE(t2);
+}
+template <class tag, class A1, class A2, class A3, class A4>
+inline typename detail::expression<tag, A1, A2, A3, A4>::result_type (min)(const detail::expression<tag, A1, A2, A3, A4>& a, const detail::expression<tag, A1, A2, A3, A4>& b)
+{
+ typename detail::expression<tag, A1, A2, A3, A4>::result_type t1(a), t2(b);
+ if(t1 < t2)
+ return BOOST_MP_MOVE(t1);
+ return BOOST_MP_MOVE(t2);
+}
+
+template <class Backend>
+inline typename boost::enable_if_c < boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on>&>::type
+ (max)(const number<Backend, et_on>& a, const number<Backend, et_on>& b)
+{
+ return a > b ? a : b;
+}
+template <class Backend, class tag, class A1, class A2, class A3, class A4>
+inline typename boost::enable_if_c < boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on> >::type
+ (max)(const number<Backend, et_on>& a, const detail::expression<tag, A1, A2, A3, A4>& b)
+{
+ number<Backend, et_on> t(b);
+ if(a > t)
+ return a;
+ return BOOST_MP_MOVE(t);
+}
+template <class tag, class A1, class A2, class A3, class A4, class Backend>
+inline typename boost::enable_if_c < boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on> >::type
+ (max)(const detail::expression<tag, A1, A2, A3, A4>& a, const number<Backend, et_on>& b)
+{
+ number<Backend, et_on> t(a);
+ if(t > b)
+ return BOOST_MP_MOVE(t);
+ return b;
+}
+template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
+inline typename detail::expression<tag, A1, A2, A3, A4>::result_type
+ (max)(const detail::expression<tag, A1, A2, A3, A4>& a, const detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
+{
+ typename detail::expression<tag, A1, A2, A3, A4>::result_type t1(a), t2(b);
+ if(t1 > t2)
+ return BOOST_MP_MOVE(t1);
+ return BOOST_MP_MOVE(t2);
+}
+template <class tag, class A1, class A2, class A3, class A4>
+inline typename detail::expression<tag, A1, A2, A3, A4>::result_type (max)(const detail::expression<tag, A1, A2, A3, A4>& a, const detail::expression<tag, A1, A2, A3, A4>& b)
+{
+ typename detail::expression<tag, A1, A2, A3, A4>::result_type t1(a), t2(b);
+ if(t1 > t2)
+ return BOOST_MP_MOVE(t1);
+ return BOOST_MP_MOVE(t2);
+}
+
+}} // namespaces
+
+#endif
diff --git a/boost/multiprecision/detail/number_base.hpp b/boost/multiprecision/detail/number_base.hpp
index 6e18763b5c..f229914c79 100644
--- a/boost/multiprecision/detail/number_base.hpp
+++ b/boost/multiprecision/detail/number_base.hpp
@@ -9,6 +9,7 @@
#include <limits>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_constructible.hpp>
#include <boost/type_traits/decay.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
@@ -25,12 +26,16 @@
# define BOOST_MP_FORCEINLINE inline
#endif
-#if defined(BOOST_GCC) && (BOOST_GCC <= 40700)
+#if (defined(BOOST_GCC) && (BOOST_GCC <= 40700)) || defined(__SUNPRO_CC)
# define BOOST_MP_NOEXCEPT_IF(x)
#else
# define BOOST_MP_NOEXCEPT_IF(x) BOOST_NOEXCEPT_IF(x)
#endif
+#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) || defined(__SUNPRO_CC)
+#define BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
+#endif
+
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable:6326)
@@ -378,8 +383,8 @@ struct expression<tag, Arg1, void, void, void>
const Arg1& left_ref()const BOOST_NOEXCEPT { return arg; }
static const unsigned depth = left_type::depth + 1;
-#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
-# if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
+#ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
+# if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
//
// Horrible workaround for gcc-4.6.x which always prefers the template
// operator bool() rather than the non-template operator when converting to
@@ -397,7 +402,7 @@ struct expression<tag, Arg1, void, void, void>
return static_cast<T>(static_cast<result_type>(*this));
}
# else
- template <class T, typename boost::disable_if_c<is_number<T>::value, int>::type = 0>
+ template <class T, typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0>
explicit operator T()const
{
return static_cast<T>(static_cast<result_type>(*this));
@@ -442,8 +447,8 @@ struct expression<terminal, Arg1, void, void, void>
static const unsigned depth = 0;
-#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
-# if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
+#ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
+# if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
//
// Horrible workaround for gcc-4.6.x which always prefers the template
// operator bool() rather than the non-template operator when converting to
@@ -461,7 +466,7 @@ struct expression<terminal, Arg1, void, void, void>
return static_cast<T>(static_cast<result_type>(*this));
}
# else
- template <class T, typename boost::disable_if_c<is_number<T>::value, int>::type = 0>
+ template <class T, typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0>
explicit operator T()const
{
return static_cast<T>(static_cast<result_type>(*this));
@@ -510,8 +515,8 @@ struct expression<tag, Arg1, Arg2, void, void>
const Arg1& left_ref()const BOOST_NOEXCEPT { return arg1; }
const Arg2& right_ref()const BOOST_NOEXCEPT { return arg2; }
-#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
-# if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
+#ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
+# if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
//
// Horrible workaround for gcc-4.6.x which always prefers the template
// operator bool() rather than the non-template operator when converting to
@@ -529,7 +534,7 @@ struct expression<tag, Arg1, Arg2, void, void>
return static_cast<T>(static_cast<result_type>(*this));
}
# else
- template <class T, typename boost::disable_if_c<is_number<T>::value, int>::type = 0>
+ template <class T, typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0>
explicit operator T()const
{
return static_cast<T>(static_cast<result_type>(*this));
@@ -589,8 +594,8 @@ struct expression<tag, Arg1, Arg2, Arg3, void>
const Arg2& middle_ref()const BOOST_NOEXCEPT { return arg2; }
const Arg3& right_ref()const BOOST_NOEXCEPT { return arg3; }
-#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
-# if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
+#ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
+# if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
//
// Horrible workaround for gcc-4.6.x which always prefers the template
// operator bool() rather than the non-template operator when converting to
@@ -608,7 +613,7 @@ struct expression<tag, Arg1, Arg2, Arg3, void>
return static_cast<T>(static_cast<result_type>(*this));
}
# else
- template <class T, typename boost::disable_if_c<is_number<T>::value, int>::type = 0>
+ template <class T, typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0>
explicit operator T()const
{
return static_cast<T>(static_cast<result_type>(*this));
@@ -677,8 +682,8 @@ struct expression
const Arg3& right_middle_ref()const BOOST_NOEXCEPT { return arg3; }
const Arg4& right_ref()const BOOST_NOEXCEPT { return arg4; }
-#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
-# if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
+#ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
+# if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
//
// Horrible workaround for gcc-4.6.x which always prefers the template
// operator bool() rather than the non-template operator when converting to
@@ -696,7 +701,7 @@ struct expression
return static_cast<T>(static_cast<result_type>(*this));
}
# else
- template <class T, typename boost::disable_if_c<is_number<T>::value, int>::type = 0>
+ template <class T, typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0>
explicit operator T()const
{
return static_cast<T>(static_cast<result_type>(*this));
diff --git a/boost/multiprecision/detail/number_compare.hpp b/boost/multiprecision/detail/number_compare.hpp
index e9e510d302..3a36289d8b 100644
--- a/boost/multiprecision/detail/number_compare.hpp
+++ b/boost/multiprecision/detail/number_compare.hpp
@@ -120,7 +120,11 @@ inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Backend>::val
return false;
}
template <class Backend, expression_template_option ExpressionTemplates>
-inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Backend>::value == number_kind_floating_point, bool>::type is_unordered_value(const number<Backend, ExpressionTemplates>& a)
+inline
+#if !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40700)
+BOOST_CONSTEXPR
+#endif
+ typename boost::enable_if_c<number_category<Backend>::value == number_kind_floating_point, bool>::type is_unordered_value(const number<Backend, ExpressionTemplates>& a)
{
using default_ops::eval_fpclassify;
return eval_fpclassify(a.backend()) == FP_NAN;
diff --git a/boost/multiprecision/float128.hpp b/boost/multiprecision/float128.hpp
index 4341672393..979666a393 100644
--- a/boost/multiprecision/float128.hpp
+++ b/boost/multiprecision/float128.hpp
@@ -152,6 +152,21 @@ public:
m_value = i;
return *this;
}
+ float128_backend(long double const& f)
+ {
+ if(boost::math::isinf(f))
+ m_value = (f < 0) ? -1.0Q / 0.0Q : 1.0Q / 0.0Q;
+ else
+ m_value = f;
+ }
+ float128_backend& operator=(long double const& f)
+ {
+ if(boost::math::isinf(f))
+ m_value = (f < 0) ? -1.0Q / 0.0Q : 1.0Q / 0.0Q;
+ else
+ m_value = f;
+ return *this;
+ }
float128_backend& operator = (const char* s)
{
#ifndef BOOST_MP_USE_QUAD
@@ -336,7 +351,19 @@ inline void eval_sqrt(float128_backend& result, const float128_backend& arg)
}
inline int eval_fpclassify(const float128_backend& arg)
{
- return isnanq(arg.value()) ? FP_NAN : isinfq(arg.value()) ? FP_INFINITE : arg.value() == 0 ? FP_ZERO : FP_NORMAL;
+ if(isnanq(arg.value()))
+ return FP_NAN;
+ else if(isinfq(arg.value()))
+ return FP_INFINITE;
+ else if(arg.value() == 0)
+ return FP_ZERO;
+
+ float128_backend t(arg);
+ if(t.value() < 0)
+ t.negate();
+ if(t.value() < 3.36210314311209350626267781732175260e-4932Q)
+ return FP_SUBNORMAL;
+ return FP_NORMAL;
}
inline void eval_increment(float128_backend& arg)
@@ -549,12 +576,12 @@ public:
BOOST_STATIC_CONSTEXPR bool has_infinity = true;
BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true;
BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
- BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent;
- BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
+ BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_present;
+ BOOST_STATIC_CONSTEXPR bool has_denorm_loss = true;
static number_type infinity() { return 1.0q / 0.0q; }
static number_type quiet_NaN() { return number_type("nan"); }
static number_type signaling_NaN() { return 0; }
- static number_type denorm_min() { return 0; }
+ static number_type denorm_min() { return 6.475175119438025110924438958227646552e-4966Q; }
BOOST_STATIC_CONSTEXPR bool is_iec559 = true;
BOOST_STATIC_CONSTEXPR bool is_bounded = false;
BOOST_STATIC_CONSTEXPR bool is_modulo = false;
diff --git a/boost/multiprecision/mpfi.hpp b/boost/multiprecision/mpfi.hpp
index 66a23cab70..1ac7d1b5b9 100644
--- a/boost/multiprecision/mpfi.hpp
+++ b/boost/multiprecision/mpfi.hpp
@@ -907,8 +907,10 @@ inline void eval_pow(mpfi_float_backend<Digits10>& result, const mpfi_float_back
return;
}
typename boost::multiprecision::detail::canonical<boost::uintmax_t, mpfi_float_backend<Digits10> >::type an;
+#ifndef BOOST_NO_EXCEPTIONS
try
{
+#endif
using default_ops::eval_convert_to;
eval_convert_to(&an, e);
if(e.compare(an) == 0)
@@ -920,11 +922,13 @@ inline void eval_pow(mpfi_float_backend<Digits10>& result, const mpfi_float_back
result.negate();
return;
}
+#ifndef BOOST_NO_EXCEPTIONS
}
catch(const std::exception&)
{
// conversion failed, just fall through, value is not an integer.
}
+#endif
result = std::numeric_limits<number<mpfi_float_backend<Digits10>, et_on> >::quiet_NaN().backend();
return;
}
diff --git a/boost/multiprecision/mpfr.hpp b/boost/multiprecision/mpfr.hpp
index fde558be79..299de4a587 100644
--- a/boost/multiprecision/mpfr.hpp
+++ b/boost/multiprecision/mpfr.hpp
@@ -1228,6 +1228,11 @@ inline void eval_convert_to(boost::long_long_type* result, const mpfr_float_back
}
#endif
template <unsigned digits10, mpfr_allocation_type AllocationType>
+inline void eval_convert_to(float* result, const mpfr_float_backend<digits10, AllocationType>& val) BOOST_NOEXCEPT
+{
+ *result = mpfr_get_flt(val.data(), GMP_RNDN);
+}
+template <unsigned digits10, mpfr_allocation_type AllocationType>
inline void eval_convert_to(double* result, const mpfr_float_backend<digits10, AllocationType>& val) BOOST_NOEXCEPT
{
*result = mpfr_get_d(val.data(), GMP_RNDN);
diff --git a/boost/multiprecision/number.hpp b/boost/multiprecision/number.hpp
index 9d8b64b20e..fca63661e3 100644
--- a/boost/multiprecision/number.hpp
+++ b/boost/multiprecision/number.hpp
@@ -604,7 +604,7 @@ public:
//
// Use in boolean context, and explicit conversion operators:
//
-#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
+#ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
# if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
//
// Horrible workaround for gcc-4.6.x which always prefers the template
@@ -1761,7 +1761,12 @@ inline std::istream& operator >> (std::istream& is, number<Backend, ExpressionTe
switch(boost::multiprecision::number_category<number<Backend, ExpressionTemplates> >::value)
{
case boost::multiprecision::number_kind_integer:
- s = detail::read_string_while(is, "+-0xX123456789");
+ if(oct_format)
+ s = detail::read_string_while(is, "+-01234567");
+ else if(hex_format)
+ s = detail::read_string_while(is, "+-xXabcdefABCDEF0123456789");
+ else
+ s = detail::read_string_while(is, "+-0123456789");
break;
case boost::multiprecision::number_kind_floating_point:
s = detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY");
@@ -1863,6 +1868,54 @@ typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator
return a != multiprecision::number<T, ExpressionTemplates>(b);
}
+template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
+typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator < (const rational<multiprecision::number<T, ExpressionTemplates> >& a, const Arithmetic& b)
+{
+ return a < multiprecision::number<T, ExpressionTemplates>(b);
+}
+
+template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
+typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator < (const Arithmetic& b, const rational<multiprecision::number<T, ExpressionTemplates> >& a)
+{
+ return a > multiprecision::number<T, ExpressionTemplates>(b);
+}
+
+template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
+typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator <= (const rational<multiprecision::number<T, ExpressionTemplates> >& a, const Arithmetic& b)
+{
+ return a <= multiprecision::number<T, ExpressionTemplates>(b);
+}
+
+template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
+typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator <= (const Arithmetic& b, const rational<multiprecision::number<T, ExpressionTemplates> >& a)
+{
+ return a >= multiprecision::number<T, ExpressionTemplates>(b);
+}
+
+template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
+typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator > (const rational<multiprecision::number<T, ExpressionTemplates> >& a, const Arithmetic& b)
+{
+ return a > multiprecision::number<T, ExpressionTemplates>(b);
+}
+
+template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
+typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator > (const Arithmetic& b, const rational<multiprecision::number<T, ExpressionTemplates> >& a)
+{
+ return a < multiprecision::number<T, ExpressionTemplates>(b);
+}
+
+template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
+typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator >= (const rational<multiprecision::number<T, ExpressionTemplates> >& a, const Arithmetic& b)
+{
+ return a >= multiprecision::number<T, ExpressionTemplates>(b);
+}
+
+template <class T, multiprecision::expression_template_option ExpressionTemplates, class Arithmetic>
+typename boost::enable_if<boost::is_arithmetic<Arithmetic>, bool>::type operator >= (const Arithmetic& b, const rational<multiprecision::number<T, ExpressionTemplates> >& a)
+{
+ return a <= multiprecision::number<T, ExpressionTemplates>(b);
+}
+
template <class T, multiprecision::expression_template_option ExpressionTemplates>
inline multiprecision::number<T, ExpressionTemplates> numerator(const rational<multiprecision::number<T, ExpressionTemplates> >& a)
{
diff --git a/boost/multiprecision/tommath.hpp b/boost/multiprecision/tommath.hpp
index 346e5395b4..3d576051ae 100644
--- a/boost/multiprecision/tommath.hpp
+++ b/boost/multiprecision/tommath.hpp
@@ -415,21 +415,29 @@ inline void eval_left_shift(tommath_int& t, UI i)
template <class UI>
inline void eval_right_shift(tommath_int& t, UI i)
{
+ using default_ops::eval_increment;
+ using default_ops::eval_decrement;
+ bool neg = eval_get_sign(t) < 0;
tommath_int d;
+ if(neg)
+ eval_increment(t);
detail::check_tommath_result(mp_div_2d(&t.data(), static_cast<unsigned>(i), &t.data(), &d.data()));
+ if(neg)
+ eval_decrement(t);
}
template <class UI>
inline void eval_left_shift(tommath_int& t, const tommath_int& v, UI i)
{
detail::check_tommath_result(mp_mul_2d(const_cast< ::mp_int*>(&v.data()), static_cast<unsigned>(i), &t.data()));
}
+/*
template <class UI>
inline void eval_right_shift(tommath_int& t, const tommath_int& v, UI i)
{
tommath_int d;
detail::check_tommath_result(mp_div_2d(const_cast< ::mp_int*>(&v.data()), static_cast<unsigned long>(i), &t.data(), &d.data()));
}
-
+*/
inline void eval_bitwise_and(tommath_int& result, const tommath_int& v)
{
BOOST_MP_TOMMATH_BIT_OP_CHECK(result);
diff --git a/boost/none.hpp b/boost/none.hpp
index db744e58ac..a37c45c514 100644
--- a/boost/none.hpp
+++ b/boost/none.hpp
@@ -1,5 +1,5 @@
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
-// Copyright (C) 2014 Andrzej Krzemienski.
+// Copyright (C) 2014, 2015 Andrzej Krzemienski.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
diff --git a/boost/none_t.hpp b/boost/none_t.hpp
index 608cb0c354..008f369d1c 100644
--- a/boost/none_t.hpp
+++ b/boost/none_t.hpp
@@ -1,5 +1,5 @@
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
-// Copyright (C) 2014 Andrzej Krzemienski.
+// Copyright (C) 2014, 2015 Andrzej Krzemienski.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -29,7 +29,7 @@ class none_t {};
struct none_t
{
struct init_tag{};
- explicit none_t(init_tag){} // to prevent default constructor
+ explicit none_t(init_tag){} // to disable default constructor
};
#endif // old implementation workarounds
@@ -37,4 +37,3 @@ struct none_t
} // namespace boost
#endif // header guard
-
diff --git a/boost/operators.hpp b/boost/operators.hpp
index ab203304c7..3fc08d5e8d 100644
--- a/boost/operators.hpp
+++ b/boost/operators.hpp
@@ -1,6 +1,7 @@
// Boost operators.hpp header file ----------------------------------------//
// (C) Copyright David Abrahams, Jeremy Siek, Daryle Walker 1999-2001.
+// (C) Copyright Daniel Frey 2002-2016.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -8,6 +9,8 @@
// See http://www.boost.org/libs/utility/operators.htm for documentation.
// Revision History
+// 22 Feb 16 Added ADL protection, preserve old work-arounds in
+// operators_v1.hpp and clean up this file. (Daniel Frey)
// 16 Dec 10 Limit warning suppression for 4284 to older versions of VC++
// (Matthew Bradbury, fixes #4432)
// 07 Aug 08 Added "euclidean" spelling. (Daniel Frey)
@@ -24,8 +27,8 @@
// additional classes for groups of related operators added;
// workaround for empty base class optimization
// bug of GCC 3.0 (Helmut Zeisel)
-// 25 Jun 01 output_iterator_helper changes: removed default template
-// parameters, added support for self-proxying, additional
+// 25 Jun 01 output_iterator_helper changes: removed default template
+// parameters, added support for self-proxying, additional
// documentation and tests (Aleksey Gurtovoy)
// 29 May 01 Added operator classes for << and >>. Added input and output
// iterator helper classes. Added classes to connect equality and
@@ -38,18 +41,18 @@
// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
// refactoring of compiler workarounds, additional documentation
// (Alexy Gurtovoy and Mark Rodgers with some help and prompting from
-// Dave Abrahams)
+// Dave Abrahams)
// 28 Jun 00 General cleanup and integration of bugfixes from Mark Rodgers and
// Jeremy Siek (Dave Abrahams)
// 20 Jun 00 Changes to accommodate Borland C++Builder 4 and Borland C++ 5.5
// (Mark Rodgers)
// 20 Jun 00 Minor fixes to the prior revision (Aleksey Gurtovoy)
// 10 Jun 00 Support for the base class chaining technique was added
-// (Aleksey Gurtovoy). See documentation and the comments below
-// for the details.
+// (Aleksey Gurtovoy). See documentation and the comments below
+// for the details.
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
// 18 Nov 99 Change name "divideable" to "dividable", remove unnecessary
-// specializations of dividable, subtractable, modable (Ed Brey)
+// specializations of dividable, subtractable, modable (Ed Brey)
// 17 Nov 99 Add comments (Beman Dawes)
// Remove unnecessary specialization of operators<> (Ed Brey)
// 15 Nov 99 Fix less_than_comparable<T,U> second operand type for first two
@@ -60,8 +63,8 @@
// 10 Nov 99 Initial version
// 10 Jun 00:
-// An additional optional template parameter was added to most of
-// operator templates to support the base class chaining technique (see
+// An additional optional template parameter was added to most of
+// operator templates to support the base class chaining technique (see
// documentation for the details). Unfortunately, a straightforward
// implementation of this change would have broken compatibility with the
// previous version of the library by making it impossible to use the same
@@ -70,18 +73,24 @@
// issue at the cost of some simplicity.
//
// One of the complications is an existence of special auxiliary class template
-// 'is_chained_base<>' (see 'detail' namespace below), which is used
+// 'is_chained_base<>' (see 'operators_detail' namespace below), which is used
// to determine whether its template parameter is a library's operator template
-// or not. You have to specialize 'is_chained_base<>' for each new
+// or not. You have to specialize 'is_chained_base<>' for each new
// operator template you add to the library.
//
-// However, most of the non-trivial implementation details are hidden behind
+// However, most of the non-trivial implementation details are hidden behind
// several local macros defined below, and as soon as you understand them,
-// you understand the whole library implementation.
+// you understand the whole library implementation.
#ifndef BOOST_OPERATORS_HPP
#define BOOST_OPERATORS_HPP
+// If old work-arounds are needed, refer to the preserved version without
+// ADL protection.
+#if defined(BOOST_NO_OPERATORS_IN_NAMESPACE) || defined(BOOST_USE_OPERATORS_V1)
+#include "operators_v1.hpp"
+#else
+
#include <cstddef>
#include <iterator>
@@ -93,35 +102,30 @@
#endif
#if BOOST_WORKAROUND(BOOST_MSVC, < 1600)
-# pragma warning( disable : 4284 ) // complaint about return type of
+# pragma warning( disable : 4284 ) // complaint about return type of
#endif // operator-> not begin a UDT
-namespace boost {
-namespace detail {
-
-template <typename T> class empty_base {};
-
-} // namespace detail
-} // namespace boost
-
// In this section we supply the xxxx1 and xxxx2 forms of the operator
// templates, which are explicitly targeted at the 1-type-argument and
-// 2-type-argument operator forms, respectively. Some compilers get confused
-// when inline friend functions are overloaded in namespaces other than the
-// global namespace. When BOOST_NO_OPERATORS_IN_NAMESPACE is defined, all of
-// these templates must go in the global namespace.
+// 2-type-argument operator forms, respectively.
-#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
namespace boost
{
-#endif
+namespace operators_impl
+{
+namespace operators_detail
+{
+
+template <typename T> class empty_base {};
+
+} // namespace operators_detail
// Basic operator classes (contributed by Dave Abrahams) ------------------//
// Note that friend functions defined in a class are implicitly inline.
// See the C++ std, 11.4 [class.friend] paragraph 5
-template <class T, class U, class B = ::boost::detail::empty_base<T> >
+template <class T, class U, class B = operators_detail::empty_base<T> >
struct less_than_comparable2 : B
{
friend bool operator<=(const T& x, const U& y) { return !static_cast<bool>(x > y); }
@@ -132,7 +136,7 @@ struct less_than_comparable2 : B
friend bool operator>=(const U& x, const T& y) { return !static_cast<bool>(y > x); }
};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct less_than_comparable1 : B
{
friend bool operator>(const T& x, const T& y) { return y < x; }
@@ -140,7 +144,7 @@ struct less_than_comparable1 : B
friend bool operator>=(const T& x, const T& y) { return !static_cast<bool>(x < y); }
};
-template <class T, class U, class B = ::boost::detail::empty_base<T> >
+template <class T, class U, class B = operators_detail::empty_base<T> >
struct equality_comparable2 : B
{
friend bool operator==(const U& y, const T& x) { return x == y; }
@@ -148,7 +152,7 @@ struct equality_comparable2 : B
friend bool operator!=(const T& y, const U& x) { return !static_cast<bool>(y == x); }
};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct equality_comparable1 : B
{
friend bool operator!=(const T& x, const T& y) { return !static_cast<bool>(x == y); }
@@ -166,39 +170,39 @@ struct equality_comparable1 : B
// If the compiler has no NRVO, this is the best symmetric
// implementation available.
-#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
-template <class T, class U, class B = ::boost::detail::empty_base<T> > \
-struct NAME##2 : B \
-{ \
- friend T operator OP( const T& lhs, const U& rhs ) \
- { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
- friend T operator OP( const U& lhs, const T& rhs ) \
- { T nrv( rhs ); nrv OP##= lhs; return nrv; } \
-}; \
- \
-template <class T, class B = ::boost::detail::empty_base<T> > \
-struct NAME##1 : B \
-{ \
- friend T operator OP( const T& lhs, const T& rhs ) \
- { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
+#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
+template <class T, class U, class B = operators_detail::empty_base<T> > \
+struct NAME##2 : B \
+{ \
+ friend T operator OP( const T& lhs, const U& rhs ) \
+ { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
+ friend T operator OP( const U& lhs, const T& rhs ) \
+ { T nrv( rhs ); nrv OP##= lhs; return nrv; } \
+}; \
+ \
+template <class T, class B = operators_detail::empty_base<T> > \
+struct NAME##1 : B \
+{ \
+ friend T operator OP( const T& lhs, const T& rhs ) \
+ { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
};
#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
-template <class T, class U, class B = ::boost::detail::empty_base<T> > \
+template <class T, class U, class B = operators_detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( const T& lhs, const U& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; \
\
-template <class T, class U, class B = ::boost::detail::empty_base<T> > \
+template <class T, class U, class B = operators_detail::empty_base<T> > \
struct BOOST_OPERATOR2_LEFT(NAME) : B \
{ \
friend T operator OP( const U& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; \
\
-template <class T, class B = ::boost::detail::empty_base<T> > \
+template <class T, class B = operators_detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( const T& lhs, const T& rhs ) \
@@ -213,34 +217,34 @@ struct NAME##1 : B \
// optimization opportunities to the compiler :)
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
-template <class T, class U, class B = ::boost::detail::empty_base<T> > \
+template <class T, class U, class B = operators_detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \
}; \
\
-template <class T, class B = ::boost::detail::empty_base<T> > \
+template <class T, class B = operators_detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
};
#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
-template <class T, class U, class B = ::boost::detail::empty_base<T> > \
+template <class T, class U, class B = operators_detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
}; \
\
-template <class T, class U, class B = ::boost::detail::empty_base<T> > \
+template <class T, class U, class B = operators_detail::empty_base<T> > \
struct BOOST_OPERATOR2_LEFT(NAME) : B \
{ \
friend T operator OP( const U& lhs, const T& rhs ) \
{ return T( lhs ) OP##= rhs; } \
}; \
\
-template <class T, class B = ::boost::detail::empty_base<T> > \
+template <class T, class B = operators_detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
@@ -263,7 +267,7 @@ BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | )
// incrementable and decrementable contributed by Jeremy Siek
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct incrementable : B
{
friend T operator++(T& x, int)
@@ -276,7 +280,7 @@ private: // The use of this typedef works around a Borland bug
typedef T incrementable_type;
};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct decrementable : B
{
friend T operator--(T& x, int)
@@ -291,16 +295,16 @@ private: // The use of this typedef works around a Borland bug
// Iterator operator classes (contributed by Jeremy Siek) ------------------//
-template <class T, class P, class B = ::boost::detail::empty_base<T> >
+template <class T, class P, class B = operators_detail::empty_base<T> >
struct dereferenceable : B
{
P operator->() const
- {
- return &*static_cast<const T&>(*this);
+ {
+ return &*static_cast<const T&>(*this);
}
};
-template <class T, class I, class R, class B = ::boost::detail::empty_base<T> >
+template <class T, class I, class R, class B = operators_detail::empty_base<T> >
struct indexable : B
{
R operator[](I n) const
@@ -314,34 +318,34 @@ struct indexable : B
#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
-#define BOOST_BINARY_OPERATOR( NAME, OP ) \
-template <class T, class U, class B = ::boost::detail::empty_base<T> > \
-struct NAME##2 : B \
-{ \
- friend T operator OP( const T& lhs, const U& rhs ) \
- { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
-}; \
- \
-template <class T, class B = ::boost::detail::empty_base<T> > \
-struct NAME##1 : B \
-{ \
- friend T operator OP( const T& lhs, const T& rhs ) \
- { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
+#define BOOST_BINARY_OPERATOR( NAME, OP ) \
+template <class T, class U, class B = operators_detail::empty_base<T> > \
+struct NAME##2 : B \
+{ \
+ friend T operator OP( const T& lhs, const U& rhs ) \
+ { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
+}; \
+ \
+template <class T, class B = operators_detail::empty_base<T> > \
+struct NAME##1 : B \
+{ \
+ friend T operator OP( const T& lhs, const T& rhs ) \
+ { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
};
#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
-#define BOOST_BINARY_OPERATOR( NAME, OP ) \
-template <class T, class U, class B = ::boost::detail::empty_base<T> > \
-struct NAME##2 : B \
-{ \
- friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
-}; \
- \
-template <class T, class B = ::boost::detail::empty_base<T> > \
-struct NAME##1 : B \
-{ \
- friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
+#define BOOST_BINARY_OPERATOR( NAME, OP ) \
+template <class T, class U, class B = operators_detail::empty_base<T> > \
+struct NAME##2 : B \
+{ \
+ friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
+}; \
+ \
+template <class T, class B = operators_detail::empty_base<T> > \
+struct NAME##1 : B \
+{ \
+ friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
};
#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
@@ -351,7 +355,7 @@ BOOST_BINARY_OPERATOR( right_shiftable, >> )
#undef BOOST_BINARY_OPERATOR
-template <class T, class U, class B = ::boost::detail::empty_base<T> >
+template <class T, class U, class B = operators_detail::empty_base<T> >
struct equivalent2 : B
{
friend bool operator==(const T& x, const U& y)
@@ -360,7 +364,7 @@ struct equivalent2 : B
}
};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct equivalent1 : B
{
friend bool operator==(const T&x, const T&y)
@@ -369,7 +373,7 @@ struct equivalent1 : B
}
};
-template <class T, class U, class B = ::boost::detail::empty_base<T> >
+template <class T, class U, class B = operators_detail::empty_base<T> >
struct partially_ordered2 : B
{
friend bool operator<=(const T& x, const U& y)
@@ -386,7 +390,7 @@ struct partially_ordered2 : B
{ return static_cast<bool>(y < x) || static_cast<bool>(y == x); }
};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct partially_ordered1 : B
{
friend bool operator>(const T& x, const T& y)
@@ -399,161 +403,161 @@ struct partially_ordered1 : B
// Combined operator classes (contributed by Daryle Walker) ----------------//
-template <class T, class U, class B = ::boost::detail::empty_base<T> >
+template <class T, class U, class B = operators_detail::empty_base<T> >
struct totally_ordered2
: less_than_comparable2<T, U
, equality_comparable2<T, U, B
> > {};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct totally_ordered1
: less_than_comparable1<T
, equality_comparable1<T, B
> > {};
-template <class T, class U, class B = ::boost::detail::empty_base<T> >
+template <class T, class U, class B = operators_detail::empty_base<T> >
struct additive2
: addable2<T, U
, subtractable2<T, U, B
> > {};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct additive1
: addable1<T
, subtractable1<T, B
> > {};
-template <class T, class U, class B = ::boost::detail::empty_base<T> >
+template <class T, class U, class B = operators_detail::empty_base<T> >
struct multiplicative2
: multipliable2<T, U
, dividable2<T, U, B
> > {};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct multiplicative1
: multipliable1<T
, dividable1<T, B
> > {};
-template <class T, class U, class B = ::boost::detail::empty_base<T> >
+template <class T, class U, class B = operators_detail::empty_base<T> >
struct integer_multiplicative2
: multiplicative2<T, U
, modable2<T, U, B
> > {};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct integer_multiplicative1
: multiplicative1<T
, modable1<T, B
> > {};
-template <class T, class U, class B = ::boost::detail::empty_base<T> >
+template <class T, class U, class B = operators_detail::empty_base<T> >
struct arithmetic2
: additive2<T, U
, multiplicative2<T, U, B
> > {};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct arithmetic1
: additive1<T
, multiplicative1<T, B
> > {};
-template <class T, class U, class B = ::boost::detail::empty_base<T> >
+template <class T, class U, class B = operators_detail::empty_base<T> >
struct integer_arithmetic2
: additive2<T, U
, integer_multiplicative2<T, U, B
> > {};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct integer_arithmetic1
: additive1<T
, integer_multiplicative1<T, B
> > {};
-template <class T, class U, class B = ::boost::detail::empty_base<T> >
+template <class T, class U, class B = operators_detail::empty_base<T> >
struct bitwise2
: xorable2<T, U
, andable2<T, U
, orable2<T, U, B
> > > {};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct bitwise1
: xorable1<T
, andable1<T
, orable1<T, B
> > > {};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct unit_steppable
: incrementable<T
, decrementable<T, B
> > {};
-template <class T, class U, class B = ::boost::detail::empty_base<T> >
+template <class T, class U, class B = operators_detail::empty_base<T> >
struct shiftable2
: left_shiftable2<T, U
, right_shiftable2<T, U, B
> > {};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct shiftable1
: left_shiftable1<T
, right_shiftable1<T, B
> > {};
-template <class T, class U, class B = ::boost::detail::empty_base<T> >
+template <class T, class U, class B = operators_detail::empty_base<T> >
struct ring_operators2
: additive2<T, U
, subtractable2_left<T, U
, multipliable2<T, U, B
> > > {};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct ring_operators1
: additive1<T
, multipliable1<T, B
> > {};
-template <class T, class U, class B = ::boost::detail::empty_base<T> >
+template <class T, class U, class B = operators_detail::empty_base<T> >
struct ordered_ring_operators2
: ring_operators2<T, U
, totally_ordered2<T, U, B
> > {};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct ordered_ring_operators1
: ring_operators1<T
, totally_ordered1<T, B
> > {};
-template <class T, class U, class B = ::boost::detail::empty_base<T> >
+template <class T, class U, class B = operators_detail::empty_base<T> >
struct field_operators2
: ring_operators2<T, U
, dividable2<T, U
, dividable2_left<T, U, B
> > > {};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct field_operators1
: ring_operators1<T
, dividable1<T, B
> > {};
-template <class T, class U, class B = ::boost::detail::empty_base<T> >
+template <class T, class U, class B = operators_detail::empty_base<T> >
struct ordered_field_operators2
: field_operators2<T, U
, totally_ordered2<T, U, B
> > {};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct ordered_field_operators1
: field_operators1<T
, totally_ordered1<T, B
> > {};
-template <class T, class U, class B = ::boost::detail::empty_base<T> >
+template <class T, class U, class B = operators_detail::empty_base<T> >
struct euclidian_ring_operators2
: ring_operators2<T, U
, dividable2<T, U
@@ -562,26 +566,26 @@ struct euclidian_ring_operators2
, modable2_left<T, U, B
> > > > > {};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct euclidian_ring_operators1
: ring_operators1<T
, dividable1<T
, modable1<T, B
> > > {};
-template <class T, class U, class B = ::boost::detail::empty_base<T> >
+template <class T, class U, class B = operators_detail::empty_base<T> >
struct ordered_euclidian_ring_operators2
: totally_ordered2<T, U
, euclidian_ring_operators2<T, U, B
> > {};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct ordered_euclidian_ring_operators1
: totally_ordered1<T
, euclidian_ring_operators1<T, B
> > {};
-template <class T, class U, class B = ::boost::detail::empty_base<T> >
+template <class T, class U, class B = operators_detail::empty_base<T> >
struct euclidean_ring_operators2
: ring_operators2<T, U
, dividable2<T, U
@@ -590,43 +594,43 @@ struct euclidean_ring_operators2
, modable2_left<T, U, B
> > > > > {};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct euclidean_ring_operators1
: ring_operators1<T
, dividable1<T
, modable1<T, B
> > > {};
-template <class T, class U, class B = ::boost::detail::empty_base<T> >
+template <class T, class U, class B = operators_detail::empty_base<T> >
struct ordered_euclidean_ring_operators2
: totally_ordered2<T, U
, euclidean_ring_operators2<T, U, B
> > {};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct ordered_euclidean_ring_operators1
: totally_ordered1<T
, euclidean_ring_operators1<T, B
> > {};
-template <class T, class P, class B = ::boost::detail::empty_base<T> >
+template <class T, class P, class B = operators_detail::empty_base<T> >
struct input_iteratable
: equality_comparable1<T
, incrementable<T
, dereferenceable<T, P, B
> > > {};
-template <class T, class B = ::boost::detail::empty_base<T> >
+template <class T, class B = operators_detail::empty_base<T> >
struct output_iteratable
: incrementable<T, B
> {};
-template <class T, class P, class B = ::boost::detail::empty_base<T> >
+template <class T, class P, class B = operators_detail::empty_base<T> >
struct forward_iteratable
: input_iteratable<T, P, B
> {};
-template <class T, class P, class B = ::boost::detail::empty_base<T> >
+template <class T, class P, class B = operators_detail::empty_base<T> >
struct bidirectional_iteratable
: forward_iteratable<T, P
, decrementable<T, B
@@ -636,7 +640,7 @@ struct bidirectional_iteratable
// which is an indirect base class of bidirectional_iterable,
// random_access_iteratable must not be derived from totally_ordered1
// but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001)
-template <class T, class P, class D, class R, class B = ::boost::detail::empty_base<T> >
+template <class T, class P, class D, class R, class B = operators_detail::empty_base<T> >
struct random_access_iteratable
: bidirectional_iteratable<T, P
, less_than_comparable1<T
@@ -644,124 +648,64 @@ struct random_access_iteratable
, indexable<T, D, R, B
> > > > {};
-#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
-} // namespace boost
-#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
-
-// BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE4 -
//
-// When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an
-// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used
-// for one-argument forms of operator templates; BOOST_IMPORT_TEMPLATE2 for
-// two-argument forms. Note that these macros expect to be invoked from within
-// boost.
-
-#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
-
- // The template is already in boost so we have nothing to do.
-# define BOOST_IMPORT_TEMPLATE4(template_name)
-# define BOOST_IMPORT_TEMPLATE3(template_name)
-# define BOOST_IMPORT_TEMPLATE2(template_name)
-# define BOOST_IMPORT_TEMPLATE1(template_name)
-
-#else // BOOST_NO_OPERATORS_IN_NAMESPACE
-
-# ifndef BOOST_NO_USING_TEMPLATE
-
- // Bring the names in with a using-declaration
- // to avoid stressing the compiler.
-# define BOOST_IMPORT_TEMPLATE4(template_name) using ::template_name;
-# define BOOST_IMPORT_TEMPLATE3(template_name) using ::template_name;
-# define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name;
-# define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name;
-
-# else
-
- // Otherwise, because a Borland C++ 5.5 bug prevents a using declaration
- // from working, we are forced to use inheritance for that compiler.
-# define BOOST_IMPORT_TEMPLATE4(template_name) \
- template <class T, class U, class V, class W, class B = ::boost::detail::empty_base<T> > \
- struct template_name : ::template_name<T, U, V, W, B> {};
-
-# define BOOST_IMPORT_TEMPLATE3(template_name) \
- template <class T, class U, class V, class B = ::boost::detail::empty_base<T> > \
- struct template_name : ::template_name<T, U, V, B> {};
-
-# define BOOST_IMPORT_TEMPLATE2(template_name) \
- template <class T, class U, class B = ::boost::detail::empty_base<T> > \
- struct template_name : ::template_name<T, U, B> {};
-
-# define BOOST_IMPORT_TEMPLATE1(template_name) \
- template <class T, class B = ::boost::detail::empty_base<T> > \
- struct template_name : ::template_name<T, B> {};
+// Here's where we put it all together, defining the xxxx forms of the templates.
+// We also define specializations of is_chained_base<> for
+// the xxxx, xxxx1, and xxxx2 templates.
+//
-# endif // BOOST_NO_USING_TEMPLATE
+namespace operators_detail
+{
-#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
+// A type parameter is used instead of a plain bool because Borland's compiler
+// didn't cope well with the more obvious non-type template parameter.
+struct true_t {};
+struct false_t {};
-//
-// Here's where we put it all together, defining the xxxx forms of the templates
-// in namespace boost. We also define specializations of is_chained_base<> for
-// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
-// necessary.
-//
+} // namespace operators_detail
// is_chained_base<> - a traits class used to distinguish whether an operator
// template argument is being used for base class chaining, or is specifying a
// 2nd argument type.
-namespace boost {
-// A type parameter is used instead of a plain bool because Borland's compiler
-// didn't cope well with the more obvious non-type template parameter.
-namespace detail {
- struct true_t {};
- struct false_t {};
-} // namespace detail
-
// Unspecialized version assumes that most types are not being used for base
// class chaining. We specialize for the operator templates defined in this
// library.
template<class T> struct is_chained_base {
- typedef ::boost::detail::false_t value;
+ typedef operators_detail::false_t value;
};
-} // namespace boost
-
-// Import a 4-type-argument operator template into boost (if necessary) and
-// provide a specialization of 'is_chained_base<>' for it.
-# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
- BOOST_IMPORT_TEMPLATE4(template_name4) \
- template<class T, class U, class V, class W, class B> \
- struct is_chained_base< ::boost::template_name4<T, U, V, W, B> > { \
- typedef ::boost::detail::true_t value; \
+// Provide a specialization of 'is_chained_base<>'
+// for a 4-type-argument operator template.
+# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
+ template<class T, class U, class V, class W, class B> \
+ struct is_chained_base< template_name4<T, U, V, W, B> > { \
+ typedef operators_detail::true_t value; \
};
-// Import a 3-type-argument operator template into boost (if necessary) and
-// provide a specialization of 'is_chained_base<>' for it.
-# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
- BOOST_IMPORT_TEMPLATE3(template_name3) \
- template<class T, class U, class V, class B> \
- struct is_chained_base< ::boost::template_name3<T, U, V, B> > { \
- typedef ::boost::detail::true_t value; \
+// Provide a specialization of 'is_chained_base<>'
+// for a 3-type-argument operator template.
+# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
+ template<class T, class U, class V, class B> \
+ struct is_chained_base< template_name3<T, U, V, B> > { \
+ typedef operators_detail::true_t value; \
};
-// Import a 2-type-argument operator template into boost (if necessary) and
-// provide a specialization of 'is_chained_base<>' for it.
-# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
- BOOST_IMPORT_TEMPLATE2(template_name2) \
- template<class T, class U, class B> \
- struct is_chained_base< ::boost::template_name2<T, U, B> > { \
- typedef ::boost::detail::true_t value; \
+// Provide a specialization of 'is_chained_base<>'
+// for a 2-type-argument operator template.
+# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
+ template<class T, class U, class B> \
+ struct is_chained_base< template_name2<T, U, B> > { \
+ typedef operators_detail::true_t value; \
};
-// Import a 1-type-argument operator template into boost (if necessary) and
-// provide a specialization of 'is_chained_base<>' for it.
-# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
- BOOST_IMPORT_TEMPLATE1(template_name1) \
- template<class T, class B> \
- struct is_chained_base< ::boost::template_name1<T, B> > { \
- typedef ::boost::detail::true_t value; \
+// Provide a specialization of 'is_chained_base<>'
+// for a 1-type-argument operator template.
+# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
+ template<class T, class B> \
+ struct is_chained_base< template_name1<T, B> > { \
+ typedef operators_detail::true_t value; \
};
// BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it
@@ -778,34 +722,34 @@ template<class T> struct is_chained_base {
// implementation in terms of either '<template_name>1' or '<template_name>2'.
//
-# define BOOST_OPERATOR_TEMPLATE(template_name) \
-template <class T \
- ,class U = T \
- ,class B = ::boost::detail::empty_base<T> \
- ,class O = typename is_chained_base<U>::value \
- > \
-struct template_name : template_name##2<T, U, B> {}; \
- \
-template<class T, class U, class B> \
-struct template_name<T, U, B, ::boost::detail::true_t> \
- : template_name##1<T, U> {}; \
- \
-template <class T, class B> \
-struct template_name<T, T, B, ::boost::detail::false_t> \
- : template_name##1<T, B> {}; \
- \
-template<class T, class U, class B, class O> \
-struct is_chained_base< ::boost::template_name<T, U, B, O> > { \
- typedef ::boost::detail::true_t value; \
-}; \
- \
-BOOST_OPERATOR_TEMPLATE2(template_name##2) \
+# define BOOST_OPERATOR_TEMPLATE(template_name) \
+template <class T \
+ ,class U = T \
+ ,class B = operators_detail::empty_base<T> \
+ ,class O = typename is_chained_base<U>::value \
+ > \
+struct template_name; \
+ \
+template<class T, class U, class B> \
+struct template_name<T, U, B, operators_detail::false_t> \
+ : template_name##2<T, U, B> {}; \
+ \
+template<class T, class U> \
+struct template_name<T, U, operators_detail::empty_base<T>, operators_detail::true_t> \
+ : template_name##1<T, U> {}; \
+ \
+template <class T, class B> \
+struct template_name<T, T, B, operators_detail::false_t> \
+ : template_name##1<T, B> {}; \
+ \
+template<class T, class U, class B, class O> \
+struct is_chained_base< template_name<T, U, B, O> > { \
+ typedef operators_detail::true_t value; \
+}; \
+ \
+BOOST_OPERATOR_TEMPLATE2(template_name##2) \
BOOST_OPERATOR_TEMPLATE1(template_name##1)
-
-
-namespace boost {
-
BOOST_OPERATOR_TEMPLATE(less_than_comparable)
BOOST_OPERATOR_TEMPLATE(equality_comparable)
BOOST_OPERATOR_TEMPLATE(multipliable)
@@ -859,13 +803,7 @@ BOOST_OPERATOR_TEMPLATE4(random_access_iteratable)
#undef BOOST_OPERATOR_TEMPLATE3
#undef BOOST_OPERATOR_TEMPLATE2
#undef BOOST_OPERATOR_TEMPLATE1
-#undef BOOST_IMPORT_TEMPLATE1
-#undef BOOST_IMPORT_TEMPLATE2
-#undef BOOST_IMPORT_TEMPLATE3
-#undef BOOST_IMPORT_TEMPLATE4
-// The following 'operators' classes can only be used portably if the derived class
-// declares ALL of the required member operators.
template <class T, class U>
struct operators2
: totally_ordered2<T,U
@@ -927,7 +865,7 @@ struct bidirectional_iterator_helper
> > {};
template <class T,
- class V,
+ class V,
class D = std::ptrdiff_t,
class P = V*,
class R = V&>
@@ -941,10 +879,14 @@ struct random_access_iterator_helper
}
}; // random_access_iterator_helper
+} // namespace operators_impl
+using namespace operators_impl;
+
} // namespace boost
#if defined(__sgi) && !defined(__GNUC__)
#pragma reset woff 1234
#endif
+#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
#endif // BOOST_OPERATORS_HPP
diff --git a/boost/operators_v1.hpp b/boost/operators_v1.hpp
new file mode 100644
index 0000000000..e1c53e8703
--- /dev/null
+++ b/boost/operators_v1.hpp
@@ -0,0 +1,951 @@
+// Boost operators.hpp header file ----------------------------------------//
+
+// (C) Copyright David Abrahams, Jeremy Siek, Daryle Walker 1999-2001.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/utility/operators.htm for documentation.
+
+// Revision History
+// 22 Feb 16 Preserve old work-arounds. (Daniel Frey)
+// 16 Dec 10 Limit warning suppression for 4284 to older versions of VC++
+// (Matthew Bradbury, fixes #4432)
+// 07 Aug 08 Added "euclidean" spelling. (Daniel Frey)
+// 03 Apr 08 Make sure "convertible to bool" is sufficient
+// for T::operator<, etc. (Daniel Frey)
+// 24 May 07 Changed empty_base to depend on T, see
+// http://svn.boost.org/trac/boost/ticket/979
+// 21 Oct 02 Modified implementation of operators to allow compilers with a
+// correct named return value optimization (NRVO) to produce optimal
+// code. (Daniel Frey)
+// 02 Dec 01 Bug fixed in random_access_iteratable. (Helmut Zeisel)
+// 28 Sep 01 Factored out iterator operator groups. (Daryle Walker)
+// 27 Aug 01 'left' form for non commutative operators added;
+// additional classes for groups of related operators added;
+// workaround for empty base class optimization
+// bug of GCC 3.0 (Helmut Zeisel)
+// 25 Jun 01 output_iterator_helper changes: removed default template
+// parameters, added support for self-proxying, additional
+// documentation and tests (Aleksey Gurtovoy)
+// 29 May 01 Added operator classes for << and >>. Added input and output
+// iterator helper classes. Added classes to connect equality and
+// relational operators. Added classes for groups of related
+// operators. Reimplemented example operator and iterator helper
+// classes in terms of the new groups. (Daryle Walker, with help
+// from Alexy Gurtovoy)
+// 11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly
+// supplied arguments from actually being used (Dave Abrahams)
+// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
+// refactoring of compiler workarounds, additional documentation
+// (Alexy Gurtovoy and Mark Rodgers with some help and prompting from
+// Dave Abrahams)
+// 28 Jun 00 General cleanup and integration of bugfixes from Mark Rodgers and
+// Jeremy Siek (Dave Abrahams)
+// 20 Jun 00 Changes to accommodate Borland C++Builder 4 and Borland C++ 5.5
+// (Mark Rodgers)
+// 20 Jun 00 Minor fixes to the prior revision (Aleksey Gurtovoy)
+// 10 Jun 00 Support for the base class chaining technique was added
+// (Aleksey Gurtovoy). See documentation and the comments below
+// for the details.
+// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
+// 18 Nov 99 Change name "divideable" to "dividable", remove unnecessary
+// specializations of dividable, subtractable, modable (Ed Brey)
+// 17 Nov 99 Add comments (Beman Dawes)
+// Remove unnecessary specialization of operators<> (Ed Brey)
+// 15 Nov 99 Fix less_than_comparable<T,U> second operand type for first two
+// operators.(Beman Dawes)
+// 12 Nov 99 Add operators templates (Ed Brey)
+// 11 Nov 99 Add single template parameter version for compilers without
+// partial specialization (Beman Dawes)
+// 10 Nov 99 Initial version
+
+// 10 Jun 00:
+// An additional optional template parameter was added to most of
+// operator templates to support the base class chaining technique (see
+// documentation for the details). Unfortunately, a straightforward
+// implementation of this change would have broken compatibility with the
+// previous version of the library by making it impossible to use the same
+// template name (e.g. 'addable') for both the 1- and 2-argument versions of
+// an operator template. This implementation solves the backward-compatibility
+// issue at the cost of some simplicity.
+//
+// One of the complications is an existence of special auxiliary class template
+// 'is_chained_base<>' (see 'detail' namespace below), which is used
+// to determine whether its template parameter is a library's operator template
+// or not. You have to specialize 'is_chained_base<>' for each new
+// operator template you add to the library.
+//
+// However, most of the non-trivial implementation details are hidden behind
+// several local macros defined below, and as soon as you understand them,
+// you understand the whole library implementation.
+
+#ifndef BOOST_OPERATORS_V1_HPP
+#define BOOST_OPERATORS_V1_HPP
+
+#include <cstddef>
+#include <iterator>
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+
+#if defined(__sgi) && !defined(__GNUC__)
+# pragma set woff 1234
+#endif
+
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1600)
+# pragma warning( disable : 4284 ) // complaint about return type of
+#endif // operator-> not begin a UDT
+
+namespace boost {
+namespace detail {
+
+template <typename T> class empty_base {};
+
+} // namespace detail
+} // namespace boost
+
+// In this section we supply the xxxx1 and xxxx2 forms of the operator
+// templates, which are explicitly targeted at the 1-type-argument and
+// 2-type-argument operator forms, respectively. Some compilers get confused
+// when inline friend functions are overloaded in namespaces other than the
+// global namespace. When BOOST_NO_OPERATORS_IN_NAMESPACE is defined, all of
+// these templates must go in the global namespace.
+
+#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
+namespace boost
+{
+#endif
+
+// Basic operator classes (contributed by Dave Abrahams) ------------------//
+
+// Note that friend functions defined in a class are implicitly inline.
+// See the C++ std, 11.4 [class.friend] paragraph 5
+
+template <class T, class U, class B = ::boost::detail::empty_base<T> >
+struct less_than_comparable2 : B
+{
+ friend bool operator<=(const T& x, const U& y) { return !static_cast<bool>(x > y); }
+ friend bool operator>=(const T& x, const U& y) { return !static_cast<bool>(x < y); }
+ friend bool operator>(const U& x, const T& y) { return y < x; }
+ friend bool operator<(const U& x, const T& y) { return y > x; }
+ friend bool operator<=(const U& x, const T& y) { return !static_cast<bool>(y < x); }
+ friend bool operator>=(const U& x, const T& y) { return !static_cast<bool>(y > x); }
+};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct less_than_comparable1 : B
+{
+ friend bool operator>(const T& x, const T& y) { return y < x; }
+ friend bool operator<=(const T& x, const T& y) { return !static_cast<bool>(y < x); }
+ friend bool operator>=(const T& x, const T& y) { return !static_cast<bool>(x < y); }
+};
+
+template <class T, class U, class B = ::boost::detail::empty_base<T> >
+struct equality_comparable2 : B
+{
+ friend bool operator==(const U& y, const T& x) { return x == y; }
+ friend bool operator!=(const U& y, const T& x) { return !static_cast<bool>(x == y); }
+ friend bool operator!=(const T& y, const U& x) { return !static_cast<bool>(y == x); }
+};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct equality_comparable1 : B
+{
+ friend bool operator!=(const T& x, const T& y) { return !static_cast<bool>(x == y); }
+};
+
+// A macro which produces "name_2left" from "name".
+#define BOOST_OPERATOR2_LEFT(name) name##2##_##left
+
+// NRVO-friendly implementation (contributed by Daniel Frey) ---------------//
+
+#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
+
+// This is the optimal implementation for ISO/ANSI C++,
+// but it requires the compiler to implement the NRVO.
+// If the compiler has no NRVO, this is the best symmetric
+// implementation available.
+
+#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
+template <class T, class U, class B = ::boost::detail::empty_base<T> > \
+struct NAME##2 : B \
+{ \
+ friend T operator OP( const T& lhs, const U& rhs ) \
+ { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
+ friend T operator OP( const U& lhs, const T& rhs ) \
+ { T nrv( rhs ); nrv OP##= lhs; return nrv; } \
+}; \
+ \
+template <class T, class B = ::boost::detail::empty_base<T> > \
+struct NAME##1 : B \
+{ \
+ friend T operator OP( const T& lhs, const T& rhs ) \
+ { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
+};
+
+#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
+template <class T, class U, class B = ::boost::detail::empty_base<T> > \
+struct NAME##2 : B \
+{ \
+ friend T operator OP( const T& lhs, const U& rhs ) \
+ { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
+}; \
+ \
+template <class T, class U, class B = ::boost::detail::empty_base<T> > \
+struct BOOST_OPERATOR2_LEFT(NAME) : B \
+{ \
+ friend T operator OP( const U& lhs, const T& rhs ) \
+ { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
+}; \
+ \
+template <class T, class B = ::boost::detail::empty_base<T> > \
+struct NAME##1 : B \
+{ \
+ friend T operator OP( const T& lhs, const T& rhs ) \
+ { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
+};
+
+#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
+
+// For compilers without NRVO the following code is optimal, but not
+// symmetric! Note that the implementation of
+// BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide
+// optimization opportunities to the compiler :)
+
+#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
+template <class T, class U, class B = ::boost::detail::empty_base<T> > \
+struct NAME##2 : B \
+{ \
+ friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
+ friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \
+}; \
+ \
+template <class T, class B = ::boost::detail::empty_base<T> > \
+struct NAME##1 : B \
+{ \
+ friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
+};
+
+#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
+template <class T, class U, class B = ::boost::detail::empty_base<T> > \
+struct NAME##2 : B \
+{ \
+ friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
+}; \
+ \
+template <class T, class U, class B = ::boost::detail::empty_base<T> > \
+struct BOOST_OPERATOR2_LEFT(NAME) : B \
+{ \
+ friend T operator OP( const U& lhs, const T& rhs ) \
+ { return T( lhs ) OP##= rhs; } \
+}; \
+ \
+template <class T, class B = ::boost::detail::empty_base<T> > \
+struct NAME##1 : B \
+{ \
+ friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
+};
+
+#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
+
+BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * )
+BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + )
+BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - )
+BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / )
+BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % )
+BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ )
+BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & )
+BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | )
+
+#undef BOOST_BINARY_OPERATOR_COMMUTATIVE
+#undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE
+#undef BOOST_OPERATOR2_LEFT
+
+// incrementable and decrementable contributed by Jeremy Siek
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct incrementable : B
+{
+ friend T operator++(T& x, int)
+ {
+ incrementable_type nrv(x);
+ ++x;
+ return nrv;
+ }
+private: // The use of this typedef works around a Borland bug
+ typedef T incrementable_type;
+};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct decrementable : B
+{
+ friend T operator--(T& x, int)
+ {
+ decrementable_type nrv(x);
+ --x;
+ return nrv;
+ }
+private: // The use of this typedef works around a Borland bug
+ typedef T decrementable_type;
+};
+
+// Iterator operator classes (contributed by Jeremy Siek) ------------------//
+
+template <class T, class P, class B = ::boost::detail::empty_base<T> >
+struct dereferenceable : B
+{
+ P operator->() const
+ {
+ return &*static_cast<const T&>(*this);
+ }
+};
+
+template <class T, class I, class R, class B = ::boost::detail::empty_base<T> >
+struct indexable : B
+{
+ R operator[](I n) const
+ {
+ return *(static_cast<const T&>(*this) + n);
+ }
+};
+
+// More operator classes (contributed by Daryle Walker) --------------------//
+// (NRVO-friendly implementation contributed by Daniel Frey) ---------------//
+
+#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
+
+#define BOOST_BINARY_OPERATOR( NAME, OP ) \
+template <class T, class U, class B = ::boost::detail::empty_base<T> > \
+struct NAME##2 : B \
+{ \
+ friend T operator OP( const T& lhs, const U& rhs ) \
+ { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
+}; \
+ \
+template <class T, class B = ::boost::detail::empty_base<T> > \
+struct NAME##1 : B \
+{ \
+ friend T operator OP( const T& lhs, const T& rhs ) \
+ { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
+};
+
+#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
+
+#define BOOST_BINARY_OPERATOR( NAME, OP ) \
+template <class T, class U, class B = ::boost::detail::empty_base<T> > \
+struct NAME##2 : B \
+{ \
+ friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
+}; \
+ \
+template <class T, class B = ::boost::detail::empty_base<T> > \
+struct NAME##1 : B \
+{ \
+ friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
+};
+
+#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
+
+BOOST_BINARY_OPERATOR( left_shiftable, << )
+BOOST_BINARY_OPERATOR( right_shiftable, >> )
+
+#undef BOOST_BINARY_OPERATOR
+
+template <class T, class U, class B = ::boost::detail::empty_base<T> >
+struct equivalent2 : B
+{
+ friend bool operator==(const T& x, const U& y)
+ {
+ return !static_cast<bool>(x < y) && !static_cast<bool>(x > y);
+ }
+};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct equivalent1 : B
+{
+ friend bool operator==(const T&x, const T&y)
+ {
+ return !static_cast<bool>(x < y) && !static_cast<bool>(y < x);
+ }
+};
+
+template <class T, class U, class B = ::boost::detail::empty_base<T> >
+struct partially_ordered2 : B
+{
+ friend bool operator<=(const T& x, const U& y)
+ { return static_cast<bool>(x < y) || static_cast<bool>(x == y); }
+ friend bool operator>=(const T& x, const U& y)
+ { return static_cast<bool>(x > y) || static_cast<bool>(x == y); }
+ friend bool operator>(const U& x, const T& y)
+ { return y < x; }
+ friend bool operator<(const U& x, const T& y)
+ { return y > x; }
+ friend bool operator<=(const U& x, const T& y)
+ { return static_cast<bool>(y > x) || static_cast<bool>(y == x); }
+ friend bool operator>=(const U& x, const T& y)
+ { return static_cast<bool>(y < x) || static_cast<bool>(y == x); }
+};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct partially_ordered1 : B
+{
+ friend bool operator>(const T& x, const T& y)
+ { return y < x; }
+ friend bool operator<=(const T& x, const T& y)
+ { return static_cast<bool>(x < y) || static_cast<bool>(x == y); }
+ friend bool operator>=(const T& x, const T& y)
+ { return static_cast<bool>(y < x) || static_cast<bool>(x == y); }
+};
+
+// Combined operator classes (contributed by Daryle Walker) ----------------//
+
+template <class T, class U, class B = ::boost::detail::empty_base<T> >
+struct totally_ordered2
+ : less_than_comparable2<T, U
+ , equality_comparable2<T, U, B
+ > > {};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct totally_ordered1
+ : less_than_comparable1<T
+ , equality_comparable1<T, B
+ > > {};
+
+template <class T, class U, class B = ::boost::detail::empty_base<T> >
+struct additive2
+ : addable2<T, U
+ , subtractable2<T, U, B
+ > > {};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct additive1
+ : addable1<T
+ , subtractable1<T, B
+ > > {};
+
+template <class T, class U, class B = ::boost::detail::empty_base<T> >
+struct multiplicative2
+ : multipliable2<T, U
+ , dividable2<T, U, B
+ > > {};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct multiplicative1
+ : multipliable1<T
+ , dividable1<T, B
+ > > {};
+
+template <class T, class U, class B = ::boost::detail::empty_base<T> >
+struct integer_multiplicative2
+ : multiplicative2<T, U
+ , modable2<T, U, B
+ > > {};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct integer_multiplicative1
+ : multiplicative1<T
+ , modable1<T, B
+ > > {};
+
+template <class T, class U, class B = ::boost::detail::empty_base<T> >
+struct arithmetic2
+ : additive2<T, U
+ , multiplicative2<T, U, B
+ > > {};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct arithmetic1
+ : additive1<T
+ , multiplicative1<T, B
+ > > {};
+
+template <class T, class U, class B = ::boost::detail::empty_base<T> >
+struct integer_arithmetic2
+ : additive2<T, U
+ , integer_multiplicative2<T, U, B
+ > > {};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct integer_arithmetic1
+ : additive1<T
+ , integer_multiplicative1<T, B
+ > > {};
+
+template <class T, class U, class B = ::boost::detail::empty_base<T> >
+struct bitwise2
+ : xorable2<T, U
+ , andable2<T, U
+ , orable2<T, U, B
+ > > > {};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct bitwise1
+ : xorable1<T
+ , andable1<T
+ , orable1<T, B
+ > > > {};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct unit_steppable
+ : incrementable<T
+ , decrementable<T, B
+ > > {};
+
+template <class T, class U, class B = ::boost::detail::empty_base<T> >
+struct shiftable2
+ : left_shiftable2<T, U
+ , right_shiftable2<T, U, B
+ > > {};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct shiftable1
+ : left_shiftable1<T
+ , right_shiftable1<T, B
+ > > {};
+
+template <class T, class U, class B = ::boost::detail::empty_base<T> >
+struct ring_operators2
+ : additive2<T, U
+ , subtractable2_left<T, U
+ , multipliable2<T, U, B
+ > > > {};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct ring_operators1
+ : additive1<T
+ , multipliable1<T, B
+ > > {};
+
+template <class T, class U, class B = ::boost::detail::empty_base<T> >
+struct ordered_ring_operators2
+ : ring_operators2<T, U
+ , totally_ordered2<T, U, B
+ > > {};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct ordered_ring_operators1
+ : ring_operators1<T
+ , totally_ordered1<T, B
+ > > {};
+
+template <class T, class U, class B = ::boost::detail::empty_base<T> >
+struct field_operators2
+ : ring_operators2<T, U
+ , dividable2<T, U
+ , dividable2_left<T, U, B
+ > > > {};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct field_operators1
+ : ring_operators1<T
+ , dividable1<T, B
+ > > {};
+
+template <class T, class U, class B = ::boost::detail::empty_base<T> >
+struct ordered_field_operators2
+ : field_operators2<T, U
+ , totally_ordered2<T, U, B
+ > > {};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct ordered_field_operators1
+ : field_operators1<T
+ , totally_ordered1<T, B
+ > > {};
+
+template <class T, class U, class B = ::boost::detail::empty_base<T> >
+struct euclidian_ring_operators2
+ : ring_operators2<T, U
+ , dividable2<T, U
+ , dividable2_left<T, U
+ , modable2<T, U
+ , modable2_left<T, U, B
+ > > > > > {};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct euclidian_ring_operators1
+ : ring_operators1<T
+ , dividable1<T
+ , modable1<T, B
+ > > > {};
+
+template <class T, class U, class B = ::boost::detail::empty_base<T> >
+struct ordered_euclidian_ring_operators2
+ : totally_ordered2<T, U
+ , euclidian_ring_operators2<T, U, B
+ > > {};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct ordered_euclidian_ring_operators1
+ : totally_ordered1<T
+ , euclidian_ring_operators1<T, B
+ > > {};
+
+template <class T, class U, class B = ::boost::detail::empty_base<T> >
+struct euclidean_ring_operators2
+ : ring_operators2<T, U
+ , dividable2<T, U
+ , dividable2_left<T, U
+ , modable2<T, U
+ , modable2_left<T, U, B
+ > > > > > {};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct euclidean_ring_operators1
+ : ring_operators1<T
+ , dividable1<T
+ , modable1<T, B
+ > > > {};
+
+template <class T, class U, class B = ::boost::detail::empty_base<T> >
+struct ordered_euclidean_ring_operators2
+ : totally_ordered2<T, U
+ , euclidean_ring_operators2<T, U, B
+ > > {};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct ordered_euclidean_ring_operators1
+ : totally_ordered1<T
+ , euclidean_ring_operators1<T, B
+ > > {};
+
+template <class T, class P, class B = ::boost::detail::empty_base<T> >
+struct input_iteratable
+ : equality_comparable1<T
+ , incrementable<T
+ , dereferenceable<T, P, B
+ > > > {};
+
+template <class T, class B = ::boost::detail::empty_base<T> >
+struct output_iteratable
+ : incrementable<T, B
+ > {};
+
+template <class T, class P, class B = ::boost::detail::empty_base<T> >
+struct forward_iteratable
+ : input_iteratable<T, P, B
+ > {};
+
+template <class T, class P, class B = ::boost::detail::empty_base<T> >
+struct bidirectional_iteratable
+ : forward_iteratable<T, P
+ , decrementable<T, B
+ > > {};
+
+// To avoid repeated derivation from equality_comparable,
+// which is an indirect base class of bidirectional_iterable,
+// random_access_iteratable must not be derived from totally_ordered1
+// but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001)
+template <class T, class P, class D, class R, class B = ::boost::detail::empty_base<T> >
+struct random_access_iteratable
+ : bidirectional_iteratable<T, P
+ , less_than_comparable1<T
+ , additive2<T, D
+ , indexable<T, D, R, B
+ > > > > {};
+
+#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
+} // namespace boost
+#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
+
+
+// BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE4 -
+//
+// When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an
+// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used
+// for one-argument forms of operator templates; BOOST_IMPORT_TEMPLATE2 for
+// two-argument forms. Note that these macros expect to be invoked from within
+// boost.
+
+#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
+
+ // The template is already in boost so we have nothing to do.
+# define BOOST_IMPORT_TEMPLATE4(template_name)
+# define BOOST_IMPORT_TEMPLATE3(template_name)
+# define BOOST_IMPORT_TEMPLATE2(template_name)
+# define BOOST_IMPORT_TEMPLATE1(template_name)
+
+#else // BOOST_NO_OPERATORS_IN_NAMESPACE
+
+# ifndef BOOST_NO_USING_TEMPLATE
+
+ // Bring the names in with a using-declaration
+ // to avoid stressing the compiler.
+# define BOOST_IMPORT_TEMPLATE4(template_name) using ::template_name;
+# define BOOST_IMPORT_TEMPLATE3(template_name) using ::template_name;
+# define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name;
+# define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name;
+
+# else
+
+ // Otherwise, because a Borland C++ 5.5 bug prevents a using declaration
+ // from working, we are forced to use inheritance for that compiler.
+# define BOOST_IMPORT_TEMPLATE4(template_name) \
+ template <class T, class U, class V, class W, class B = ::boost::detail::empty_base<T> > \
+ struct template_name : ::template_name<T, U, V, W, B> {};
+
+# define BOOST_IMPORT_TEMPLATE3(template_name) \
+ template <class T, class U, class V, class B = ::boost::detail::empty_base<T> > \
+ struct template_name : ::template_name<T, U, V, B> {};
+
+# define BOOST_IMPORT_TEMPLATE2(template_name) \
+ template <class T, class U, class B = ::boost::detail::empty_base<T> > \
+ struct template_name : ::template_name<T, U, B> {};
+
+# define BOOST_IMPORT_TEMPLATE1(template_name) \
+ template <class T, class B = ::boost::detail::empty_base<T> > \
+ struct template_name : ::template_name<T, B> {};
+
+# endif // BOOST_NO_USING_TEMPLATE
+
+#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
+
+//
+// Here's where we put it all together, defining the xxxx forms of the templates
+// in namespace boost. We also define specializations of is_chained_base<> for
+// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
+// necessary.
+//
+
+// is_chained_base<> - a traits class used to distinguish whether an operator
+// template argument is being used for base class chaining, or is specifying a
+// 2nd argument type.
+
+namespace boost {
+// A type parameter is used instead of a plain bool because Borland's compiler
+// didn't cope well with the more obvious non-type template parameter.
+namespace detail {
+ struct true_t {};
+ struct false_t {};
+} // namespace detail
+
+// Unspecialized version assumes that most types are not being used for base
+// class chaining. We specialize for the operator templates defined in this
+// library.
+template<class T> struct is_chained_base {
+ typedef ::boost::detail::false_t value;
+};
+
+} // namespace boost
+
+// Import a 4-type-argument operator template into boost (if necessary) and
+// provide a specialization of 'is_chained_base<>' for it.
+# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
+ BOOST_IMPORT_TEMPLATE4(template_name4) \
+ template<class T, class U, class V, class W, class B> \
+ struct is_chained_base< ::boost::template_name4<T, U, V, W, B> > { \
+ typedef ::boost::detail::true_t value; \
+ };
+
+// Import a 3-type-argument operator template into boost (if necessary) and
+// provide a specialization of 'is_chained_base<>' for it.
+# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
+ BOOST_IMPORT_TEMPLATE3(template_name3) \
+ template<class T, class U, class V, class B> \
+ struct is_chained_base< ::boost::template_name3<T, U, V, B> > { \
+ typedef ::boost::detail::true_t value; \
+ };
+
+// Import a 2-type-argument operator template into boost (if necessary) and
+// provide a specialization of 'is_chained_base<>' for it.
+# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
+ BOOST_IMPORT_TEMPLATE2(template_name2) \
+ template<class T, class U, class B> \
+ struct is_chained_base< ::boost::template_name2<T, U, B> > { \
+ typedef ::boost::detail::true_t value; \
+ };
+
+// Import a 1-type-argument operator template into boost (if necessary) and
+// provide a specialization of 'is_chained_base<>' for it.
+# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
+ BOOST_IMPORT_TEMPLATE1(template_name1) \
+ template<class T, class B> \
+ struct is_chained_base< ::boost::template_name1<T, B> > { \
+ typedef ::boost::detail::true_t value; \
+ };
+
+// BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it
+// can be used for specifying both 1-argument and 2-argument forms. Requires the
+// existence of two previously defined class templates named '<template_name>1'
+// and '<template_name>2' which must implement the corresponding 1- and 2-
+// argument forms.
+//
+// The template type parameter O == is_chained_base<U>::value is used to
+// distinguish whether the 2nd argument to <template_name> is being used for
+// base class chaining from another boost operator template or is describing a
+// 2nd operand type. O == true_t only when U is actually an another operator
+// template from the library. Partial specialization is used to select an
+// implementation in terms of either '<template_name>1' or '<template_name>2'.
+//
+
+# define BOOST_OPERATOR_TEMPLATE(template_name) \
+template <class T \
+ ,class U = T \
+ ,class B = ::boost::detail::empty_base<T> \
+ ,class O = typename is_chained_base<U>::value \
+ > \
+struct template_name : template_name##2<T, U, B> {}; \
+ \
+template<class T, class U, class B> \
+struct template_name<T, U, B, ::boost::detail::true_t> \
+ : template_name##1<T, U> {}; \
+ \
+template <class T, class B> \
+struct template_name<T, T, B, ::boost::detail::false_t> \
+ : template_name##1<T, B> {}; \
+ \
+template<class T, class U, class B, class O> \
+struct is_chained_base< ::boost::template_name<T, U, B, O> > { \
+ typedef ::boost::detail::true_t value; \
+}; \
+ \
+BOOST_OPERATOR_TEMPLATE2(template_name##2) \
+BOOST_OPERATOR_TEMPLATE1(template_name##1)
+
+
+
+namespace boost {
+
+BOOST_OPERATOR_TEMPLATE(less_than_comparable)
+BOOST_OPERATOR_TEMPLATE(equality_comparable)
+BOOST_OPERATOR_TEMPLATE(multipliable)
+BOOST_OPERATOR_TEMPLATE(addable)
+BOOST_OPERATOR_TEMPLATE(subtractable)
+BOOST_OPERATOR_TEMPLATE2(subtractable2_left)
+BOOST_OPERATOR_TEMPLATE(dividable)
+BOOST_OPERATOR_TEMPLATE2(dividable2_left)
+BOOST_OPERATOR_TEMPLATE(modable)
+BOOST_OPERATOR_TEMPLATE2(modable2_left)
+BOOST_OPERATOR_TEMPLATE(xorable)
+BOOST_OPERATOR_TEMPLATE(andable)
+BOOST_OPERATOR_TEMPLATE(orable)
+
+BOOST_OPERATOR_TEMPLATE1(incrementable)
+BOOST_OPERATOR_TEMPLATE1(decrementable)
+
+BOOST_OPERATOR_TEMPLATE2(dereferenceable)
+BOOST_OPERATOR_TEMPLATE3(indexable)
+
+BOOST_OPERATOR_TEMPLATE(left_shiftable)
+BOOST_OPERATOR_TEMPLATE(right_shiftable)
+BOOST_OPERATOR_TEMPLATE(equivalent)
+BOOST_OPERATOR_TEMPLATE(partially_ordered)
+
+BOOST_OPERATOR_TEMPLATE(totally_ordered)
+BOOST_OPERATOR_TEMPLATE(additive)
+BOOST_OPERATOR_TEMPLATE(multiplicative)
+BOOST_OPERATOR_TEMPLATE(integer_multiplicative)
+BOOST_OPERATOR_TEMPLATE(arithmetic)
+BOOST_OPERATOR_TEMPLATE(integer_arithmetic)
+BOOST_OPERATOR_TEMPLATE(bitwise)
+BOOST_OPERATOR_TEMPLATE1(unit_steppable)
+BOOST_OPERATOR_TEMPLATE(shiftable)
+BOOST_OPERATOR_TEMPLATE(ring_operators)
+BOOST_OPERATOR_TEMPLATE(ordered_ring_operators)
+BOOST_OPERATOR_TEMPLATE(field_operators)
+BOOST_OPERATOR_TEMPLATE(ordered_field_operators)
+BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators)
+BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators)
+BOOST_OPERATOR_TEMPLATE(euclidean_ring_operators)
+BOOST_OPERATOR_TEMPLATE(ordered_euclidean_ring_operators)
+BOOST_OPERATOR_TEMPLATE2(input_iteratable)
+BOOST_OPERATOR_TEMPLATE1(output_iteratable)
+BOOST_OPERATOR_TEMPLATE2(forward_iteratable)
+BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable)
+BOOST_OPERATOR_TEMPLATE4(random_access_iteratable)
+
+#undef BOOST_OPERATOR_TEMPLATE
+#undef BOOST_OPERATOR_TEMPLATE4
+#undef BOOST_OPERATOR_TEMPLATE3
+#undef BOOST_OPERATOR_TEMPLATE2
+#undef BOOST_OPERATOR_TEMPLATE1
+#undef BOOST_IMPORT_TEMPLATE1
+#undef BOOST_IMPORT_TEMPLATE2
+#undef BOOST_IMPORT_TEMPLATE3
+#undef BOOST_IMPORT_TEMPLATE4
+
+// The following 'operators' classes can only be used portably if the derived class
+// declares ALL of the required member operators.
+template <class T, class U>
+struct operators2
+ : totally_ordered2<T,U
+ , integer_arithmetic2<T,U
+ , bitwise2<T,U
+ > > > {};
+
+template <class T, class U = T>
+struct operators : operators2<T, U> {};
+
+template <class T> struct operators<T, T>
+ : totally_ordered<T
+ , integer_arithmetic<T
+ , bitwise<T
+ , unit_steppable<T
+ > > > > {};
+
+// Iterator helper classes (contributed by Jeremy Siek) -------------------//
+// (Input and output iterator helpers contributed by Daryle Walker) -------//
+// (Changed to use combined operator classes by Daryle Walker) ------------//
+template <class T,
+ class V,
+ class D = std::ptrdiff_t,
+ class P = V const *,
+ class R = V const &>
+struct input_iterator_helper
+ : input_iteratable<T, P
+ , std::iterator<std::input_iterator_tag, V, D, P, R
+ > > {};
+
+template<class T>
+struct output_iterator_helper
+ : output_iteratable<T
+ , std::iterator<std::output_iterator_tag, void, void, void, void
+ > >
+{
+ T& operator*() { return static_cast<T&>(*this); }
+ T& operator++() { return static_cast<T&>(*this); }
+};
+
+template <class T,
+ class V,
+ class D = std::ptrdiff_t,
+ class P = V*,
+ class R = V&>
+struct forward_iterator_helper
+ : forward_iteratable<T, P
+ , std::iterator<std::forward_iterator_tag, V, D, P, R
+ > > {};
+
+template <class T,
+ class V,
+ class D = std::ptrdiff_t,
+ class P = V*,
+ class R = V&>
+struct bidirectional_iterator_helper
+ : bidirectional_iteratable<T, P
+ , std::iterator<std::bidirectional_iterator_tag, V, D, P, R
+ > > {};
+
+template <class T,
+ class V,
+ class D = std::ptrdiff_t,
+ class P = V*,
+ class R = V&>
+struct random_access_iterator_helper
+ : random_access_iteratable<T, P, D, R
+ , std::iterator<std::random_access_iterator_tag, V, D, P, R
+ > >
+{
+ friend D requires_difference_operator(const T& x, const T& y) {
+ return x - y;
+ }
+}; // random_access_iterator_helper
+
+} // namespace boost
+
+#if defined(__sgi) && !defined(__GNUC__)
+#pragma reset woff 1234
+#endif
+
+#endif // BOOST_OPERATORS_V1_HPP
diff --git a/boost/optional/detail/old_optional_implementation.hpp b/boost/optional/detail/old_optional_implementation.hpp
new file mode 100644
index 0000000000..f2e6718402
--- /dev/null
+++ b/boost/optional/detail/old_optional_implementation.hpp
@@ -0,0 +1,1059 @@
+// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
+// Copyright (C) 2014-2016 Andrzej Krzemienski.
+//
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/optional for documentation.
+//
+// You are welcome to contact the maintainer at:
+// akrzemi1@gmail.com
+
+#ifndef BOOST_OPTIONAL_DETAIL_OLD_OPTIONAL_IMPLEMENTATION_AJK_28JAN2015_HPP
+#define BOOST_OPTIONAL_DETAIL_OLD_OPTIONAL_IMPLEMENTATION_AJK_28JAN2015_HPP
+
+#include <boost/detail/reference_content.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/type_traits/is_reference.hpp>
+
+namespace boost {
+
+namespace optional_detail {
+
+
+template<class T>
+struct types_when_isnt_ref
+{
+ typedef T const& reference_const_type ;
+ typedef T & reference_type ;
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ typedef T && rval_reference_type ;
+ typedef T && reference_type_of_temporary_wrapper;
+#ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
+ // GCC 4.4 has support for an early draft of rvalue references. The conforming version below
+ // causes warnings about returning references to a temporary.
+ static T&& move(T&& r) { return r; }
+#else
+ static rval_reference_type move(reference_type r) { return boost::move(r); }
+#endif
+#endif
+ typedef T const* pointer_const_type ;
+ typedef T * pointer_type ;
+ typedef T const& argument_type ;
+} ;
+
+template<class T>
+struct types_when_is_ref
+{
+ typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type raw_type ;
+
+ typedef raw_type& reference_const_type ;
+ typedef raw_type& reference_type ;
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ typedef BOOST_DEDUCED_TYPENAME remove_const<raw_type>::type&& rval_reference_type ;
+ typedef raw_type& reference_type_of_temporary_wrapper;
+ static reference_type move(reference_type r) { return r; }
+#endif
+ typedef raw_type* pointer_const_type ;
+ typedef raw_type* pointer_type ;
+ typedef raw_type& argument_type ;
+} ;
+
+template <class To, class From>
+void prevent_binding_rvalue_ref_to_optional_lvalue_ref()
+{
+#ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES
+ BOOST_STATIC_ASSERT_MSG(
+ !boost::is_lvalue_reference<To>::value || !boost::is_rvalue_reference<From>::value,
+ "binding rvalue references to optional lvalue references is disallowed");
+#endif
+}
+
+struct optional_tag {} ;
+
+template<class T>
+class optional_base : public optional_tag
+{
+ private :
+
+ typedef
+#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+ BOOST_DEDUCED_TYPENAME
+#endif
+ ::boost::detail::make_reference_content<T>::type internal_type ;
+
+ typedef aligned_storage<internal_type> storage_type ;
+
+ typedef types_when_isnt_ref<T> types_when_not_ref ;
+ typedef types_when_is_ref<T> types_when_ref ;
+
+ typedef optional_base<T> this_type ;
+
+ protected :
+
+ typedef T value_type ;
+
+ typedef mpl::true_ is_reference_tag ;
+ typedef mpl::false_ is_not_reference_tag ;
+
+ typedef BOOST_DEDUCED_TYPENAME is_reference<T>::type is_reference_predicate ;
+
+ public:
+ typedef BOOST_DEDUCED_TYPENAME mpl::if_<is_reference_predicate,types_when_ref,types_when_not_ref>::type types ;
+
+ protected:
+ typedef BOOST_DEDUCED_TYPENAME types::reference_type reference_type ;
+ typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ;
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ typedef BOOST_DEDUCED_TYPENAME types::rval_reference_type rval_reference_type ;
+ typedef BOOST_DEDUCED_TYPENAME types::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ;
+#endif
+ typedef BOOST_DEDUCED_TYPENAME types::pointer_type pointer_type ;
+ typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type pointer_const_type ;
+ typedef BOOST_DEDUCED_TYPENAME types::argument_type argument_type ;
+
+ // Creates an optional<T> uninitialized.
+ // No-throw
+ optional_base()
+ :
+ m_initialized(false) {}
+
+ // Creates an optional<T> uninitialized.
+ // No-throw
+ optional_base ( none_t )
+ :
+ m_initialized(false) {}
+
+ // Creates an optional<T> initialized with 'val'.
+ // Can throw if T::T(T const&) does
+ optional_base ( argument_type val )
+ :
+ m_initialized(false)
+ {
+ construct(val);
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // move-construct an optional<T> initialized from an rvalue-ref to 'val'.
+ // Can throw if T::T(T&&) does
+ optional_base ( rval_reference_type val )
+ :
+ m_initialized(false)
+ {
+ construct( boost::move(val) );
+ }
+#endif
+
+ // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional<T>.
+ // Can throw if T::T(T const&) does
+ optional_base ( bool cond, argument_type val )
+ :
+ m_initialized(false)
+ {
+ if ( cond )
+ construct(val);
+ }
+
+ // Creates a deep copy of another optional<T>
+ // Can throw if T::T(T const&) does
+ optional_base ( optional_base const& rhs )
+ :
+ m_initialized(false)
+ {
+ if ( rhs.is_initialized() )
+ construct(rhs.get_impl());
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Creates a deep move of another optional<T>
+ // Can throw if T::T(T&&) does
+ optional_base ( optional_base&& rhs )
+ :
+ m_initialized(false)
+ {
+ if ( rhs.is_initialized() )
+ construct( boost::move(rhs.get_impl()) );
+ }
+#endif
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+
+ template<class Expr, class PtrExpr>
+ explicit optional_base ( Expr&& expr, PtrExpr const* tag )
+ :
+ m_initialized(false)
+ {
+ construct(boost::forward<Expr>(expr),tag);
+ }
+
+#else
+ // This is used for both converting and in-place constructions.
+ // Derived classes use the 'tag' to select the appropriate
+ // implementation (the correct 'construct()' overload)
+ template<class Expr>
+ explicit optional_base ( Expr const& expr, Expr const* tag )
+ :
+ m_initialized(false)
+ {
+ construct(expr,tag);
+ }
+
+#endif
+
+
+ // No-throw (assuming T::~T() doesn't)
+ ~optional_base() { destroy() ; }
+
+ // Assigns from another optional<T> (deep-copies the rhs value)
+ void assign ( optional_base const& rhs )
+ {
+ if (is_initialized())
+ {
+ if ( rhs.is_initialized() )
+ assign_value(rhs.get_impl(), is_reference_predicate() );
+ else destroy();
+ }
+ else
+ {
+ if ( rhs.is_initialized() )
+ construct(rhs.get_impl());
+ }
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Assigns from another optional<T> (deep-moves the rhs value)
+ void assign ( optional_base&& rhs )
+ {
+ if (is_initialized())
+ {
+ if ( rhs.is_initialized() )
+ assign_value(boost::move(rhs.get_impl()), is_reference_predicate() );
+ else destroy();
+ }
+ else
+ {
+ if ( rhs.is_initialized() )
+ construct(boost::move(rhs.get_impl()));
+ }
+ }
+#endif
+
+ // Assigns from another _convertible_ optional<U> (deep-copies the rhs value)
+ template<class U>
+ void assign ( optional<U> const& rhs )
+ {
+ if (is_initialized())
+ {
+ if ( rhs.is_initialized() )
+#ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
+ assign_value(rhs.get(), is_reference_predicate() );
+#else
+ assign_value(static_cast<value_type>(rhs.get()), is_reference_predicate() );
+#endif
+
+ else destroy();
+ }
+ else
+ {
+ if ( rhs.is_initialized() )
+#ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
+ construct(rhs.get());
+#else
+ construct(static_cast<value_type>(rhs.get()));
+#endif
+ }
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // move-assigns from another _convertible_ optional<U> (deep-moves from the rhs value)
+ template<class U>
+ void assign ( optional<U>&& rhs )
+ {
+ typedef BOOST_DEDUCED_TYPENAME optional<U>::rval_reference_type ref_type;
+ if (is_initialized())
+ {
+ if ( rhs.is_initialized() )
+ assign_value(static_cast<ref_type>(rhs.get()), is_reference_predicate() );
+ else destroy();
+ }
+ else
+ {
+ if ( rhs.is_initialized() )
+ construct(static_cast<ref_type>(rhs.get()));
+ }
+ }
+#endif
+
+ // Assigns from a T (deep-copies the rhs value)
+ void assign ( argument_type val )
+ {
+ if (is_initialized())
+ assign_value(val, is_reference_predicate() );
+ else construct(val);
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Assigns from a T (deep-moves the rhs value)
+ void assign ( rval_reference_type val )
+ {
+ if (is_initialized())
+ assign_value( boost::move(val), is_reference_predicate() );
+ else construct( boost::move(val) );
+ }
+#endif
+
+ // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
+ // No-throw (assuming T::~T() doesn't)
+ void assign ( none_t ) BOOST_NOEXCEPT { destroy(); }
+
+#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ template<class Expr, class ExprPtr>
+ void assign_expr ( Expr&& expr, ExprPtr const* tag )
+ {
+ if (is_initialized())
+ assign_expr_to_initialized(boost::forward<Expr>(expr),tag);
+ else construct(boost::forward<Expr>(expr),tag);
+ }
+#else
+ template<class Expr>
+ void assign_expr ( Expr const& expr, Expr const* tag )
+ {
+ if (is_initialized())
+ assign_expr_to_initialized(expr,tag);
+ else construct(expr,tag);
+ }
+#endif
+
+#endif
+
+ public :
+
+ // **DEPPRECATED** Destroys the current value, if any, leaving this UNINITIALIZED
+ // No-throw (assuming T::~T() doesn't)
+ void reset() BOOST_NOEXCEPT { destroy(); }
+
+ // **DEPPRECATED** Replaces the current value -if any- with 'val'
+ void reset ( argument_type val ) { assign(val); }
+
+ // Returns a pointer to the value if this is initialized, otherwise,
+ // returns NULL.
+ // No-throw
+ pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; }
+ pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; }
+
+ bool is_initialized() const { return m_initialized ; }
+
+ protected :
+
+ void construct ( argument_type val )
+ {
+ ::new (m_storage.address()) internal_type(val) ;
+ m_initialized = true ;
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ void construct ( rval_reference_type val )
+ {
+ ::new (m_storage.address()) internal_type( types::move(val) ) ;
+ m_initialized = true ;
+ }
+#endif
+
+
+#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ // Constructs in-place
+ // upon exception *this is always uninitialized
+ template<class... Args>
+ void emplace_assign ( Args&&... args )
+ {
+ destroy();
+ ::new (m_storage.address()) internal_type( boost::forward<Args>(args)... );
+ m_initialized = true ;
+ }
+#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
+ template<class Arg>
+ void emplace_assign ( Arg&& arg )
+ {
+ destroy();
+ ::new (m_storage.address()) internal_type( boost::forward<Arg>(arg) );
+ m_initialized = true ;
+ }
+
+ void emplace_assign ()
+ {
+ destroy();
+ ::new (m_storage.address()) internal_type();
+ m_initialized = true ;
+ }
+#else
+ template<class Arg>
+ void emplace_assign ( const Arg& arg )
+ {
+ destroy();
+ ::new (m_storage.address()) internal_type( arg );
+ m_initialized = true ;
+ }
+
+ template<class Arg>
+ void emplace_assign ( Arg& arg )
+ {
+ destroy();
+ ::new (m_storage.address()) internal_type( arg );
+ m_initialized = true ;
+ }
+
+ void emplace_assign ()
+ {
+ destroy();
+ ::new (m_storage.address()) internal_type();
+ m_initialized = true ;
+ }
+#endif
+
+#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Constructs in-place using the given factory
+ template<class Expr>
+ void construct ( Expr&& factory, in_place_factory_base const* )
+ {
+ BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
+ boost_optional_detail::construct<value_type>(factory, m_storage.address());
+ m_initialized = true ;
+ }
+
+ // Constructs in-place using the given typed factory
+ template<class Expr>
+ void construct ( Expr&& factory, typed_in_place_factory_base const* )
+ {
+ BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
+ factory.apply(m_storage.address()) ;
+ m_initialized = true ;
+ }
+
+ template<class Expr>
+ void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag )
+ {
+ destroy();
+ construct(factory,tag);
+ }
+
+ // Constructs in-place using the given typed factory
+ template<class Expr>
+ void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag )
+ {
+ destroy();
+ construct(factory,tag);
+ }
+
+#else
+ // Constructs in-place using the given factory
+ template<class Expr>
+ void construct ( Expr const& factory, in_place_factory_base const* )
+ {
+ BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
+ boost_optional_detail::construct<value_type>(factory, m_storage.address());
+ m_initialized = true ;
+ }
+
+ // Constructs in-place using the given typed factory
+ template<class Expr>
+ void construct ( Expr const& factory, typed_in_place_factory_base const* )
+ {
+ BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
+ factory.apply(m_storage.address()) ;
+ m_initialized = true ;
+ }
+
+ template<class Expr>
+ void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag )
+ {
+ destroy();
+ construct(factory,tag);
+ }
+
+ // Constructs in-place using the given typed factory
+ template<class Expr>
+ void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag )
+ {
+ destroy();
+ construct(factory,tag);
+ }
+#endif
+
+#endif
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Constructs using any expression implicitly convertible to the single argument
+ // of a one-argument T constructor.
+ // Converting constructions of optional<T> from optional<U> uses this function with
+ // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
+ template<class Expr>
+ void construct ( Expr&& expr, void const* )
+ {
+ new (m_storage.address()) internal_type(boost::forward<Expr>(expr)) ;
+ m_initialized = true ;
+ }
+
+ // Assigns using a form any expression implicitly convertible to the single argument
+ // of a T's assignment operator.
+ // Converting assignments of optional<T> from optional<U> uses this function with
+ // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
+ template<class Expr>
+ void assign_expr_to_initialized ( Expr&& expr, void const* )
+ {
+ assign_value(boost::forward<Expr>(expr), is_reference_predicate());
+ }
+#else
+ // Constructs using any expression implicitly convertible to the single argument
+ // of a one-argument T constructor.
+ // Converting constructions of optional<T> from optional<U> uses this function with
+ // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
+ template<class Expr>
+ void construct ( Expr const& expr, void const* )
+ {
+ new (m_storage.address()) internal_type(expr) ;
+ m_initialized = true ;
+ }
+
+ // Assigns using a form any expression implicitly convertible to the single argument
+ // of a T's assignment operator.
+ // Converting assignments of optional<T> from optional<U> uses this function with
+ // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
+ template<class Expr>
+ void assign_expr_to_initialized ( Expr const& expr, void const* )
+ {
+ assign_value(expr, is_reference_predicate());
+ }
+
+#endif
+
+#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
+ // BCB5.64 (and probably lower versions) workaround.
+ // The in-place factories are supported by means of catch-all constructors
+ // and assignment operators (the functions are parameterized in terms of
+ // an arbitrary 'Expr' type)
+ // This compiler incorrectly resolves the overload set and sinks optional<T> and optional<U>
+ // to the 'Expr'-taking functions even though explicit overloads are present for them.
+ // Thus, the following overload is needed to properly handle the case when the 'lhs'
+ // is another optional.
+ //
+ // For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error
+ // instead of choosing the wrong overload
+ //
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
+ template<class Expr>
+ void construct ( Expr&& expr, optional_tag const* )
+ {
+ if ( expr.is_initialized() )
+ {
+ // An exception can be thrown here.
+ // It it happens, THIS will be left uninitialized.
+ new (m_storage.address()) internal_type(types::move(expr.get())) ;
+ m_initialized = true ;
+ }
+ }
+#else
+ // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
+ template<class Expr>
+ void construct ( Expr const& expr, optional_tag const* )
+ {
+ if ( expr.is_initialized() )
+ {
+ // An exception can be thrown here.
+ // It it happens, THIS will be left uninitialized.
+ new (m_storage.address()) internal_type(expr.get()) ;
+ m_initialized = true ;
+ }
+ }
+#endif
+#endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
+
+ void assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; }
+ void assign_value ( argument_type val, is_reference_tag ) { construct(val); }
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ void assign_value ( rval_reference_type val, is_not_reference_tag ) { get_impl() = static_cast<rval_reference_type>(val); }
+ void assign_value ( rval_reference_type val, is_reference_tag ) { construct( static_cast<rval_reference_type>(val) ); }
+#endif
+
+ void destroy()
+ {
+ if ( m_initialized )
+ destroy_impl(is_reference_predicate()) ;
+ }
+
+ reference_const_type get_impl() const { return dereference(get_object(), is_reference_predicate() ) ; }
+ reference_type get_impl() { return dereference(get_object(), is_reference_predicate() ) ; }
+
+ pointer_const_type get_ptr_impl() const { return cast_ptr(get_object(), is_reference_predicate() ) ; }
+ pointer_type get_ptr_impl() { return cast_ptr(get_object(), is_reference_predicate() ) ; }
+
+ private :
+
+ // internal_type can be either T or reference_content<T>
+#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
+ // This workaround is supposed to silence GCC warnings about broken strict aliasing rules
+ internal_type const* get_object() const
+ {
+ union { void const* ap_pvoid; internal_type const* as_ptype; } caster = { m_storage.address() };
+ return caster.as_ptype;
+ }
+ internal_type * get_object()
+ {
+ union { void* ap_pvoid; internal_type* as_ptype; } caster = { m_storage.address() };
+ return caster.as_ptype;
+ }
+#else
+ internal_type const* get_object() const { return static_cast<internal_type const*>(m_storage.address()); }
+ internal_type * get_object() { return static_cast<internal_type *> (m_storage.address()); }
+#endif
+
+ // reference_content<T> lacks an implicit conversion to T&, so the following is needed to obtain a proper reference.
+ reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; }
+ reference_type dereference( internal_type* p, is_not_reference_tag ) { return *p ; }
+ reference_const_type dereference( internal_type const* p, is_reference_tag ) const { return p->get() ; }
+ reference_type dereference( internal_type* p, is_reference_tag ) { return p->get() ; }
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
+ void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->internal_type::~internal_type() ; m_initialized = false ; }
+#else
+ void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->~T() ; m_initialized = false ; }
+#endif
+
+ void destroy_impl ( is_reference_tag ) { m_initialized = false ; }
+
+ // If T is of reference type, trying to get a pointer to the held value must result in a compile-time error.
+ // Decent compilers should disallow conversions from reference_content<T>* to T*, but just in case,
+ // the following olverloads are used to filter out the case and guarantee an error in case of T being a reference.
+ pointer_const_type cast_ptr( internal_type const* p, is_not_reference_tag ) const { return p ; }
+ pointer_type cast_ptr( internal_type * p, is_not_reference_tag ) { return p ; }
+ pointer_const_type cast_ptr( internal_type const* p, is_reference_tag ) const { return &p->get() ; }
+ pointer_type cast_ptr( internal_type * p, is_reference_tag ) { return &p->get() ; }
+
+ bool m_initialized ;
+ storage_type m_storage ;
+} ;
+
+} // namespace optional_detail
+
+template<class T>
+class optional : public optional_detail::optional_base<T>
+{
+ typedef optional_detail::optional_base<T> base ;
+
+ public :
+
+ typedef optional<T> this_type ;
+
+ typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ;
+ typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ;
+ typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type rval_reference_type ;
+ typedef BOOST_DEDUCED_TYPENAME base::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ;
+#endif
+ typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ;
+ typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ;
+ typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ;
+
+ // Creates an optional<T> uninitialized.
+ // No-throw
+ optional() BOOST_NOEXCEPT : base() {}
+
+ // Creates an optional<T> uninitialized.
+ // No-throw
+ optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {}
+
+ // Creates an optional<T> initialized with 'val'.
+ // Can throw if T::T(T const&) does
+ optional ( argument_type val ) : base(val) {}
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Creates an optional<T> initialized with 'move(val)'.
+ // Can throw if T::T(T &&) does
+ optional ( rval_reference_type val ) : base( boost::forward<T>(val) )
+ {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();}
+#endif
+
+ // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
+ // Can throw if T::T(T const&) does
+ optional ( bool cond, argument_type val ) : base(cond,val) {}
+
+ // NOTE: MSVC needs templated versions first
+
+ // Creates a deep copy of another convertible optional<U>
+ // Requires a valid conversion from U to T.
+ // Can throw if T::T(U const&) does
+ template<class U>
+ explicit optional ( optional<U> const& rhs )
+ :
+ base()
+ {
+ if ( rhs.is_initialized() )
+ this->construct(rhs.get());
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Creates a deep move of another convertible optional<U>
+ // Requires a valid conversion from U to T.
+ // Can throw if T::T(U&&) does
+ template<class U>
+ explicit optional ( optional<U> && rhs )
+ :
+ base()
+ {
+ if ( rhs.is_initialized() )
+ this->construct( boost::move(rhs.get()) );
+ }
+#endif
+
+#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
+ // Creates an optional<T> with an expression which can be either
+ // (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
+ // (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
+ // (c) Any expression implicitly convertible to the single type
+ // of a one-argument T's constructor.
+ // (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
+ // even though explicit overloads are present for these.
+ // Depending on the above some T ctor is called.
+ // Can throw if the resolved T ctor throws.
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+
+
+ template<class Expr>
+ explicit optional ( Expr&& expr,
+ BOOST_DEDUCED_TYPENAME boost::disable_if_c<
+ (boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type>::value) ||
+ boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type, none_t>::value >::type* = 0
+ )
+ : base(boost::forward<Expr>(expr),boost::addressof(expr))
+ {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, Expr&&>();}
+
+#else
+ template<class Expr>
+ explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
+#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+#endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
+
+ // Creates a deep copy of another optional<T>
+ // Can throw if T::T(T const&) does
+ optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {}
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Creates a deep move of another optional<T>
+ // Can throw if T::T(T&&) does
+ optional ( optional && rhs )
+ BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
+ : base( boost::move(rhs) )
+ {}
+
+#endif
+ // No-throw (assuming T::~T() doesn't)
+ ~optional() {}
+
+#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
+ // Assigns from an expression. See corresponding constructor.
+ // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+
+ template<class Expr>
+ BOOST_DEDUCED_TYPENAME boost::disable_if_c<
+ boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type>::value ||
+ boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type, none_t>::value,
+ optional&
+ >::type
+ operator= ( Expr&& expr )
+ {
+ optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, Expr&&>();
+ this->assign_expr(boost::forward<Expr>(expr),boost::addressof(expr));
+ return *this ;
+ }
+
+#else
+ template<class Expr>
+ optional& operator= ( Expr const& expr )
+ {
+ this->assign_expr(expr,boost::addressof(expr));
+ return *this ;
+ }
+#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+#endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
+
+ // Copy-assigns from another convertible optional<U> (converts && deep-copies the rhs value)
+ // Requires a valid conversion from U to T.
+ // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
+ template<class U>
+ optional& operator= ( optional<U> const& rhs )
+ {
+ this->assign(rhs);
+ return *this ;
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Move-assigns from another convertible optional<U> (converts && deep-moves the rhs value)
+ // Requires a valid conversion from U to T.
+ // Basic Guarantee: If T::T( U && ) throws, this is left UNINITIALIZED
+ template<class U>
+ optional& operator= ( optional<U> && rhs )
+ {
+ this->assign(boost::move(rhs));
+ return *this ;
+ }
+#endif
+
+ // Assigns from another optional<T> (deep-copies the rhs value)
+ // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
+ // (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
+ optional& operator= ( optional const& rhs )
+ {
+ this->assign( static_cast<base const&>(rhs) ) ;
+ return *this ;
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Assigns from another optional<T> (deep-moves the rhs value)
+ optional& operator= ( optional && rhs )
+ BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
+ {
+ this->assign( static_cast<base &&>(rhs) ) ;
+ return *this ;
+ }
+#endif
+
+ // Assigns from a T (deep-copies the rhs value)
+ // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
+ optional& operator= ( argument_type val )
+ {
+ this->assign( val ) ;
+ return *this ;
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Assigns from a T (deep-moves the rhs value)
+ optional& operator= ( rval_reference_type val )
+ {
+ optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();
+ this->assign( boost::move(val) ) ;
+ return *this ;
+ }
+#endif
+
+ // Assigns from a "none"
+ // Which destroys the current value, if any, leaving this UNINITIALIZED
+ // No-throw (assuming T::~T() doesn't)
+ optional& operator= ( none_t none_ ) BOOST_NOEXCEPT
+ {
+ this->assign( none_ ) ;
+ return *this ;
+ }
+
+#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ // Constructs in-place
+ // upon exception *this is always uninitialized
+ template<class... Args>
+ void emplace ( Args&&... args )
+ {
+ this->emplace_assign( boost::forward<Args>(args)... );
+ }
+#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
+ template<class Arg>
+ void emplace ( Arg&& arg )
+ {
+ this->emplace_assign( boost::forward<Arg>(arg) );
+ }
+
+ void emplace ()
+ {
+ this->emplace_assign();
+ }
+#else
+ template<class Arg>
+ void emplace ( const Arg& arg )
+ {
+ this->emplace_assign( arg );
+ }
+
+ template<class Arg>
+ void emplace ( Arg& arg )
+ {
+ this->emplace_assign( arg );
+ }
+
+ void emplace ()
+ {
+ this->emplace_assign();
+ }
+#endif
+
+ void swap( optional & arg )
+ BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
+ {
+ // allow for Koenig lookup
+ boost::swap(*this, arg);
+ }
+
+
+ // Returns a reference to the value if this is initialized, otherwise,
+ // the behaviour is UNDEFINED
+ // No-throw
+ reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
+ reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
+
+ // Returns a copy of the value if this is initialized, 'v' otherwise
+ reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
+ reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; }
+
+ // Returns a pointer to the value if this is initialized, otherwise,
+ // the behaviour is UNDEFINED
+ // No-throw
+ pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
+ pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
+
+ // Returns a reference to the value if this is initialized, otherwise,
+ // the behaviour is UNDEFINED
+ // No-throw
+#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
+ reference_const_type operator *() const& { return this->get() ; }
+ reference_type operator *() & { return this->get() ; }
+ reference_type_of_temporary_wrapper operator *() && { return base::types::move(this->get()) ; }
+#else
+ reference_const_type operator *() const { return this->get() ; }
+ reference_type operator *() { return this->get() ; }
+#endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS
+
+#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
+ reference_const_type value() const&
+ {
+ if (this->is_initialized())
+ return this->get() ;
+ else
+ throw_exception(bad_optional_access());
+ }
+
+ reference_type value() &
+ {
+ if (this->is_initialized())
+ return this->get() ;
+ else
+ throw_exception(bad_optional_access());
+ }
+
+ reference_type_of_temporary_wrapper value() &&
+ {
+ if (this->is_initialized())
+ return base::types::move(this->get()) ;
+ else
+ throw_exception(bad_optional_access());
+ }
+
+#else
+ reference_const_type value() const
+ {
+ if (this->is_initialized())
+ return this->get() ;
+ else
+ throw_exception(bad_optional_access());
+ }
+
+ reference_type value()
+ {
+ if (this->is_initialized())
+ return this->get() ;
+ else
+ throw_exception(bad_optional_access());
+ }
+#endif
+
+
+#ifndef BOOST_NO_CXX11_REF_QUALIFIERS
+ template <class U>
+ value_type value_or ( U&& v ) const&
+ {
+ if (this->is_initialized())
+ return get();
+ else
+ return boost::forward<U>(v);
+ }
+
+ template <class U>
+ value_type value_or ( U&& v ) &&
+ {
+ if (this->is_initialized())
+ return base::types::move(get());
+ else
+ return boost::forward<U>(v);
+ }
+#elif !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ template <class U>
+ value_type value_or ( U&& v ) const
+ {
+ if (this->is_initialized())
+ return get();
+ else
+ return boost::forward<U>(v);
+ }
+#else
+ template <class U>
+ value_type value_or ( U const& v ) const
+ {
+ if (this->is_initialized())
+ return get();
+ else
+ return v;
+ }
+
+ template <class U>
+ value_type value_or ( U& v ) const
+ {
+ if (this->is_initialized())
+ return get();
+ else
+ return v;
+ }
+#endif
+
+
+#ifndef BOOST_NO_CXX11_REF_QUALIFIERS
+ template <typename F>
+ value_type value_or_eval ( F f ) const&
+ {
+ if (this->is_initialized())
+ return get();
+ else
+ return f();
+ }
+
+ template <typename F>
+ value_type value_or_eval ( F f ) &&
+ {
+ if (this->is_initialized())
+ return base::types::move(get());
+ else
+ return f();
+ }
+#else
+ template <typename F>
+ value_type value_or_eval ( F f ) const
+ {
+ if (this->is_initialized())
+ return get();
+ else
+ return f();
+ }
+#endif
+
+ bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; }
+
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+} ;
+
+} // namespace boost
+
+
+#endif // header guard
diff --git a/boost/optional/detail/optional_aligned_storage.hpp b/boost/optional/detail/optional_aligned_storage.hpp
new file mode 100644
index 0000000000..6c7d58148e
--- /dev/null
+++ b/boost/optional/detail/optional_aligned_storage.hpp
@@ -0,0 +1,75 @@
+// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
+// Copyright (C) 2016 Andrzej Krzemienski.
+//
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/optional for documentation.
+//
+// You are welcome to contact the author at:
+// fernando_cacciola@hotmail.com
+// akrzemi1@gmail.com
+
+#ifndef BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_ALIGNED_STORAGE_AJK_12FEB2016_HPP
+#define BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_ALIGNED_STORAGE_AJK_12FEB2016_HPP
+
+namespace boost {
+
+namespace optional_detail {
+// This local class is used instead of that in "aligned_storage.hpp"
+// because I've found the 'official' class to ICE BCB5.5
+// when some types are used with optional<>
+// (due to sizeof() passed down as a non-type template parameter)
+template <class T>
+class aligned_storage
+{
+ // Borland ICEs if unnamed unions are used for this!
+ union
+ // This works around GCC warnings about breaking strict aliasing rules when casting storage address to T*
+#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
+ __attribute__((__may_alias__))
+#endif
+ dummy_u
+ {
+ char data[ sizeof(T) ];
+ BOOST_DEDUCED_TYPENAME type_with_alignment<
+ ::boost::alignment_of<T>::value >::type aligner_;
+ } dummy_ ;
+
+ public:
+
+#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
+ void const* address() const { return &dummy_; }
+ void * address() { return &dummy_; }
+#else
+ void const* address() const { return dummy_.data; }
+ void * address() { return dummy_.data; }
+#endif
+
+#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
+ // This workaround is supposed to silence GCC warnings about broken strict aliasing rules
+ T const* ptr_ref() const
+ {
+ union { void const* ap_pvoid; T const* as_ptype; } caster = { address() };
+ return caster.as_ptype;
+ }
+ T * ptr_ref()
+ {
+ union { void* ap_pvoid; T* as_ptype; } caster = { address() };
+ return caster.as_ptype;
+ }
+#else
+ T const* ptr_ref() const { return static_cast<T const*>(address()); }
+ T * ptr_ref() { return static_cast<T *> (address()); }
+#endif
+
+ T const& ref() const { return *ptr_ref(); }
+ T & ref() { return *ptr_ref(); }
+
+} ;
+
+} // namespace optional_detail
+} // namespace boost
+
+#endif // header guard
diff --git a/boost/optional/detail/optional_config.hpp b/boost/optional/detail/optional_config.hpp
new file mode 100644
index 0000000000..648744edbe
--- /dev/null
+++ b/boost/optional/detail/optional_config.hpp
@@ -0,0 +1,99 @@
+// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
+// Copyright (C) 2015 Andrzej Krzemienski.
+//
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/optional for documentation.
+//
+// You are welcome to contact the author at:
+// akrzemi1@gmail.com
+
+#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_CONFIG_AJK_28JAN2015_HPP
+#define BOOST_OPTIONAL_DETAIL_OPTIONAL_CONFIG_AJK_28JAN2015_HPP
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+
+#if (defined BOOST_NO_CXX11_RVALUE_REFERENCES) || (defined BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES)
+# define BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+#endif
+
+#if BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION,<=700)
+// AFAICT only Intel 7 correctly resolves the overload set
+// that includes the in-place factory taking functions,
+// so for the other icc versions, in-place factory support
+// is disabled
+# define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
+#endif
+
+#if BOOST_WORKAROUND(__BORLANDC__, <= 0x551)
+// BCB (5.5.1) cannot parse the nested template struct in an inplace factory.
+# define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
+#endif
+
+#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) \
+ && defined BOOST_BCB_PARTIAL_SPECIALIZATION_BUG
+// BCB (up to 5.64) has the following bug:
+// If there is a member function/operator template of the form
+// template<class Expr> mfunc( Expr expr ) ;
+// some calls are resolved to this even if there are other better matches.
+// The effect of this bug is that calls to converting ctors and assignments
+// are incorrectly sink to this general catch-all member function template as shown above.
+# define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
+#endif
+
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+// GCC since 3.3 has may_alias attribute that helps to alleviate optimizer issues with
+// regard to violation of the strict aliasing rules. The optional< T > storage type is marked
+// with this attribute in order to let the compiler know that it will alias objects of type T
+// and silence compilation warnings.
+# define BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS
+#endif
+
+#if (defined(_MSC_VER) && _MSC_VER <= 1800)
+// on MSCV 2013 and earlier an unwanted temporary is created when you assign from
+// a const lvalue of integral type. Thus we bind not to the original address but
+// to a temporary.
+# define BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT
+#endif
+
+#if (defined __GNUC__) && (!defined BOOST_INTEL_CXX_VERSION) && (!defined __clang__)
+// On some GCC versions an unwanted temporary is created when you copy-initialize
+// from a const lvalue of integral type. Thus we bind not to the original address but
+// to a temporary.
+
+# if (__GNUC__ < 4)
+# define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT
+# endif
+
+# if (__GNUC__ == 4 && __GNUC_MINOR__ <= 5)
+# define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT
+# endif
+
+# if (__GNUC__ == 5 && __GNUC_MINOR__ < 2)
+# define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT
+# endif
+
+# if (__GNUC__ == 5 && __GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ == 0)
+# define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT
+# endif
+
+#endif // defined(__GNUC__)
+
+#if (defined __GNUC__) && (!defined BOOST_NO_CXX11_RVALUE_REFERENCES)
+// On some initial rvalue reference implementations GCC does it in a strange way,
+// preferring perfect-forwarding constructor to implicit copy constructor.
+
+# if (__GNUC__ == 4 && __GNUC_MINOR__ == 4)
+# define BOOST_OPTIONAL_CONFIG_NO_LEGAL_CONVERT_FROM_REF
+# endif
+
+# if (__GNUC__ == 4 && __GNUC_MINOR__ == 5)
+# define BOOST_OPTIONAL_CONFIG_NO_LEGAL_CONVERT_FROM_REF
+# endif
+
+#endif // defined(__GNUC__)
+
+#endif // header guard
diff --git a/boost/optional/detail/optional_factory_support.hpp b/boost/optional/detail/optional_factory_support.hpp
new file mode 100644
index 0000000000..efff92a503
--- /dev/null
+++ b/boost/optional/detail/optional_factory_support.hpp
@@ -0,0 +1,36 @@
+// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
+// Copyright (C) 2016 Andrzej Krzemienski.
+//
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/optional for documentation.
+//
+// You are welcome to contact the author at:
+// fernando_cacciola@hotmail.com
+// akrzemi1@gmail.com
+
+#ifndef BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_FACTORY_SUPPORT_AJK_12FEB2016_HPP
+#define BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_FACTORY_SUPPORT_AJK_12FEB2016_HPP
+
+// Daniel Wallin discovered that bind/apply.hpp badly interacts with the apply<>
+// member template of a factory as used in the optional<> implementation.
+// He proposed this simple fix which is to move the call to apply<> outside
+// namespace boost.
+namespace boost_optional_detail
+{
+ template <class T, class Factory>
+ inline void construct(Factory const& factory, void* address)
+ {
+ factory.BOOST_NESTED_TEMPLATE apply<T>(address);
+ }
+}
+
+namespace boost
+{
+ class in_place_factory_base ;
+ class typed_in_place_factory_base ;
+}
+
+#endif // header guard
diff --git a/boost/optional/detail/optional_reference_spec.hpp b/boost/optional/detail/optional_reference_spec.hpp
new file mode 100644
index 0000000000..ba3951af7b
--- /dev/null
+++ b/boost/optional/detail/optional_reference_spec.hpp
@@ -0,0 +1,203 @@
+// Copyright (C) 2015-2016 Andrzej Krzemienski.
+//
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/optional for documentation.
+//
+// You are welcome to contact the author at:
+// akrzemi1@gmail.com
+
+#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_REFERENCE_SPEC_AJK_03OCT2015_HPP
+#define BOOST_OPTIONAL_DETAIL_OPTIONAL_REFERENCE_SPEC_AJK_03OCT2015_HPP
+
+#ifdef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_const.hpp>
+#endif
+
+# if 1
+
+namespace boost {
+
+namespace detail {
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+
+template <class From>
+void prevent_binding_rvalue()
+{
+#ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES
+ BOOST_STATIC_ASSERT_MSG(boost::is_lvalue_reference<From>::value,
+ "binding rvalue references to optional lvalue references is disallowed");
+#endif
+}
+
+template <class T>
+BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type& forward_reference(T&& r)
+{
+ BOOST_STATIC_ASSERT_MSG(boost::is_lvalue_reference<T>::value,
+ "binding rvalue references to optional lvalue references is disallowed");
+ return boost::forward<T>(r);
+}
+
+#endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+
+template <class From>
+void prevent_assignment_from_false_const_integral()
+{
+#ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES
+#ifdef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT
+ // MSVC compiler without rvalue refernces: we need to disable the asignment from
+ // const integral lvalue reference, as it may be an invalid temporary
+ BOOST_STATIC_ASSERT_MSG(!(boost::is_const<From>::value && boost::is_integral<From>::value),
+ "binding const lvalue references to integral types is disabled in this compiler");
+#endif
+#endif
+}
+
+template <class T>
+struct is_optional_
+{
+ static const bool value = false;
+};
+
+template <class U>
+struct is_optional_< ::boost::optional<U> >
+{
+ static const bool value = true;
+};
+
+template <class T>
+struct is_no_optional
+{
+ static const bool value = !is_optional_<BOOST_DEDUCED_TYPENAME boost::decay<T>::type>::value;
+};
+
+} // namespace detail
+
+template <class T>
+class optional<T&> : public optional_detail::optional_tag
+{
+ T* ptr_;
+
+public:
+ typedef T& value_type;
+ typedef T& reference_type;
+ typedef T& reference_const_type;
+ typedef T& rval_reference_type;
+ typedef T* pointer_type;
+ typedef T* pointer_const_type;
+
+ optional() BOOST_NOEXCEPT : ptr_() {}
+ optional(none_t) BOOST_NOEXCEPT : ptr_() {}
+
+ template <class U>
+ explicit optional(const optional<U&>& rhs) BOOST_NOEXCEPT : ptr_(rhs.ptr_) {}
+ optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.ptr_) {}
+
+
+ optional& operator=(const optional& rhs) BOOST_NOEXCEPT { ptr_ = rhs.ptr_; return *this; }
+ template <class U>
+ optional& operator=(const optional<U&>& rhs) BOOST_NOEXCEPT { ptr_ = rhs.ptr_; return *this; }
+ optional& operator=(none_t) BOOST_NOEXCEPT { ptr_ = 0; return *this; }
+
+
+ void swap(optional& rhs) BOOST_NOEXCEPT { std::swap(ptr_, rhs.ptr_); }
+ T& get() const { BOOST_ASSERT(ptr_); return *ptr_; }
+
+ T* get_ptr() const BOOST_NOEXCEPT { return ptr_; }
+ T* operator->() const { BOOST_ASSERT(ptr_); return ptr_; }
+ T& operator*() const { BOOST_ASSERT(ptr_); return *ptr_; }
+ T& value() const { return ptr_ ? *ptr_ : (throw_exception(bad_optional_access()), *ptr_); }
+
+ bool operator!() const BOOST_NOEXCEPT { return ptr_ == 0; }
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+
+ void reset() BOOST_NOEXCEPT { ptr_ = 0; }
+
+ bool is_initialized() const BOOST_NOEXCEPT { return ptr_ != 0; }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+
+ template <class R>
+ optional(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R> >::type* = 0) BOOST_NOEXCEPT
+ : ptr_(boost::addressof(r)) { detail::prevent_binding_rvalue<R>(); }
+
+ template <class R>
+ optional(bool cond, R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R> >::type* = 0) BOOST_NOEXCEPT
+ : ptr_(cond ? boost::addressof(r) : 0) { detail::prevent_binding_rvalue<R>(); }
+
+ template <class R>
+ BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R>, optional<T&>&>::type
+ operator=(R&& r) BOOST_NOEXCEPT { detail::prevent_binding_rvalue<R>(); ptr_ = boost::addressof(r); return *this; }
+
+ template <class R>
+ void emplace(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R> >::type* = 0) BOOST_NOEXCEPT
+ { detail::prevent_binding_rvalue<R>(); ptr_ = boost::addressof(r); }
+
+ template <class R>
+ T& get_value_or(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R> >::type* = 0) const BOOST_NOEXCEPT
+ { detail::prevent_binding_rvalue<R>(); return ptr_ ? *ptr_ : r; }
+
+ template <class R>
+ T& value_or(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R> >::type* = 0) const BOOST_NOEXCEPT
+ { detail::prevent_binding_rvalue<R>(); return ptr_ ? *ptr_ : r; }
+
+ template <class R>
+ void reset(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R> >::type* = 0) BOOST_NOEXCEPT
+ { detail::prevent_binding_rvalue<R>(); ptr_ = boost::addressof(r); }
+
+ template <class F>
+ T& value_or_eval(F f) const { return ptr_ ? *ptr_ : detail::forward_reference(f()); }
+
+#else // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+
+ template <class U>
+ optional(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U> >::type* = 0) BOOST_NOEXCEPT : ptr_(boost::addressof(v)) { }
+
+ template <class U>
+ optional(bool cond, U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U> >::type* = 0) BOOST_NOEXCEPT : ptr_(cond ? boost::addressof(v) : 0) {}
+
+ template <class U>
+ BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U>, optional<T&>&>::type
+ operator=(U& v) BOOST_NOEXCEPT
+ {
+ detail::prevent_assignment_from_false_const_integral<U>();
+ ptr_ = boost::addressof(v); return *this;
+ }
+
+ template <class U>
+ void emplace(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U> >::type* = 0) BOOST_NOEXCEPT
+ { ptr_ = boost::addressof(v); }
+
+ template <class U>
+ T& get_value_or(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U> >::type* = 0) const BOOST_NOEXCEPT
+ { return ptr_ ? *ptr_ : v; }
+
+ template <class U>
+ T& value_or(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U> >::type* = 0) const BOOST_NOEXCEPT
+ { return ptr_ ? *ptr_ : v; }
+
+ template <class U>
+ void reset(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U> >::type* = 0) BOOST_NOEXCEPT
+ { ptr_ = boost::addressof(v); }
+
+ template <class F>
+ T& value_or_eval(F f) const { return ptr_ ? *ptr_ : f(); }
+
+#endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+};
+
+template <class T>
+ void swap ( optional<T&>& x, optional<T&>& y) BOOST_NOEXCEPT
+{
+ x.swap(y);
+}
+
+} // namespace boost
+
+#endif // 1/0
+
+#endif // header guard
diff --git a/boost/optional/detail/optional_relops.hpp b/boost/optional/detail/optional_relops.hpp
new file mode 100644
index 0000000000..3f961179d7
--- /dev/null
+++ b/boost/optional/detail/optional_relops.hpp
@@ -0,0 +1,196 @@
+// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
+// Copyright (C) 2015 Andrzej Krzemienski.
+//
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/optional for documentation.
+//
+// You are welcome to contact the author at:
+// akrzemi1@gmail.com
+
+#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_RELOPS_AJK_03OCT2015_HPP
+#define BOOST_OPTIONAL_DETAIL_OPTIONAL_RELOPS_AJK_03OCT2015_HPP
+
+namespace boost {
+
+// optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values).
+// WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointess() in generic code instead.
+
+
+//
+// optional<T> vs optional<T> cases
+//
+
+template<class T>
+inline
+bool operator == ( optional<T> const& x, optional<T> const& y )
+{ return equal_pointees(x,y); }
+
+template<class T>
+inline
+bool operator < ( optional<T> const& x, optional<T> const& y )
+{ return less_pointees(x,y); }
+
+template<class T>
+inline
+bool operator != ( optional<T> const& x, optional<T> const& y )
+{ return !( x == y ) ; }
+
+template<class T>
+inline
+bool operator > ( optional<T> const& x, optional<T> const& y )
+{ return y < x ; }
+
+template<class T>
+inline
+bool operator <= ( optional<T> const& x, optional<T> const& y )
+{ return !( y < x ) ; }
+
+template<class T>
+inline
+bool operator >= ( optional<T> const& x, optional<T> const& y )
+{ return !( x < y ) ; }
+
+
+//
+// optional<T> vs T cases
+//
+template<class T>
+inline
+bool operator == ( optional<T> const& x, T const& y )
+{ return equal_pointees(x, optional<T>(y)); }
+
+template<class T>
+inline
+bool operator < ( optional<T> const& x, T const& y )
+{ return less_pointees(x, optional<T>(y)); }
+
+template<class T>
+inline
+bool operator != ( optional<T> const& x, T const& y )
+{ return !( x == y ) ; }
+
+template<class T>
+inline
+bool operator > ( optional<T> const& x, T const& y )
+{ return y < x ; }
+
+template<class T>
+inline
+bool operator <= ( optional<T> const& x, T const& y )
+{ return !( y < x ) ; }
+
+template<class T>
+inline
+bool operator >= ( optional<T> const& x, T const& y )
+{ return !( x < y ) ; }
+
+//
+// T vs optional<T> cases
+//
+
+template<class T>
+inline
+bool operator == ( T const& x, optional<T> const& y )
+{ return equal_pointees( optional<T>(x), y ); }
+
+template<class T>
+inline
+bool operator < ( T const& x, optional<T> const& y )
+{ return less_pointees( optional<T>(x), y ); }
+
+template<class T>
+inline
+bool operator != ( T const& x, optional<T> const& y )
+{ return !( x == y ) ; }
+
+template<class T>
+inline
+bool operator > ( T const& x, optional<T> const& y )
+{ return y < x ; }
+
+template<class T>
+inline
+bool operator <= ( T const& x, optional<T> const& y )
+{ return !( y < x ) ; }
+
+template<class T>
+inline
+bool operator >= ( T const& x, optional<T> const& y )
+{ return !( x < y ) ; }
+
+
+//
+// optional<T> vs none cases
+//
+
+template<class T>
+inline
+bool operator == ( optional<T> const& x, none_t ) BOOST_NOEXCEPT
+{ return !x; }
+
+template<class T>
+inline
+bool operator < ( optional<T> const& x, none_t )
+{ return less_pointees(x,optional<T>() ); }
+
+template<class T>
+inline
+bool operator != ( optional<T> const& x, none_t ) BOOST_NOEXCEPT
+{ return bool(x); }
+
+template<class T>
+inline
+bool operator > ( optional<T> const& x, none_t y )
+{ return y < x ; }
+
+template<class T>
+inline
+bool operator <= ( optional<T> const& x, none_t y )
+{ return !( y < x ) ; }
+
+template<class T>
+inline
+bool operator >= ( optional<T> const& x, none_t y )
+{ return !( x < y ) ; }
+
+//
+// none vs optional<T> cases
+//
+
+template<class T>
+inline
+bool operator == ( none_t , optional<T> const& y ) BOOST_NOEXCEPT
+{ return !y; }
+
+template<class T>
+inline
+bool operator < ( none_t , optional<T> const& y )
+{ return less_pointees(optional<T>() ,y); }
+
+template<class T>
+inline
+bool operator != ( none_t, optional<T> const& y ) BOOST_NOEXCEPT
+{ return bool(y); }
+
+template<class T>
+inline
+bool operator > ( none_t x, optional<T> const& y )
+{ return y < x ; }
+
+template<class T>
+inline
+bool operator <= ( none_t x, optional<T> const& y )
+{ return !( y < x ) ; }
+
+template<class T>
+inline
+bool operator >= ( none_t x, optional<T> const& y )
+{ return !( x < y ) ; }
+
+} // namespace boost
+
+#endif // header guard
+
diff --git a/boost/optional/detail/optional_swap.hpp b/boost/optional/detail/optional_swap.hpp
new file mode 100644
index 0000000000..2a7059e701
--- /dev/null
+++ b/boost/optional/detail/optional_swap.hpp
@@ -0,0 +1,117 @@
+// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
+// Copyright (C) 2015 Andrzej Krzemienski.
+//
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/optional for documentation.
+//
+// You are welcome to contact the author at:
+// akrzemi1@gmail.com
+
+#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_SWAP_AJK_28JAN2015_HPP
+#define BOOST_OPTIONAL_DETAIL_OPTIONAL_SWAP_AJK_28JAN2015_HPP
+
+#include <boost/core/swap.hpp>
+#include <boost/optional/optional_fwd.hpp>
+
+namespace boost {
+
+namespace optional_detail {
+
+template <bool use_default_constructor> struct swap_selector;
+
+template <>
+struct swap_selector<true>
+{
+ template <class T>
+ static void optional_swap ( optional<T>& x, optional<T>& y )
+ {
+ const bool hasX = !!x;
+ const bool hasY = !!y;
+
+ if ( !hasX && !hasY )
+ return;
+
+ if( !hasX )
+ x.emplace();
+ else if ( !hasY )
+ y.emplace();
+
+ // Boost.Utility.Swap will take care of ADL and workarounds for broken compilers
+ boost::swap(x.get(), y.get());
+
+ if( !hasX )
+ y = boost::none ;
+ else if( !hasY )
+ x = boost::none ;
+ }
+};
+
+#ifdef BOOST_OPTIONAL_DETAIL_MOVE
+# undef BOOST_OPTIONAL_DETAIL_MOVE
+#endif
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+# define BOOST_OPTIONAL_DETAIL_MOVE(EXPR_) boost::move(EXPR_)
+#else
+# define BOOST_OPTIONAL_DETAIL_MOVE(EXPR_) EXPR_
+#endif
+
+template <>
+struct swap_selector<false>
+{
+ template <class T>
+ static void optional_swap ( optional<T>& x, optional<T>& y )
+ //BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y)))
+ {
+ if (x)
+ {
+ if (y)
+ {
+ boost::swap(*x, *y);
+ }
+ else
+ {
+ y = BOOST_OPTIONAL_DETAIL_MOVE(*x);
+ x = boost::none;
+ }
+ }
+ else
+ {
+ if (y)
+ {
+ x = BOOST_OPTIONAL_DETAIL_MOVE(*y);
+ y = boost::none;
+ }
+ }
+ }
+};
+
+} // namespace optional_detail
+
+#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined BOOST_CONFIG_RESTORE_OBSOLETE_SWAP_IMPLEMENTATION)
+
+template<class T>
+struct optional_swap_should_use_default_constructor : boost::false_type {} ;
+
+#else
+
+template<class T>
+struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor<T> {} ;
+
+#endif
+
+template <class T>
+inline void swap ( optional<T>& x, optional<T>& y )
+//BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y)))
+{
+ optional_detail::swap_selector<optional_swap_should_use_default_constructor<T>::value>::optional_swap(x, y);
+}
+
+} // namespace boost
+
+#undef BOOST_OPTIONAL_DETAIL_MOVE
+
+#endif // header guard
diff --git a/boost/optional/optional.hpp b/boost/optional/optional.hpp
index 9def94ede8..ff1a16ca48 100644
--- a/boost/optional/optional.hpp
+++ b/boost/optional/optional.hpp
@@ -20,7 +20,6 @@
#include <new>
#include <iosfwd>
-#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/core/addressof.hpp>
#include <boost/core/enable_if.hpp>
@@ -31,208 +30,60 @@
#include <boost/throw_exception.hpp>
#include <boost/type.hpp>
#include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/conditional.hpp>
#include <boost/type_traits/has_nothrow_constructor.hpp>
#include <boost/type_traits/type_with_alignment.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/decay.hpp>
#include <boost/type_traits/is_base_of.hpp>
+#include <boost/type_traits/is_constructible.hpp>
#include <boost/type_traits/is_lvalue_reference.hpp>
#include <boost/type_traits/is_nothrow_move_assignable.hpp>
#include <boost/type_traits/is_nothrow_move_constructible.hpp>
-#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/is_rvalue_reference.hpp>
#include <boost/type_traits/is_same.hpp>
-#include <boost/mpl/if.hpp>
-#include <boost/mpl/bool.hpp>
-#include <boost/mpl/not.hpp>
-#include <boost/detail/reference_content.hpp>
#include <boost/move/utility.hpp>
#include <boost/none.hpp>
#include <boost/utility/compare_pointees.hpp>
#include <boost/optional/optional_fwd.hpp>
+#include <boost/optional/detail/optional_config.hpp>
+#include <boost/optional/detail/optional_factory_support.hpp>
+#include <boost/optional/detail/optional_aligned_storage.hpp>
-#if (defined BOOST_NO_CXX11_RVALUE_REFERENCES) || (defined BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES)
-#define BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
-#endif
-
-#if BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION,<=700)
-// AFAICT only Intel 7 correctly resolves the overload set
-// that includes the in-place factory taking functions,
-// so for the other icc versions, in-place factory support
-// is disabled
-#define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
-#endif
-
-#if BOOST_WORKAROUND(__BORLANDC__, <= 0x551)
-// BCB (5.5.1) cannot parse the nested template struct in an inplace factory.
-#define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
-#endif
-
-#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) \
- && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581) )
-// BCB (up to 5.64) has the following bug:
-// If there is a member function/operator template of the form
-// template<class Expr> mfunc( Expr expr ) ;
-// some calls are resolved to this even if there are other better matches.
-// The effect of this bug is that calls to converting ctors and assignments
-// are incrorrectly sink to this general catch-all member function template as shown above.
-#define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
-#endif
-
-#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
-// GCC since 3.3 has may_alias attribute that helps to alleviate optimizer issues with
-// regard to violation of the strict aliasing rules. The optional< T > storage type is marked
-// with this attribute in order to let the compiler know that it will alias objects of type T
-// and silence compilation warnings.
-#define BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS
-#endif
-
-// Daniel Wallin discovered that bind/apply.hpp badly interacts with the apply<>
-// member template of a factory as used in the optional<> implementation.
-// He proposed this simple fix which is to move the call to apply<> outside
-// namespace boost.
-namespace boost_optional_detail
-{
- template <class T, class Factory>
- inline void construct(Factory const& factory, void* address)
- {
- factory.BOOST_NESTED_TEMPLATE apply<T>(address);
- }
-}
-
-
+#ifdef BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL
+#include <boost/optional/detail/old_optional_implementation.hpp>
+#else
namespace boost {
-class in_place_factory_base ;
-class typed_in_place_factory_base ;
-
-// This forward is needed to refer to namespace scope swap from the member swap
-template<class T> void swap ( optional<T>& x, optional<T>& y );
-
namespace optional_detail {
-// This local class is used instead of that in "aligned_storage.hpp"
-// because I've found the 'official' class to ICE BCB5.5
-// when some types are used with optional<>
-// (due to sizeof() passed down as a non-type template parameter)
-template <class T>
-class aligned_storage
-{
- // Borland ICEs if unnamed unions are used for this!
- union
- // This works around GCC warnings about breaking strict aliasing rules when casting storage address to T*
-#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
- __attribute__((__may_alias__))
-#endif
- dummy_u
- {
- char data[ sizeof(T) ];
- BOOST_DEDUCED_TYPENAME type_with_alignment<
- ::boost::alignment_of<T>::value >::type aligner_;
- } dummy_ ;
-
- public:
-
-#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
- void const* address() const { return &dummy_; }
- void * address() { return &dummy_; }
-#else
- void const* address() const { return dummy_.data; }
- void * address() { return dummy_.data; }
-#endif
-} ;
-
-template<class T>
-struct types_when_isnt_ref
-{
- typedef T const& reference_const_type ;
- typedef T & reference_type ;
-#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
- typedef T && rval_reference_type ;
- typedef T && reference_type_of_temporary_wrapper;
-#ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
- // GCC 4.4 has support for an early draft of rvalue references. The conforming version below
- // causes warnings about returning references to a temporary.
- static T&& move(T&& r) { return r; }
-#else
- static rval_reference_type move(reference_type r) { return boost::move(r); }
-#endif
-#endif
- typedef T const* pointer_const_type ;
- typedef T * pointer_type ;
- typedef T const& argument_type ;
-} ;
-
-template<class T>
-struct types_when_is_ref
-{
- typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type raw_type ;
-
- typedef raw_type& reference_const_type ;
- typedef raw_type& reference_type ;
-#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
- typedef BOOST_DEDUCED_TYPENAME remove_const<raw_type>::type&& rval_reference_type ;
- typedef raw_type& reference_type_of_temporary_wrapper;
- static reference_type move(reference_type r) { return r; }
-#endif
- typedef raw_type* pointer_const_type ;
- typedef raw_type* pointer_type ;
- typedef raw_type& argument_type ;
-} ;
-
-template <class To, class From>
-void prevent_binding_rvalue_ref_to_optional_lvalue_ref()
-{
-#ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES
- BOOST_STATIC_ASSERT_MSG(
- !boost::is_lvalue_reference<To>::value || !boost::is_rvalue_reference<From>::value,
- "binding rvalue references to optional lvalue references is disallowed");
-#endif
-}
struct optional_tag {} ;
+
template<class T>
class optional_base : public optional_tag
{
private :
- typedef
-#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
- BOOST_DEDUCED_TYPENAME
-#endif
- ::boost::detail::make_reference_content<T>::type internal_type ;
-
- typedef aligned_storage<internal_type> storage_type ;
-
- typedef types_when_isnt_ref<T> types_when_not_ref ;
- typedef types_when_is_ref<T> types_when_ref ;
-
+ typedef aligned_storage<T> storage_type ;
typedef optional_base<T> this_type ;
protected :
typedef T value_type ;
- typedef mpl::true_ is_reference_tag ;
- typedef mpl::false_ is_not_reference_tag ;
-
- typedef BOOST_DEDUCED_TYPENAME is_reference<T>::type is_reference_predicate ;
-
- public:
- typedef BOOST_DEDUCED_TYPENAME mpl::if_<is_reference_predicate,types_when_ref,types_when_not_ref>::type types ;
-
protected:
- typedef BOOST_DEDUCED_TYPENAME types::reference_type reference_type ;
- typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ;
+ typedef T & reference_type ;
+ typedef T const& reference_const_type ;
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
- typedef BOOST_DEDUCED_TYPENAME types::rval_reference_type rval_reference_type ;
- typedef BOOST_DEDUCED_TYPENAME types::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ;
+ typedef T && rval_reference_type ;
+ typedef T && reference_type_of_temporary_wrapper ;
#endif
- typedef BOOST_DEDUCED_TYPENAME types::pointer_type pointer_type ;
- typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type pointer_const_type ;
- typedef BOOST_DEDUCED_TYPENAME types::argument_type argument_type ;
+ typedef T * pointer_type ;
+ typedef T const* pointer_const_type ;
+ typedef T const& argument_type ;
// Creates an optional<T> uninitialized.
// No-throw
@@ -252,7 +103,7 @@ class optional_base : public optional_tag
:
m_initialized(false)
{
- construct(val);
+ construct(val);
}
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
@@ -332,7 +183,7 @@ class optional_base : public optional_tag
if (is_initialized())
{
if ( rhs.is_initialized() )
- assign_value(rhs.get_impl(), is_reference_predicate() );
+ assign_value(rhs.get_impl());
else destroy();
}
else
@@ -349,7 +200,7 @@ class optional_base : public optional_tag
if (is_initialized())
{
if ( rhs.is_initialized() )
- assign_value(boost::move(rhs.get_impl()), is_reference_predicate() );
+ assign_value( boost::move(rhs.get_impl()) );
else destroy();
}
else
@@ -368,9 +219,9 @@ class optional_base : public optional_tag
{
if ( rhs.is_initialized() )
#ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
- assign_value(rhs.get(), is_reference_predicate() );
+ assign_value( rhs.get() );
#else
- assign_value(static_cast<value_type>(rhs.get()), is_reference_predicate() );
+ assign_value( static_cast<value_type>(rhs.get()) );
#endif
else destroy();
@@ -395,7 +246,7 @@ class optional_base : public optional_tag
if (is_initialized())
{
if ( rhs.is_initialized() )
- assign_value(static_cast<ref_type>(rhs.get()), is_reference_predicate() );
+ assign_value( static_cast<ref_type>(rhs.get()) );
else destroy();
}
else
@@ -410,7 +261,7 @@ class optional_base : public optional_tag
void assign ( argument_type val )
{
if (is_initialized())
- assign_value(val, is_reference_predicate() );
+ assign_value(val);
else construct(val);
}
@@ -419,7 +270,7 @@ class optional_base : public optional_tag
void assign ( rval_reference_type val )
{
if (is_initialized())
- assign_value( boost::move(val), is_reference_predicate() );
+ assign_value( boost::move(val) );
else construct( boost::move(val) );
}
#endif
@@ -471,14 +322,14 @@ class optional_base : public optional_tag
void construct ( argument_type val )
{
- ::new (m_storage.address()) internal_type(val) ;
+ ::new (m_storage.address()) value_type(val) ;
m_initialized = true ;
}
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
void construct ( rval_reference_type val )
{
- ::new (m_storage.address()) internal_type( types::move(val) ) ;
+ ::new (m_storage.address()) value_type( boost::move(val) ) ;
m_initialized = true ;
}
#endif
@@ -491,7 +342,7 @@ class optional_base : public optional_tag
void emplace_assign ( Args&&... args )
{
destroy();
- ::new (m_storage.address()) internal_type( boost::forward<Args>(args)... );
+ ::new (m_storage.address()) value_type( boost::forward<Args>(args)... );
m_initialized = true ;
}
#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
@@ -499,14 +350,14 @@ class optional_base : public optional_tag
void emplace_assign ( Arg&& arg )
{
destroy();
- ::new (m_storage.address()) internal_type( boost::forward<Arg>(arg) );
+ ::new (m_storage.address()) value_type( boost::forward<Arg>(arg) );
m_initialized = true ;
}
void emplace_assign ()
{
destroy();
- ::new (m_storage.address()) internal_type();
+ ::new (m_storage.address()) value_type();
m_initialized = true ;
}
#else
@@ -514,7 +365,7 @@ class optional_base : public optional_tag
void emplace_assign ( const Arg& arg )
{
destroy();
- ::new (m_storage.address()) internal_type( arg );
+ ::new (m_storage.address()) value_type( arg );
m_initialized = true ;
}
@@ -522,14 +373,14 @@ class optional_base : public optional_tag
void emplace_assign ( Arg& arg )
{
destroy();
- ::new (m_storage.address()) internal_type( arg );
+ ::new (m_storage.address()) value_type( arg );
m_initialized = true ;
}
void emplace_assign ()
{
destroy();
- ::new (m_storage.address()) internal_type();
+ ::new (m_storage.address()) value_type();
m_initialized = true ;
}
#endif
@@ -541,7 +392,6 @@ class optional_base : public optional_tag
template<class Expr>
void construct ( Expr&& factory, in_place_factory_base const* )
{
- BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
boost_optional_detail::construct<value_type>(factory, m_storage.address());
m_initialized = true ;
}
@@ -550,7 +400,6 @@ class optional_base : public optional_tag
template<class Expr>
void construct ( Expr&& factory, typed_in_place_factory_base const* )
{
- BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
factory.apply(m_storage.address()) ;
m_initialized = true ;
}
@@ -575,7 +424,6 @@ class optional_base : public optional_tag
template<class Expr>
void construct ( Expr const& factory, in_place_factory_base const* )
{
- BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
boost_optional_detail::construct<value_type>(factory, m_storage.address());
m_initialized = true ;
}
@@ -584,7 +432,6 @@ class optional_base : public optional_tag
template<class Expr>
void construct ( Expr const& factory, typed_in_place_factory_base const* )
{
- BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
factory.apply(m_storage.address()) ;
m_initialized = true ;
}
@@ -615,7 +462,7 @@ class optional_base : public optional_tag
template<class Expr>
void construct ( Expr&& expr, void const* )
{
- new (m_storage.address()) internal_type(boost::forward<Expr>(expr)) ;
+ new (m_storage.address()) value_type(boost::forward<Expr>(expr)) ;
m_initialized = true ;
}
@@ -626,7 +473,7 @@ class optional_base : public optional_tag
template<class Expr>
void assign_expr_to_initialized ( Expr&& expr, void const* )
{
- assign_value(boost::forward<Expr>(expr), is_reference_predicate());
+ assign_value( boost::forward<Expr>(expr) );
}
#else
// Constructs using any expression implicitly convertible to the single argument
@@ -636,7 +483,7 @@ class optional_base : public optional_tag
template<class Expr>
void construct ( Expr const& expr, void const* )
{
- new (m_storage.address()) internal_type(expr) ;
+ new (m_storage.address()) value_type(expr) ;
m_initialized = true ;
}
@@ -647,7 +494,7 @@ class optional_base : public optional_tag
template<class Expr>
void assign_expr_to_initialized ( Expr const& expr, void const* )
{
- assign_value(expr, is_reference_predicate());
+ assign_value(expr);
}
#endif
@@ -674,7 +521,7 @@ class optional_base : public optional_tag
{
// An exception can be thrown here.
// It it happens, THIS will be left uninitialized.
- new (m_storage.address()) internal_type(types::move(expr.get())) ;
+ new (m_storage.address()) value_type(boost::move(expr.get())) ;
m_initialized = true ;
}
}
@@ -687,78 +534,78 @@ class optional_base : public optional_tag
{
// An exception can be thrown here.
// It it happens, THIS will be left uninitialized.
- new (m_storage.address()) internal_type(expr.get()) ;
+ new (m_storage.address()) value_type(expr.get()) ;
m_initialized = true ;
}
}
#endif
#endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
- void assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; }
- void assign_value ( argument_type val, is_reference_tag ) { construct(val); }
+ void assign_value ( argument_type val ) { get_impl() = val; }
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
- void assign_value ( rval_reference_type val, is_not_reference_tag ) { get_impl() = static_cast<rval_reference_type>(val); }
- void assign_value ( rval_reference_type val, is_reference_tag ) { construct( static_cast<rval_reference_type>(val) ); }
+ void assign_value ( rval_reference_type val ) { get_impl() = static_cast<rval_reference_type>(val); }
#endif
void destroy()
{
if ( m_initialized )
- destroy_impl(is_reference_predicate()) ;
+ destroy_impl() ;
}
- reference_const_type get_impl() const { return dereference(get_object(), is_reference_predicate() ) ; }
- reference_type get_impl() { return dereference(get_object(), is_reference_predicate() ) ; }
+ reference_const_type get_impl() const { return m_storage.ref() ; }
+ reference_type get_impl() { return m_storage.ref() ; }
- pointer_const_type get_ptr_impl() const { return cast_ptr(get_object(), is_reference_predicate() ) ; }
- pointer_type get_ptr_impl() { return cast_ptr(get_object(), is_reference_predicate() ) ; }
+ pointer_const_type get_ptr_impl() const { return m_storage.ptr_ref(); }
+ pointer_type get_ptr_impl() { return m_storage.ptr_ref(); }
private :
- // internal_type can be either T or reference_content<T>
-#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
- // This workaround is supposed to silence GCC warnings about broken strict aliasing rules
- internal_type const* get_object() const
- {
- union { void const* ap_pvoid; internal_type const* as_ptype; } caster = { m_storage.address() };
- return caster.as_ptype;
- }
- internal_type * get_object()
- {
- union { void* ap_pvoid; internal_type* as_ptype; } caster = { m_storage.address() };
- return caster.as_ptype;
- }
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1600)
+ void destroy_impl ( ) { m_storage.ptr_ref()->~T() ; m_initialized = false ; }
#else
- internal_type const* get_object() const { return static_cast<internal_type const*>(m_storage.address()); }
- internal_type * get_object() { return static_cast<internal_type *> (m_storage.address()); }
+ void destroy_impl ( ) { m_storage.ref().T::~T() ; m_initialized = false ; }
#endif
- // reference_content<T> lacks an implicit conversion to T&, so the following is needed to obtain a proper reference.
- reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; }
- reference_type dereference( internal_type* p, is_not_reference_tag ) { return *p ; }
- reference_const_type dereference( internal_type const* p, is_reference_tag ) const { return p->get() ; }
- reference_type dereference( internal_type* p, is_reference_tag ) { return p->get() ; }
+ bool m_initialized ;
+ storage_type m_storage ;
+} ;
+
+// definition of metafunciton is_optional_val_init_candidate
+template <typename U>
+struct is_optional_related
+ : boost::conditional< boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
+ || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, none_t>::value,
+ boost::true_type, boost::false_type>::type
+{};
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40500) && !defined(__SUNPRO_CC)
+ // this condition is a copy paste from is_constructible.hpp
+ // I also disable SUNPRO, as it seems not to support type_traits correctly
+
+template <typename T, typename U>
+struct is_convertible_to_T_or_factory
+ : boost::conditional< boost::is_base_of<boost::in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
+ || boost::is_base_of<boost::typed_in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
+ || boost::is_constructible<T, U&&>::value
+ , boost::true_type, boost::false_type>::type
+{};
-#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
- void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->internal_type::~internal_type() ; m_initialized = false ; }
#else
- void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->~T() ; m_initialized = false ; }
-#endif
- void destroy_impl ( is_reference_tag ) { m_initialized = false ; }
+#define BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT
- // If T is of reference type, trying to get a pointer to the held value must result in a compile-time error.
- // Decent compilers should disallow conversions from reference_content<T>* to T*, but just in case,
- // the following olverloads are used to filter out the case and guarantee an error in case of T being a reference.
- pointer_const_type cast_ptr( internal_type const* p, is_not_reference_tag ) const { return p ; }
- pointer_type cast_ptr( internal_type * p, is_not_reference_tag ) { return p ; }
- pointer_const_type cast_ptr( internal_type const* p, is_reference_tag ) const { return &p->get() ; }
- pointer_type cast_ptr( internal_type * p, is_reference_tag ) { return &p->get() ; }
+template <typename, typename>
+struct is_convertible_to_T_or_factory : boost::true_type
+{};
- bool m_initialized ;
- storage_type m_storage ;
-} ;
+#endif // is_convertible condition
+template <typename T, typename U>
+struct is_optional_val_init_candidate
+ : boost::conditional< !is_optional_related<U>::value && is_convertible_to_T_or_factory<T, U>::value
+ , boost::true_type, boost::false_type>::type
+{};
+
} // namespace optional_detail
template<class T>
@@ -797,7 +644,7 @@ class optional : public optional_detail::optional_base<T>
// Creates an optional<T> initialized with 'move(val)'.
// Can throw if T::T(T &&) does
optional ( rval_reference_type val ) : base( boost::forward<T>(val) )
- {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();}
+ {}
#endif
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
@@ -847,12 +694,10 @@ class optional : public optional_detail::optional_base<T>
template<class Expr>
explicit optional ( Expr&& expr,
- BOOST_DEDUCED_TYPENAME boost::disable_if_c<
- (boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type>::value) ||
- boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type, none_t>::value >::type* = 0
+ BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_val_init_candidate<T, Expr> >::type* = 0
)
: base(boost::forward<Expr>(expr),boost::addressof(expr))
- {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, Expr&&>();}
+ {}
#else
template<class Expr>
@@ -873,23 +718,22 @@ class optional : public optional_detail::optional_base<T>
{}
#endif
- // No-throw (assuming T::~T() doesn't)
+
+#if BOOST_WORKAROUND(_MSC_VER, <= 1600)
+ // On old MSVC compilers the implicitly declared dtor is not called
~optional() {}
+#endif
+
#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
// Assigns from an expression. See corresponding constructor.
// Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
template<class Expr>
- BOOST_DEDUCED_TYPENAME boost::disable_if_c<
- boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type>::value ||
- boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type, none_t>::value,
- optional&
- >::type
+ BOOST_DEDUCED_TYPENAME boost::enable_if<optional_detail::is_optional_val_init_candidate<T, Expr>, optional&>::type
operator= ( Expr&& expr )
{
- optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, Expr&&>();
this->assign_expr(boost::forward<Expr>(expr),boost::addressof(expr));
return *this ;
}
@@ -957,7 +801,6 @@ class optional : public optional_detail::optional_base<T>
// Assigns from a T (deep-moves the rhs value)
optional& operator= ( rval_reference_type val )
{
- optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();
this->assign( boost::move(val) ) ;
return *this ;
}
@@ -1040,7 +883,7 @@ class optional : public optional_detail::optional_base<T>
#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
reference_const_type operator *() const& { return this->get() ; }
reference_type operator *() & { return this->get() ; }
- reference_type_of_temporary_wrapper operator *() && { return base::types::move(this->get()) ; }
+ reference_type_of_temporary_wrapper operator *() && { return boost::move(this->get()) ; }
#else
reference_const_type operator *() const { return this->get() ; }
reference_type operator *() { return this->get() ; }
@@ -1066,7 +909,7 @@ class optional : public optional_detail::optional_base<T>
reference_type_of_temporary_wrapper value() &&
{
if (this->is_initialized())
- return base::types::move(this->get()) ;
+ return boost::move(this->get()) ;
else
throw_exception(bad_optional_access());
}
@@ -1104,7 +947,7 @@ class optional : public optional_detail::optional_base<T>
value_type value_or ( U&& v ) &&
{
if (this->is_initialized())
- return base::types::move(get());
+ return boost::move(get());
else
return boost::forward<U>(v);
}
@@ -1152,7 +995,7 @@ class optional : public optional_detail::optional_base<T>
value_type value_or_eval ( F f ) &&
{
if (this->is_initialized())
- return base::types::move(get());
+ return boost::move(get());
else
return f();
}
@@ -1172,6 +1015,12 @@ class optional : public optional_detail::optional_base<T>
BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
} ;
+} // namespace boost
+
+#endif // BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL
+
+namespace boost {
+
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
template<class T>
class optional<T&&>
@@ -1180,6 +1029,14 @@ class optional<T&&>
} ;
#endif
+} // namespace boost
+
+#ifndef BOOST_OPTIONAL_CONFIG_DONT_SPECIALIZE_OPTIONAL_REFS
+# include <boost/optional/detail/optional_reference_spec.hpp>
+#endif
+
+namespace boost {
+
// Returns optional<T>(v)
template<class T>
inline
@@ -1268,6 +1125,10 @@ get_pointer ( optional<T>& opt )
return opt.get_ptr() ;
}
+} // namespace boost
+
+namespace boost {
+
// The following declaration prevents a bug where operator safe-bool is used upon streaming optional object if you forget the IO header.
template<class CharType, class CharTrait>
std::basic_ostream<CharType, CharTrait>&
@@ -1277,291 +1138,9 @@ operator<<(std::basic_ostream<CharType, CharTrait>& os, optional_detail::optiona
return os;
}
-// optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values).
-// WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointess() in generic code instead.
-
-
-//
-// optional<T> vs optional<T> cases
-//
-
-template<class T>
-inline
-bool operator == ( optional<T> const& x, optional<T> const& y )
-{ return equal_pointees(x,y); }
-
-template<class T>
-inline
-bool operator < ( optional<T> const& x, optional<T> const& y )
-{ return less_pointees(x,y); }
-
-template<class T>
-inline
-bool operator != ( optional<T> const& x, optional<T> const& y )
-{ return !( x == y ) ; }
-
-template<class T>
-inline
-bool operator > ( optional<T> const& x, optional<T> const& y )
-{ return y < x ; }
-
-template<class T>
-inline
-bool operator <= ( optional<T> const& x, optional<T> const& y )
-{ return !( y < x ) ; }
-
-template<class T>
-inline
-bool operator >= ( optional<T> const& x, optional<T> const& y )
-{ return !( x < y ) ; }
-
-
-//
-// optional<T> vs T cases
-//
-template<class T>
-inline
-bool operator == ( optional<T> const& x, T const& y )
-{ return equal_pointees(x, optional<T>(y)); }
-
-template<class T>
-inline
-bool operator < ( optional<T> const& x, T const& y )
-{ return less_pointees(x, optional<T>(y)); }
-
-template<class T>
-inline
-bool operator != ( optional<T> const& x, T const& y )
-{ return !( x == y ) ; }
-
-template<class T>
-inline
-bool operator > ( optional<T> const& x, T const& y )
-{ return y < x ; }
-
-template<class T>
-inline
-bool operator <= ( optional<T> const& x, T const& y )
-{ return !( y < x ) ; }
-
-template<class T>
-inline
-bool operator >= ( optional<T> const& x, T const& y )
-{ return !( x < y ) ; }
-
-//
-// T vs optional<T> cases
-//
-
-template<class T>
-inline
-bool operator == ( T const& x, optional<T> const& y )
-{ return equal_pointees( optional<T>(x), y ); }
-
-template<class T>
-inline
-bool operator < ( T const& x, optional<T> const& y )
-{ return less_pointees( optional<T>(x), y ); }
-
-template<class T>
-inline
-bool operator != ( T const& x, optional<T> const& y )
-{ return !( x == y ) ; }
-
-template<class T>
-inline
-bool operator > ( T const& x, optional<T> const& y )
-{ return y < x ; }
-
-template<class T>
-inline
-bool operator <= ( T const& x, optional<T> const& y )
-{ return !( y < x ) ; }
-
-template<class T>
-inline
-bool operator >= ( T const& x, optional<T> const& y )
-{ return !( x < y ) ; }
-
-
-//
-// optional<T> vs none cases
-//
-
-template<class T>
-inline
-bool operator == ( optional<T> const& x, none_t ) BOOST_NOEXCEPT
-{ return !x; }
-
-template<class T>
-inline
-bool operator < ( optional<T> const& x, none_t )
-{ return less_pointees(x,optional<T>() ); }
-
-template<class T>
-inline
-bool operator != ( optional<T> const& x, none_t ) BOOST_NOEXCEPT
-{ return bool(x); }
-
-template<class T>
-inline
-bool operator > ( optional<T> const& x, none_t y )
-{ return y < x ; }
-
-template<class T>
-inline
-bool operator <= ( optional<T> const& x, none_t y )
-{ return !( y < x ) ; }
-
-template<class T>
-inline
-bool operator >= ( optional<T> const& x, none_t y )
-{ return !( x < y ) ; }
-
-//
-// none vs optional<T> cases
-//
-
-template<class T>
-inline
-bool operator == ( none_t , optional<T> const& y ) BOOST_NOEXCEPT
-{ return !y; }
-
-template<class T>
-inline
-bool operator < ( none_t , optional<T> const& y )
-{ return less_pointees(optional<T>() ,y); }
-
-template<class T>
-inline
-bool operator != ( none_t, optional<T> const& y ) BOOST_NOEXCEPT
-{ return bool(y); }
-
-template<class T>
-inline
-bool operator > ( none_t x, optional<T> const& y )
-{ return y < x ; }
-
-template<class T>
-inline
-bool operator <= ( none_t x, optional<T> const& y )
-{ return !( y < x ) ; }
-
-template<class T>
-inline
-bool operator >= ( none_t x, optional<T> const& y )
-{ return !( x < y ) ; }
-
-namespace optional_detail {
-
-template<bool use_default_constructor> struct swap_selector;
-
-template<>
-struct swap_selector<true>
-{
- template<class T>
- static void optional_swap ( optional<T>& x, optional<T>& y )
- {
- const bool hasX = !!x;
- const bool hasY = !!y;
-
- if ( !hasX && !hasY )
- return;
-
- if( !hasX )
- x.emplace();
- else if ( !hasY )
- y.emplace();
-
- // Boost.Utility.Swap will take care of ADL and workarounds for broken compilers
- boost::swap(x.get(),y.get());
-
- if( !hasX )
- y = boost::none ;
- else if( !hasY )
- x = boost::none ;
- }
-};
-
-#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
-template<>
-struct swap_selector<false>
-{
- template<class T>
- static void optional_swap ( optional<T>& x, optional<T>& y )
- //BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y)))
- {
- if(x)
- {
- if (y)
- {
- boost::swap(*x, *y);
- }
- else
- {
- y = boost::move(*x);
- x = boost::none;
- }
- }
- else
- {
- if (y)
- {
- x = boost::move(*y);
- y = boost::none;
- }
- }
- }
-};
-#else
-template<>
-struct swap_selector<false>
-{
- template<class T>
- static void optional_swap ( optional<T>& x, optional<T>& y )
- {
- const bool hasX = !!x;
- const bool hasY = !!y;
-
- if ( !hasX && hasY )
- {
- x = y.get();
- y = boost::none ;
- }
- else if ( hasX && !hasY )
- {
- y = x.get();
- x = boost::none ;
- }
- else if ( hasX && hasY )
- {
- // Boost.Utility.Swap will take care of ADL and workarounds for broken compilers
- boost::swap(x.get(),y.get());
- }
- }
-};
-#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
-
-} // namespace optional_detail
-
-#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined BOOST_CONFIG_RESTORE_OBSOLETE_SWAP_IMPLEMENTATION)
-
-template<class T>
-struct optional_swap_should_use_default_constructor : boost::false_type {} ;
-
-#else
-
-template<class T>
-struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor<T> {} ;
-
-#endif //BOOST_NO_CXX11_RVALUE_REFERENCES
-
-template<class T> inline void swap ( optional<T>& x, optional<T>& y )
- //BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y)))
-{
- optional_detail::swap_selector<optional_swap_should_use_default_constructor<T>::value>::optional_swap(x, y);
-}
-
} // namespace boost
-#endif
+#include <boost/optional/detail/optional_relops.hpp>
+#include <boost/optional/detail/optional_swap.hpp>
+
+#endif // header guard
diff --git a/boost/optional/optional_fwd.hpp b/boost/optional/optional_fwd.hpp
index fb59682df6..c41a34d398 100644
--- a/boost/optional/optional_fwd.hpp
+++ b/boost/optional/optional_fwd.hpp
@@ -1,4 +1,5 @@
// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
+// Copyright (C) 2016 Andrzej Krzemienski
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -15,15 +16,25 @@
#ifndef BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP
#define BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP
+#include <boost/config/suffix.hpp>
namespace boost {
template<class T> class optional ;
-template<class T> void swap ( optional<T>& , optional<T>& );
+// This forward is needed to refer to namespace scope swap from the member swap
+template<class T> void swap ( optional<T>& , optional<T>& ) ;
template<class T> struct optional_swap_should_use_default_constructor ;
+#ifndef BOOST_OPTIONAL_CONFIG_DONT_SPECIALIZE_OPTIONAL_REFS
+
+template<class T> class optional<T&> ;
+
+template<class T> void swap ( optional<T&>& , optional<T&>& ) BOOST_NOEXCEPT;
+
+#endif
+
} // namespace boost
#endif
diff --git a/boost/pending/relaxed_heap.hpp b/boost/pending/relaxed_heap.hpp
index 13f7af4c0e..1c80df6942 100644
--- a/boost/pending/relaxed_heap.hpp
+++ b/boost/pending/relaxed_heap.hpp
@@ -191,7 +191,10 @@ public:
return !smallest_value || (smallest_value->kind == largest_key);
}
- bool contains(const value_type& x) const { return groups[get(id, x)]; }
+ bool contains(const value_type& x) const {
+ return static_cast<bool>(groups[get(id, x)]);
+ }
+
void pop()
{
diff --git a/boost/pool/detail/mutex.hpp b/boost/pool/detail/mutex.hpp
index 45d8e19eac..8d9b1d5627 100644
--- a/boost/pool/detail/mutex.hpp
+++ b/boost/pool/detail/mutex.hpp
@@ -9,9 +9,13 @@
#ifndef BOOST_POOL_MUTEX_HPP
#define BOOST_POOL_MUTEX_HPP
-#include <boost/config.hpp> // for workarounds
-#if defined (BOOST_HAS_THREADS) && !defined(BOOST_POOL_NO_MT)
-#include <boost/thread/mutex.hpp>
+#include <boost/config.hpp> // for workarounds
+#if defined (BOOST_HAS_THREADS) && !defined(BOOST_POOL_NO_MT)
+#if defined (BOOST_NO_CXX11_HDR_MUTEX)
+#include <boost/thread/mutex.hpp>
+#else
+#include <mutex>
+#endif
#endif
namespace boost{ namespace details{ namespace pool{
@@ -29,10 +33,14 @@ class null_mutex
static void unlock() { }
};
-#if !defined(BOOST_HAS_THREADS) || defined(BOOST_NO_MT) || defined(BOOST_POOL_NO_MT)
- typedef null_mutex default_mutex;
-#else
- typedef boost::mutex default_mutex;
+#if !defined(BOOST_HAS_THREADS) || defined(BOOST_NO_MT) || defined(BOOST_POOL_NO_MT)
+ typedef null_mutex default_mutex;
+#else
+#if defined (BOOST_NO_CXX11_HDR_MUTEX)
+ typedef boost::mutex default_mutex;
+#else
+ typedef std::mutex default_mutex;
+#endif
#endif
} // namespace pool
diff --git a/boost/predef/hardware/simd.h b/boost/predef/hardware/simd.h
index 4de1e70cd3..ac5c9da2ca 100644
--- a/boost/predef/hardware/simd.h
+++ b/boost/predef/hardware/simd.h
@@ -77,12 +77,24 @@ http://www.boost.org/LICENSE_1_0.txt)
# error "Multiple SIMD architectures detected, this cannot happen!"
#endif
-#if defined(BOOST_HW_SIMD_X86_AVAILABLE)
-# define BOOST_HW_SIMD BOOST_HW_SIMD_X86
+#if defined(BOOST_HW_SIMD_X86_AVAILABLE) && defined(BOOST_HW_SIMD_X86_AMD_AVAILABLE)
+ // If both standard _X86 and _X86_AMD are available,
+ // then take the biggest version of the two!
+# if BOOST_HW_SIMD_X86 >= BOOST_HW_SIMD_X86_AMD
+# define BOOST_HW_SIMD BOOST_HW_SIMD_X86
+# else
+# define BOOST_HW_SIMD BOOST_HW_SIMD_X86_AMD
+# endif
#endif
-#if defined(BOOST_HW_SIMD_X86_AMD_AVAILABLE)
-# define BOOST_HW_SIMD BOOST_HW_SIMD_X86_AMD
+#if !defined(BOOST_HW_SIMD)
+ // At this point, only one of these two is defined
+# if defined(BOOST_HW_SIMD_X86_AVAILABLE)
+# define BOOST_HW_SIMD BOOST_HW_SIMD_X86
+# endif
+# if defined(BOOST_HW_SIMD_X86_AMD_AVAILABLE)
+# define BOOST_HW_SIMD BOOST_HW_SIMD_X86_AMD
+# endif
#endif
#if defined(BOOST_HW_SIMD_ARM_AVAILABLE)
diff --git a/boost/predef/hardware/simd/x86.h b/boost/predef/hardware/simd/x86.h
index 0874bc4ea7..88bd81e362 100644
--- a/boost/predef/hardware/simd/x86.h
+++ b/boost/predef/hardware/simd/x86.h
@@ -67,7 +67,7 @@ http://www.boost.org/LICENSE_1_0.txt)
[[`__FMA__`] [BOOST_HW_SIMD_X86_FMA3_VERSION]]
- [[`__AVX2__`] [BOOST_HW_SIMD_x86_AVX2_VERSION]]
+ [[`__AVX2__`] [BOOST_HW_SIMD_X86_AVX2_VERSION]]
]
*/
@@ -99,10 +99,10 @@ http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_HW_SIMD_X86) && defined(__SSE3__)
# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_SSE3_VERSION
#endif
-#if !defined(BOOST_HW_SIMD_X86) && (defined(__SSE2__) || defined(_M_X64) || _M_IX86_FP >= 2)
+#if !defined(BOOST_HW_SIMD_X86) && (defined(__SSE2__) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2))
# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_SSE2_VERSION
#endif
-#if !defined(BOOST_HW_SIMD_X86) && (defined(__SSE__) || defined(_M_X64) || _M_IX86_FP >= 1)
+#if !defined(BOOST_HW_SIMD_X86) && (defined(__SSE__) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1))
# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_SSE_VERSION
#endif
#if !defined(BOOST_HW_SIMD_X86) && defined(__MMX__)
diff --git a/boost/predef/hardware/simd/x86_amd.h b/boost/predef/hardware/simd/x86_amd.h
index 60fd4485ec..c80d1ce2b7 100644
--- a/boost/predef/hardware/simd/x86_amd.h
+++ b/boost/predef/hardware/simd/x86_amd.h
@@ -33,13 +33,13 @@ http://www.boost.org/LICENSE_1_0.txt)
[table
[[__predef_symbol__] [__predef_version__]]
- [[`__SSE4A__`] [BOOST_HW_SIMD_x86_SSE4A_VERSION]]
+ [[`__SSE4A__`] [BOOST_HW_SIMD_X86_SSE4A_VERSION]]
- [[`__FMA4__`] [BOOST_HW_SIMD_x86_FMA4_VERSION]]
+ [[`__FMA4__`] [BOOST_HW_SIMD_X86_FMA4_VERSION]]
- [[`__XOP__`] [BOOST_HW_SIMD_x86_XOP_VERSION]]
+ [[`__XOP__`] [BOOST_HW_SIMD_X86_XOP_VERSION]]
- [[`BOOST_HW_SIMD_X86`] [BOOST_HW_SIMD_x86]]
+ [[`BOOST_HW_SIMD_X86`] [BOOST_HW_SIMD_X86]]
]
[note This predef includes every other x86 SIMD extensions and also has other
diff --git a/boost/predef/hardware/simd/x86_amd/versions.h b/boost/predef/hardware/simd/x86_amd/versions.h
index a0a9e918bb..11157167c6 100644
--- a/boost/predef/hardware/simd/x86_amd/versions.h
+++ b/boost/predef/hardware/simd/x86_amd/versions.h
@@ -30,9 +30,9 @@ http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_HW_SIMD_X86_AMD_SSE4A_VERSION BOOST_VERSION_NUMBER(4, 0, 0)
/*`
- [heading `BOOST_HW_SIMD_X86_XOP_VERSION`]
+ [heading `BOOST_HW_SIMD_X86_FMA4_VERSION`]
- [@https://en.wikipedia.org/wiki/XOP_instruction_set XOP] x86 extension (AMD specific).
+ [@https://en.wikipedia.org/wiki/FMA_instruction_set#FMA4_instruction_set FMA4] x86 extension (AMD specific).
Version number is: *5.1.0*.
*/
diff --git a/boost/predef/os/cygwin.h b/boost/predef/os/cygwin.h
index 1985c97edc..9d36f0f317 100644
--- a/boost/predef/os/cygwin.h
+++ b/boost/predef/os/cygwin.h
@@ -29,7 +29,7 @@ http://www.boost.org/LICENSE_1_0.txt)
defined(__CYGWIN__) \
)
# undef BOOST_OS_CYGWIN
-# define BOOST_OS_CGYWIN BOOST_VERSION_NUMBER_AVAILABLE
+# define BOOST_OS_CYGWIN BOOST_VERSION_NUMBER_AVAILABLE
#endif
#if BOOST_OS_CYGWIN
diff --git a/boost/predef/version.h b/boost/predef/version.h
index 2fcdefa694..8745c94976 100644
--- a/boost/predef/version.h
+++ b/boost/predef/version.h
@@ -1,5 +1,5 @@
/*
-Copyright Rene Rivera 2015
+Copyright Rene Rivera 2015-2016
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
@@ -10,6 +10,6 @@ http://www.boost.org/LICENSE_1_0.txt)
#include <boost/predef/version_number.h>
-#define BOOST_PREDEF_VERSION BOOST_VERSION_NUMBER(1,4,0)
+#define BOOST_PREDEF_VERSION BOOST_VERSION_NUMBER(1,4,1)
#endif
diff --git a/boost/preprocessor/config/config.hpp b/boost/preprocessor/config/config.hpp
index 835b283b7e..8be0e47545 100644
--- a/boost/preprocessor/config/config.hpp
+++ b/boost/preprocessor/config/config.hpp
@@ -73,7 +73,7 @@
# define BOOST_PP_VARIADICS_MSVC 0
# if !defined BOOST_PP_VARIADICS
# /* variadic support explicitly disabled for all untested compilers */
-# if defined __GCCXML__ || defined __CUDACC__ || defined __PATHSCALE__ || defined __DMC__ || defined __CODEGEARC__ || defined __BORLANDC__ || defined __MWERKS__ || ( defined __SUNPRO_CC && __SUNPRO_CC < 0x5130 ) || defined __HP_aCC && !defined __EDG__ || defined __MRC__ || defined __SC__ || defined __IBMCPP__ || defined __PGI
+# if defined __GCCXML__ || defined __CUDACC__ || defined __PATHSCALE__ || defined __DMC__ || defined __CODEGEARC__ || defined __BORLANDC__ || defined __MWERKS__ || ( defined __SUNPRO_CC && __SUNPRO_CC < 0x5120 ) || defined __HP_aCC && !defined __EDG__ || defined __MRC__ || defined __SC__ || defined __IBMCPP__ || defined __PGI
# define BOOST_PP_VARIADICS 0
# /* VC++ (C/C++) */
# elif defined _MSC_VER && _MSC_VER >= 1400 && (!defined __EDG__ || defined(__INTELLISENSE__)) && !defined __clang__
diff --git a/boost/property_tree/detail/info_parser_read.hpp b/boost/property_tree/detail/info_parser_read.hpp
index 99eb4aa585..87ef2cd489 100644
--- a/boost/property_tree/detail/info_parser_read.hpp
+++ b/boost/property_tree/detail/info_parser_read.hpp
@@ -69,7 +69,7 @@ namespace boost { namespace property_tree { namespace info_parser
unsigned n = c;
if (n > 127)
return false;
- return isspace(c) != 0;
+ return std::isspace(c) != 0;
}
// Advance pointer past whitespace
diff --git a/boost/property_tree/detail/json_parser/parser.hpp b/boost/property_tree/detail/json_parser/parser.hpp
deleted file mode 100644
index c44b99291d..0000000000
--- a/boost/property_tree/detail/json_parser/parser.hpp
+++ /dev/null
@@ -1,524 +0,0 @@
-#ifndef BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_PARSER_HPP
-#define BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_PARSER_HPP
-
-#include <boost/property_tree/detail/json_parser_error.hpp>
-
-#include <boost/bind.hpp>
-#include <boost/format.hpp>
-
-#include <iterator>
-#include <sstream>
-#include <string>
-
-namespace boost { namespace property_tree {
- namespace json_parser { namespace detail
-{
-
- template <typename Encoding, typename Iterator, typename Sentinel>
- class source
- {
- public:
- typedef typename std::iterator_traits<Iterator>::value_type
- code_unit;
- typedef bool (Encoding::*encoding_predicate)(code_unit c) const;
-
- explicit source(Encoding& encoding) : encoding(encoding) {}
-
- template <typename Range>
- void set_input(const std::string& filename, const Range& r)
- {
- this->filename = filename;
- cur = r.begin();
- end = r.end();
- line = 1;
- offset = 0;
- }
-
- bool done() const { return cur == end; }
-
- void parse_error(const char* msg) {
- BOOST_PROPERTY_TREE_THROW(
- json_parser_error(msg, filename, line));
- }
-
- void next() {
- if (encoding.is_nl(*cur)) {
- ++line;
- offset = 0;
- } else {
- ++offset;
- }
- ++cur;
- }
-
- template <typename Action>
- bool have(encoding_predicate p, Action& a) {
- bool found = cur != end && (encoding.*p)(*cur);
- if (found) {
- a(*cur);
- next();
- }
- return found;
- }
-
- bool have(encoding_predicate p) {
- DoNothing n;
- return have(p, n);
- }
-
- template <typename Action>
- void expect(encoding_predicate p, const char* msg, Action& a) {
- if (!have(p, a)) {
- parse_error(msg);
- }
- }
-
- void expect(encoding_predicate p, const char* msg) {
- DoNothing n;
- expect(p, msg, n);
- }
-
- code_unit need_cur(const char* msg) {
- if (cur == end) {
- parse_error(msg);
- }
- return *cur;
- }
-
- Iterator& raw_cur() { return cur; }
- Sentinel raw_end() { return end; }
-
- private:
- struct DoNothing {
- void operator ()(code_unit) const {}
- };
-
- Encoding& encoding;
- Iterator cur;
- Sentinel end;
- std::string filename;
- int line;
- int offset;
- };
-
- template <typename Callbacks, typename Encoding, typename Iterator,
- typename = typename std::iterator_traits<Iterator>
- ::iterator_category>
- class number_callback_adapter
- {
- public:
- number_callback_adapter(Callbacks& callbacks, Encoding& encoding,
- Iterator& cur)
- : callbacks(callbacks), encoding(encoding), first(cur), cur(cur)
- {}
-
- void operator ()(typename Encoding::external_char) {}
-
- void finish() const {
- callbacks.on_number(encoding.to_internal(first, cur));
- }
-
- private:
- number_callback_adapter(const number_callback_adapter&);
-
- Callbacks& callbacks;
- Encoding& encoding;
- Iterator first;
- Iterator& cur;
- };
-
- template <typename Callbacks, typename Encoding, typename Iterator>
- class number_callback_adapter<Callbacks, Encoding, Iterator,
- std::input_iterator_tag>
- {
- public:
- number_callback_adapter(Callbacks& callbacks, Encoding& encoding,
- Iterator&)
- : callbacks(callbacks), encoding(encoding), first(true)
- {}
-
- void operator ()(typename Encoding::external_char c) {
- if (first) {
- callbacks.on_begin_number();
- first = false;
- }
- callbacks.on_digit(encoding.to_internal_trivial(c));
- }
-
- void finish() const {
- callbacks.on_end_number();
- }
- private:
- number_callback_adapter(const number_callback_adapter&);
-
- Callbacks& callbacks;
- Encoding& encoding;
- bool first;
- };
-
- template <typename Callbacks, typename Encoding, typename Iterator,
- typename = typename std::iterator_traits<Iterator>
- ::iterator_category>
- class string_callback_adapter
- {
- public:
- string_callback_adapter(Callbacks& callbacks, Encoding& encoding,
- Iterator& cur)
- : callbacks(callbacks), encoding(encoding), cur(cur),
- run_begin(cur)
- {}
-
- void start_run() {
- run_begin = cur;
- }
-
- void finish_run() {
- callbacks.on_code_units(encoding.to_internal(run_begin, cur));
- }
-
- template <typename Sentinel, typename EncodingErrorFn>
- void process_codepoint(Sentinel end, EncodingErrorFn error_fn) {
- encoding.skip_codepoint(cur, end, error_fn);
- }
-
- private:
- string_callback_adapter(const string_callback_adapter&);
-
- Callbacks& callbacks;
- Encoding& encoding;
- Iterator& cur;
- Iterator run_begin;
- };
-
- template <typename Callbacks, typename Encoding, typename Iterator>
- class string_callback_adapter<Callbacks, Encoding, Iterator,
- std::input_iterator_tag>
- {
- public:
- string_callback_adapter(Callbacks& callbacks, Encoding& encoding,
- Iterator& cur)
- : callbacks(callbacks), encoding(encoding), cur(cur)
- {}
-
- void start_run() {}
-
- void finish_run() {}
-
- template <typename Sentinel, typename EncodingErrorFn>
- void process_codepoint(Sentinel end, EncodingErrorFn error_fn) {
- encoding.transcode_codepoint(cur, end,
- boost::bind(&Callbacks::on_code_unit,
- boost::ref(callbacks), _1),
- error_fn);
- }
-
- private:
- string_callback_adapter(const string_callback_adapter&);
-
- Callbacks& callbacks;
- Encoding& encoding;
- Iterator& cur;
- };
-
- template <typename Callbacks, typename Encoding, typename Iterator,
- typename Sentinel>
- class parser
- {
- typedef detail::number_callback_adapter<Callbacks, Encoding, Iterator>
- number_adapter;
- typedef detail::string_callback_adapter<Callbacks, Encoding, Iterator>
- string_adapter;
- typedef detail::source<Encoding, Iterator, Sentinel> source;
- typedef typename source::code_unit code_unit;
-
- public:
- parser(Callbacks& callbacks, Encoding& encoding)
- : callbacks(callbacks), encoding(encoding), src(encoding)
- {}
-
- template <typename Range>
- void set_input(const std::string& filename, const Range& r) {
- src.set_input(filename, r);
- }
-
- void finish() {
- skip_ws();
- if (!src.done()) {
- parse_error("garbage after data");
- }
- }
-
- void parse_value() {
- if (parse_object()) return;
- if (parse_array()) return;
- if (parse_string()) return;
- if (parse_boolean()) return;
- if (parse_null()) return;
- if (parse_number()) return;
- parse_error("expected value");
- }
-
- bool parse_null() {
- skip_ws();
- if (!have(&Encoding::is_n)) {
- return false;
- }
- expect(&Encoding::is_u, "expected 'null'");
- expect(&Encoding::is_l, "expected 'null'");
- expect(&Encoding::is_l, "expected 'null'");
- callbacks.on_null();
- return true;
- }
-
- bool parse_boolean() {
- skip_ws();
- if (have(&Encoding::is_t)) {
- expect(&Encoding::is_r, "expected 'true'");
- expect(&Encoding::is_u, "expected 'true'");
- expect(&Encoding::is_e, "expected 'true'");
- callbacks.on_boolean(true);
- return true;
- }
- if (have(&Encoding::is_f)) {
- expect(&Encoding::is_a, "expected 'false'");
- expect(&Encoding::is_l, "expected 'false'");
- expect(&Encoding::is_s, "expected 'false'");
- expect(&Encoding::is_e, "expected 'false'");
- callbacks.on_boolean(false);
- return true;
- }
- return false;
- }
-
- bool parse_number() {
- skip_ws();
-
- number_adapter adapter(callbacks, encoding, src.raw_cur());
- bool started = false;
- if (have(&Encoding::is_minus, adapter)) {
- started = true;
- }
- if (!have(&Encoding::is_0, adapter) && !parse_int_part(adapter)) {
- if (started) {
- parse_error("expected digits after -");
- }
- return false;
- }
- parse_frac_part(adapter);
- parse_exp_part(adapter);
- adapter.finish();
- return true;
- }
-
- bool parse_string() {
- skip_ws();
-
- if (!have(&Encoding::is_quote)) {
- return false;
- }
-
- callbacks.on_begin_string();
- string_adapter adapter(callbacks, encoding, src.raw_cur());
- while (!encoding.is_quote(need_cur("unterminated string"))) {
- if (encoding.is_backslash(*src.raw_cur())) {
- adapter.finish_run();
- next();
- parse_escape();
- adapter.start_run();
- } else {
- adapter.process_codepoint(src.raw_end(),
- boost::bind(&parser::parse_error,
- this, "invalid code sequence"));
- }
- }
- adapter.finish_run();
- callbacks.on_end_string();
- next();
- return true;
- }
-
- bool parse_array() {
- skip_ws();
-
- if (!have(&Encoding::is_open_bracket)) {
- return false;
- }
-
- callbacks.on_begin_array();
- skip_ws();
- if (have(&Encoding::is_close_bracket)) {
- callbacks.on_end_array();
- return true;
- }
- do {
- parse_value();
- skip_ws();
- } while (have(&Encoding::is_comma));
- expect(&Encoding::is_close_bracket, "expected ']' or ','");
- callbacks.on_end_array();
- return true;
- }
-
- bool parse_object() {
- skip_ws();
-
- if (!have(&Encoding::is_open_brace)) {
- return false;
- }
-
- callbacks.on_begin_object();
- skip_ws();
- if (have(&Encoding::is_close_brace)) {
- callbacks.on_end_object();
- return true;
- }
- do {
- if (!parse_string()) {
- parse_error("expected key string");
- }
- skip_ws();
- expect(&Encoding::is_colon, "expected ':'");
- parse_value();
- skip_ws();
- } while (have(&Encoding::is_comma));
- expect(&Encoding::is_close_brace, "expected '}' or ','");
- callbacks.on_end_object();
- return true;
- }
-
- private:
- typedef typename source::encoding_predicate encoding_predicate;
-
- void parse_error(const char* msg) { src.parse_error(msg); }
- void next() { src.next(); }
- template <typename Action>
- bool have(encoding_predicate p, Action& a) { return src.have(p, a); }
- bool have(encoding_predicate p) { return src.have(p); }
- template <typename Action>
- void expect(encoding_predicate p, const char* msg, Action& a) {
- src.expect(p, msg, a);
- }
- void expect(encoding_predicate p, const char* msg) {
- src.expect(p, msg);
- }
- code_unit need_cur(const char* msg) { return src.need_cur(msg); }
-
- void skip_ws() {
- while (have(&Encoding::is_ws)) {
- }
- }
-
- bool parse_int_part(number_adapter& action) {
- if (!have(&Encoding::is_digit0, action)) {
- return false;
- }
- parse_digits(action);
- return true;
- }
-
- void parse_frac_part(number_adapter& action) {
- if (!have(&Encoding::is_dot, action)) {
- return;
- }
- expect(&Encoding::is_digit, "need at least one digit after '.'",
- action);
- parse_digits(action);
- }
-
- void parse_exp_part(number_adapter& action) {
- if (!have(&Encoding::is_eE, action)) {
- return;
- }
- have(&Encoding::is_plusminus, action);
- expect(&Encoding::is_digit, "need at least one digit in exponent",
- action);
- parse_digits(action);
- }
-
- void parse_digits(number_adapter& action) {
- while (have(&Encoding::is_digit, action)) {
- }
- }
-
- void parse_escape() {
- if (have(&Encoding::is_quote)) {
- feed(0x22);
- } else if (have(&Encoding::is_backslash)) {
- feed(0x5c);
- } else if (have(&Encoding::is_slash)) {
- feed(0x2f);
- } else if (have(&Encoding::is_b)) {
- feed(0x08); // backspace
- } else if (have(&Encoding::is_f)) {
- feed(0x0c); // formfeed
- } else if (have(&Encoding::is_n)) {
- feed(0x0a); // line feed
- } else if (have(&Encoding::is_r)) {
- feed(0x0d); // carriage return
- } else if (have(&Encoding::is_t)) {
- feed(0x09); // horizontal tab
- } else if (have(&Encoding::is_u)) {
- parse_codepoint_ref();
- } else {
- parse_error("invalid escape sequence");
- }
- }
-
- unsigned parse_hex_quad() {
- unsigned codepoint = 0;
- for (int i = 0; i < 4; ++i) {
- int value = encoding.decode_hexdigit(
- need_cur("invalid escape sequence"));
- if (value < 0) {
- parse_error("invalid escape sequence");
- }
- codepoint *= 16;
- codepoint += value;
- next();
- }
- return codepoint;
- }
-
- static bool is_surrogate_high(unsigned codepoint) {
- return (codepoint & 0xfc00) == 0xd800;
- }
- static bool is_surrogate_low(unsigned codepoint) {
- return (codepoint & 0xfc00) == 0xdc00;
- }
- static unsigned combine_surrogates(unsigned high, unsigned low) {
- return 0x010000 + (((high & 0x3ff) << 10) | (low & 0x3ff));
- }
-
- void parse_codepoint_ref() {
- unsigned codepoint = parse_hex_quad();
- if (is_surrogate_low(codepoint)) {
- parse_error("invalid codepoint, stray low surrogate");
- }
- if (is_surrogate_high(codepoint)) {
- expect(&Encoding::is_backslash,
- "invalid codepoint, stray high surrogate");
- expect(&Encoding::is_u,
- "expected codepoint reference after high surrogate");
- int low = parse_hex_quad();
- if (!is_surrogate_low(low)) {
- parse_error("expected low surrogate after high surrogate");
- }
- codepoint = combine_surrogates(codepoint, low);
- }
- feed(codepoint);
- }
-
- void feed(unsigned codepoint) {
- encoding.feed_codepoint(codepoint,
- boost::bind(&Callbacks::on_code_unit,
- boost::ref(callbacks), _1));
- }
-
- Callbacks& callbacks;
- Encoding& encoding;
- source src;
- };
-
-}}}}
-
-#endif
diff --git a/boost/property_tree/detail/json_parser/read.hpp b/boost/property_tree/detail/json_parser/read.hpp
deleted file mode 100644
index 61c0162781..0000000000
--- a/boost/property_tree/detail/json_parser/read.hpp
+++ /dev/null
@@ -1,55 +0,0 @@
-// ----------------------------------------------------------------------------
-// Copyright (C) 2015 Sebastian Redl
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-//
-// For more information, see www.boost.org
-// ----------------------------------------------------------------------------
-#ifndef BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_READ_HPP
-#define BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_READ_HPP
-
-#include <boost/property_tree/detail/json_parser/parser.hpp>
-#include <boost/property_tree/detail/json_parser/narrow_encoding.hpp>
-#include <boost/property_tree/detail/json_parser/wide_encoding.hpp>
-#include <boost/property_tree/detail/json_parser/standard_callbacks.hpp>
-
-#include <boost/range/iterator_range_core.hpp>
-
-#include <istream>
-#include <iterator>
-#include <string>
-
-namespace boost { namespace property_tree {
- namespace json_parser { namespace detail
-{
-
- template <typename Ch> struct encoding;
- template <> struct encoding<char> : utf8_utf8_encoding {};
- template <> struct encoding<wchar_t> : wide_wide_encoding {};
-
- template <typename Ptree>
- void read_json_internal(
- std::basic_istream<typename Ptree::key_type::value_type> &stream,
- Ptree &pt, const std::string &filename)
- {
- typedef typename Ptree::key_type::value_type char_type;
- typedef standard_callbacks<Ptree> callbacks_type;
- typedef detail::encoding<char_type> encoding_type;
- typedef std::istreambuf_iterator<char_type> iterator;
- callbacks_type callbacks;
- encoding_type encoding;
- detail::parser<callbacks_type, encoding_type, iterator, iterator>
- parser(callbacks, encoding);
- parser.set_input(filename,
- boost::make_iterator_range(iterator(stream), iterator()));
- parser.parse_value();
- parser.finish();
-
- pt.swap(callbacks.output());
- }
-
-}}}}
-
-#endif
diff --git a/boost/property_tree/detail/ptree_utils.hpp b/boost/property_tree/detail/ptree_utils.hpp
index 72aed4614c..c353e08ba8 100644
--- a/boost/property_tree/detail/ptree_utils.hpp
+++ b/boost/property_tree/detail/ptree_utils.hpp
@@ -57,7 +57,7 @@ namespace boost { namespace property_tree { namespace detail
template<typename Str>
Str widen(const char *text)
{
- Str result;
+ Str result;
while (*text)
{
result += typename Str::value_type(*text);
@@ -70,7 +70,7 @@ namespace boost { namespace property_tree { namespace detail
template<typename Str, typename char_type>
Str narrow(const char_type *text)
{
- Str result;
+ Str result;
while (*text)
{
if (*text < 0 || *text > (std::numeric_limits<char>::max)())
diff --git a/boost/property_tree/detail/xml_parser_utils.hpp b/boost/property_tree/detail/xml_parser_utils.hpp
index b4c502b5eb..fbbde0153e 100644
--- a/boost/property_tree/detail/xml_parser_utils.hpp
+++ b/boost/property_tree/detail/xml_parser_utils.hpp
@@ -23,8 +23,8 @@ namespace boost { namespace property_tree { namespace xml_parser
template<class Str>
Str condense(const Str &s)
{
- typedef typename Str::value_type Ch;
- Str r;
+ typedef typename Str::value_type Ch;
+ Str r;
std::locale loc;
bool space = false;
typename Str::const_iterator end = s.end();
@@ -70,19 +70,17 @@ namespace boost { namespace property_tree { namespace xml_parser
case Ch('&'): r += detail::widen<Str>("&amp;"); break;
case Ch('"'): r += detail::widen<Str>("&quot;"); break;
case Ch('\''): r += detail::widen<Str>("&apos;"); break;
- case Ch('\t'): r += detail::widen<Str>("&#9;"); break;
- case Ch('\n'): r += detail::widen<Str>("&#10;"); break;
default: r += *it; break;
}
}
}
return r;
}
-
+
template<class Str>
Str decode_char_entities(const Str &s)
{
- typedef typename Str::value_type Ch;
+ typedef typename Str::value_type Ch;
Str r;
typename Str::const_iterator end = s.end();
for (typename Str::const_iterator it = s.begin(); it != end; ++it)
@@ -107,7 +105,7 @@ namespace boost { namespace property_tree { namespace xml_parser
}
return r;
}
-
+
template<class Str>
const Str &xmldecl()
{
diff --git a/boost/property_tree/detail/xml_parser_write.hpp b/boost/property_tree/detail/xml_parser_write.hpp
index 45af878488..0af2265fa4 100644
--- a/boost/property_tree/detail/xml_parser_write.hpp
+++ b/boost/property_tree/detail/xml_parser_write.hpp
@@ -36,7 +36,7 @@ namespace boost { namespace property_tree { namespace xml_parser
const xml_writer_settings<Str> & settings
)
{
- typedef typename Str::value_type Ch;
+ typedef typename Str::value_type Ch;
if (separate_line)
write_xml_indent(stream,indent,settings);
stream << Ch('<') << Ch('!') << Ch('-') << Ch('-');
@@ -45,7 +45,7 @@ namespace boost { namespace property_tree { namespace xml_parser
if (separate_line)
stream << Ch('\n');
}
-
+
template<class Str>
void write_xml_text(std::basic_ostream<typename Str::value_type> &stream,
const Str &s,
@@ -54,8 +54,8 @@ namespace boost { namespace property_tree { namespace xml_parser
const xml_writer_settings<Str> & settings
)
{
- typedef typename Str::value_type Ch;
- if (separate_line)
+ typedef typename Str::value_type Ch;
+ if (separate_line)
write_xml_indent(stream,indent,settings);
stream << encode_char_entities(s);
if (separate_line)
@@ -63,9 +63,9 @@ namespace boost { namespace property_tree { namespace xml_parser
}
template<class Ptree>
- void write_xml_element(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
+ void write_xml_element(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
const typename Ptree::key_type &key,
- const Ptree &pt,
+ const Ptree &pt,
int indent,
const xml_writer_settings<typename Ptree::key_type> & settings)
{
@@ -89,7 +89,7 @@ namespace boost { namespace property_tree { namespace xml_parser
}
}
}
-
+
// Write element
if (pt.data().empty() && pt.empty()) // Empty key
{
@@ -104,11 +104,9 @@ namespace boost { namespace property_tree { namespace xml_parser
}
else // Nonempty key
{
-
// Write opening tag, attributes and data
if (indent >= 0)
{
-
// Write opening brace and key
write_xml_indent(stream,indent,settings);
stream << Ch('<') << key;
@@ -163,7 +161,7 @@ namespace boost { namespace property_tree { namespace xml_parser
write_xml_element(stream, it->first, it->second,
indent + 1, settings);
}
-
+
// Write closing tag
if (indent >= 0 && !has_attrs_only)
{
diff --git a/boost/property_tree/detail/xml_parser_writer_settings.hpp b/boost/property_tree/detail/xml_parser_writer_settings.hpp
index 9b14a5d723..5fb79f3e6f 100644
--- a/boost/property_tree/detail/xml_parser_writer_settings.hpp
+++ b/boost/property_tree/detail/xml_parser_writer_settings.hpp
@@ -16,12 +16,12 @@
namespace boost { namespace property_tree { namespace xml_parser
{
-
+
// Naively convert narrow string to another character type
template<class Str>
Str widen(const char *text)
{
- typedef typename Str::value_type Ch;
+ typedef typename Str::value_type Ch;
Str result;
while (*text)
{
@@ -35,7 +35,7 @@ namespace boost { namespace property_tree { namespace xml_parser
template<class Str>
class xml_writer_settings
{
- typedef typename Str::value_type Ch;
+ typedef typename Str::value_type Ch;
public:
xml_writer_settings(Ch inchar = Ch(' '),
typename Str::size_type incount = 0,
diff --git a/boost/property_tree/json_parser.hpp b/boost/property_tree/json_parser.hpp
index d8a3e1025f..62fd89f855 100644
--- a/boost/property_tree/json_parser.hpp
+++ b/boost/property_tree/json_parser.hpp
@@ -12,9 +12,9 @@
#define BOOST_PROPERTY_TREE_JSON_PARSER_HPP_INCLUDED
#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/detail/json_parser_error.hpp>
-#include <boost/property_tree/detail/json_parser/read.hpp>
-#include <boost/property_tree/detail/json_parser_write.hpp>
+#include <boost/property_tree/json_parser/error.hpp>
+#include <boost/property_tree/json_parser/detail/read.hpp>
+#include <boost/property_tree/json_parser/detail/write.hpp>
#include <fstream>
#include <string>
diff --git a/boost/property_tree/detail/json_parser/narrow_encoding.hpp b/boost/property_tree/json_parser/detail/narrow_encoding.hpp
index 13218743d1..4e25e686ac 100644
--- a/boost/property_tree/detail/json_parser/narrow_encoding.hpp
+++ b/boost/property_tree/json_parser/detail/narrow_encoding.hpp
@@ -1,9 +1,9 @@
#ifndef BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_NARROW_ENCODING_HPP
#define BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_NARROW_ENCODING_HPP
+#include <boost/assert.hpp>
#include <boost/range/iterator_range_core.hpp>
-#include <cassert>
#include <utility>
namespace boost { namespace property_tree {
@@ -68,7 +68,7 @@ namespace boost { namespace property_tree {
}
char to_internal_trivial(char c) const {
- assert(c <= 0x7f);
+ BOOST_ASSERT(static_cast<unsigned char>(c) <= 0x7f);
return c;
}
@@ -128,6 +128,15 @@ namespace boost { namespace property_tree {
}
}
+ template <typename Iterator, typename Sentinel>
+ void skip_introduction(Iterator& cur, Sentinel end) const {
+ if (cur != end && static_cast<unsigned char>(*cur) == 0xef) {
+ if (++cur == end) return;
+ if (++cur == end) return;
+ if (++cur == end) return;
+ }
+ }
+
private:
struct DoNothing {
void operator ()(char) const {}
diff --git a/boost/property_tree/json_parser/detail/parser.hpp b/boost/property_tree/json_parser/detail/parser.hpp
new file mode 100644
index 0000000000..5554990fb2
--- /dev/null
+++ b/boost/property_tree/json_parser/detail/parser.hpp
@@ -0,0 +1,530 @@
+#ifndef BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_PARSER_HPP
+#define BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_PARSER_HPP
+
+#include <boost/property_tree/json_parser/error.hpp>
+
+#include <boost/ref.hpp>
+#include <boost/bind.hpp>
+#include <boost/format.hpp>
+
+#include <iterator>
+#include <sstream>
+#include <string>
+
+namespace boost { namespace property_tree {
+ namespace json_parser { namespace detail
+{
+
+ template <typename Encoding, typename Iterator, typename Sentinel>
+ class source
+ {
+ public:
+ typedef typename std::iterator_traits<Iterator>::value_type
+ code_unit;
+ typedef bool (Encoding::*encoding_predicate)(code_unit c) const;
+
+ explicit source(Encoding& encoding) : encoding(encoding) {}
+
+ template <typename Range>
+ void set_input(const std::string& filename, const Range& r)
+ {
+ this->filename = filename;
+ cur = r.begin();
+ end = r.end();
+ // Note that there is no backtracking, so if e.g. a UTF-8 file
+ // starts with something that initially looks like a BOM but isn't,
+ // there's trouble.
+ // However, no valid JSON file can start with a UTF-8 EF byte.
+ encoding.skip_introduction(cur, end);
+ line = 1;
+ offset = 0;
+ }
+
+ bool done() const { return cur == end; }
+
+ void parse_error(const char* msg) {
+ BOOST_PROPERTY_TREE_THROW(
+ json_parser_error(msg, filename, line));
+ }
+
+ void next() {
+ if (encoding.is_nl(*cur)) {
+ ++line;
+ offset = 0;
+ } else {
+ ++offset;
+ }
+ ++cur;
+ }
+
+ template <typename Action>
+ bool have(encoding_predicate p, Action& a) {
+ bool found = cur != end && (encoding.*p)(*cur);
+ if (found) {
+ a(*cur);
+ next();
+ }
+ return found;
+ }
+
+ bool have(encoding_predicate p) {
+ DoNothing n;
+ return have(p, n);
+ }
+
+ template <typename Action>
+ void expect(encoding_predicate p, const char* msg, Action& a) {
+ if (!have(p, a)) {
+ parse_error(msg);
+ }
+ }
+
+ void expect(encoding_predicate p, const char* msg) {
+ DoNothing n;
+ expect(p, msg, n);
+ }
+
+ code_unit need_cur(const char* msg) {
+ if (cur == end) {
+ parse_error(msg);
+ }
+ return *cur;
+ }
+
+ Iterator& raw_cur() { return cur; }
+ Sentinel raw_end() { return end; }
+
+ private:
+ struct DoNothing {
+ void operator ()(code_unit) const {}
+ };
+
+ Encoding& encoding;
+ Iterator cur;
+ Sentinel end;
+ std::string filename;
+ int line;
+ int offset;
+ };
+
+ template <typename Callbacks, typename Encoding, typename Iterator,
+ typename = typename std::iterator_traits<Iterator>
+ ::iterator_category>
+ class number_callback_adapter
+ {
+ public:
+ number_callback_adapter(Callbacks& callbacks, Encoding& encoding,
+ Iterator& cur)
+ : callbacks(callbacks), encoding(encoding), first(cur), cur(cur)
+ {}
+
+ void operator ()(typename Encoding::external_char) {}
+
+ void finish() const {
+ callbacks.on_number(encoding.to_internal(first, cur));
+ }
+
+ private:
+ number_callback_adapter(const number_callback_adapter&);
+
+ Callbacks& callbacks;
+ Encoding& encoding;
+ Iterator first;
+ Iterator& cur;
+ };
+
+ template <typename Callbacks, typename Encoding, typename Iterator>
+ class number_callback_adapter<Callbacks, Encoding, Iterator,
+ std::input_iterator_tag>
+ {
+ public:
+ number_callback_adapter(Callbacks& callbacks, Encoding& encoding,
+ Iterator&)
+ : callbacks(callbacks), encoding(encoding), first(true)
+ {}
+
+ void operator ()(typename Encoding::external_char c) {
+ if (first) {
+ callbacks.on_begin_number();
+ first = false;
+ }
+ callbacks.on_digit(encoding.to_internal_trivial(c));
+ }
+
+ void finish() const {
+ callbacks.on_end_number();
+ }
+ private:
+ number_callback_adapter(const number_callback_adapter&);
+
+ Callbacks& callbacks;
+ Encoding& encoding;
+ bool first;
+ };
+
+ template <typename Callbacks, typename Encoding, typename Iterator,
+ typename = typename std::iterator_traits<Iterator>
+ ::iterator_category>
+ class string_callback_adapter
+ {
+ public:
+ string_callback_adapter(Callbacks& callbacks, Encoding& encoding,
+ Iterator& cur)
+ : callbacks(callbacks), encoding(encoding), cur(cur),
+ run_begin(cur)
+ {}
+
+ void start_run() {
+ run_begin = cur;
+ }
+
+ void finish_run() {
+ callbacks.on_code_units(encoding.to_internal(run_begin, cur));
+ }
+
+ template <typename Sentinel, typename EncodingErrorFn>
+ void process_codepoint(Sentinel end, EncodingErrorFn error_fn) {
+ encoding.skip_codepoint(cur, end, error_fn);
+ }
+
+ private:
+ string_callback_adapter(const string_callback_adapter&);
+
+ Callbacks& callbacks;
+ Encoding& encoding;
+ Iterator& cur;
+ Iterator run_begin;
+ };
+
+ template <typename Callbacks, typename Encoding, typename Iterator>
+ class string_callback_adapter<Callbacks, Encoding, Iterator,
+ std::input_iterator_tag>
+ {
+ public:
+ string_callback_adapter(Callbacks& callbacks, Encoding& encoding,
+ Iterator& cur)
+ : callbacks(callbacks), encoding(encoding), cur(cur)
+ {}
+
+ void start_run() {}
+
+ void finish_run() {}
+
+ template <typename Sentinel, typename EncodingErrorFn>
+ void process_codepoint(Sentinel end, EncodingErrorFn error_fn) {
+ encoding.transcode_codepoint(cur, end,
+ boost::bind(&Callbacks::on_code_unit,
+ boost::ref(callbacks), _1),
+ error_fn);
+ }
+
+ private:
+ string_callback_adapter(const string_callback_adapter&);
+
+ Callbacks& callbacks;
+ Encoding& encoding;
+ Iterator& cur;
+ };
+
+ template <typename Callbacks, typename Encoding, typename Iterator,
+ typename Sentinel>
+ class parser
+ {
+ typedef detail::number_callback_adapter<Callbacks, Encoding, Iterator>
+ number_adapter;
+ typedef detail::string_callback_adapter<Callbacks, Encoding, Iterator>
+ string_adapter;
+ typedef detail::source<Encoding, Iterator, Sentinel> source;
+ typedef typename source::code_unit code_unit;
+
+ public:
+ parser(Callbacks& callbacks, Encoding& encoding)
+ : callbacks(callbacks), encoding(encoding), src(encoding)
+ {}
+
+ template <typename Range>
+ void set_input(const std::string& filename, const Range& r) {
+ src.set_input(filename, r);
+ }
+
+ void finish() {
+ skip_ws();
+ if (!src.done()) {
+ parse_error("garbage after data");
+ }
+ }
+
+ void parse_value() {
+ if (parse_object()) return;
+ if (parse_array()) return;
+ if (parse_string()) return;
+ if (parse_boolean()) return;
+ if (parse_null()) return;
+ if (parse_number()) return;
+ parse_error("expected value");
+ }
+
+ bool parse_null() {
+ skip_ws();
+ if (!have(&Encoding::is_n)) {
+ return false;
+ }
+ expect(&Encoding::is_u, "expected 'null'");
+ expect(&Encoding::is_l, "expected 'null'");
+ expect(&Encoding::is_l, "expected 'null'");
+ callbacks.on_null();
+ return true;
+ }
+
+ bool parse_boolean() {
+ skip_ws();
+ if (have(&Encoding::is_t)) {
+ expect(&Encoding::is_r, "expected 'true'");
+ expect(&Encoding::is_u, "expected 'true'");
+ expect(&Encoding::is_e, "expected 'true'");
+ callbacks.on_boolean(true);
+ return true;
+ }
+ if (have(&Encoding::is_f)) {
+ expect(&Encoding::is_a, "expected 'false'");
+ expect(&Encoding::is_l, "expected 'false'");
+ expect(&Encoding::is_s, "expected 'false'");
+ expect(&Encoding::is_e, "expected 'false'");
+ callbacks.on_boolean(false);
+ return true;
+ }
+ return false;
+ }
+
+ bool parse_number() {
+ skip_ws();
+
+ number_adapter adapter(callbacks, encoding, src.raw_cur());
+ bool started = false;
+ if (have(&Encoding::is_minus, adapter)) {
+ started = true;
+ }
+ if (!have(&Encoding::is_0, adapter) && !parse_int_part(adapter)) {
+ if (started) {
+ parse_error("expected digits after -");
+ }
+ return false;
+ }
+ parse_frac_part(adapter);
+ parse_exp_part(adapter);
+ adapter.finish();
+ return true;
+ }
+
+ bool parse_string() {
+ skip_ws();
+
+ if (!have(&Encoding::is_quote)) {
+ return false;
+ }
+
+ callbacks.on_begin_string();
+ string_adapter adapter(callbacks, encoding, src.raw_cur());
+ while (!encoding.is_quote(need_cur("unterminated string"))) {
+ if (encoding.is_backslash(*src.raw_cur())) {
+ adapter.finish_run();
+ next();
+ parse_escape();
+ adapter.start_run();
+ } else {
+ adapter.process_codepoint(src.raw_end(),
+ boost::bind(&parser::parse_error,
+ this, "invalid code sequence"));
+ }
+ }
+ adapter.finish_run();
+ callbacks.on_end_string();
+ next();
+ return true;
+ }
+
+ bool parse_array() {
+ skip_ws();
+
+ if (!have(&Encoding::is_open_bracket)) {
+ return false;
+ }
+
+ callbacks.on_begin_array();
+ skip_ws();
+ if (have(&Encoding::is_close_bracket)) {
+ callbacks.on_end_array();
+ return true;
+ }
+ do {
+ parse_value();
+ skip_ws();
+ } while (have(&Encoding::is_comma));
+ expect(&Encoding::is_close_bracket, "expected ']' or ','");
+ callbacks.on_end_array();
+ return true;
+ }
+
+ bool parse_object() {
+ skip_ws();
+
+ if (!have(&Encoding::is_open_brace)) {
+ return false;
+ }
+
+ callbacks.on_begin_object();
+ skip_ws();
+ if (have(&Encoding::is_close_brace)) {
+ callbacks.on_end_object();
+ return true;
+ }
+ do {
+ if (!parse_string()) {
+ parse_error("expected key string");
+ }
+ skip_ws();
+ expect(&Encoding::is_colon, "expected ':'");
+ parse_value();
+ skip_ws();
+ } while (have(&Encoding::is_comma));
+ expect(&Encoding::is_close_brace, "expected '}' or ','");
+ callbacks.on_end_object();
+ return true;
+ }
+
+ private:
+ typedef typename source::encoding_predicate encoding_predicate;
+
+ void parse_error(const char* msg) { src.parse_error(msg); }
+ void next() { src.next(); }
+ template <typename Action>
+ bool have(encoding_predicate p, Action& a) { return src.have(p, a); }
+ bool have(encoding_predicate p) { return src.have(p); }
+ template <typename Action>
+ void expect(encoding_predicate p, const char* msg, Action& a) {
+ src.expect(p, msg, a);
+ }
+ void expect(encoding_predicate p, const char* msg) {
+ src.expect(p, msg);
+ }
+ code_unit need_cur(const char* msg) { return src.need_cur(msg); }
+
+ void skip_ws() {
+ while (have(&Encoding::is_ws)) {
+ }
+ }
+
+ bool parse_int_part(number_adapter& action) {
+ if (!have(&Encoding::is_digit0, action)) {
+ return false;
+ }
+ parse_digits(action);
+ return true;
+ }
+
+ void parse_frac_part(number_adapter& action) {
+ if (!have(&Encoding::is_dot, action)) {
+ return;
+ }
+ expect(&Encoding::is_digit, "need at least one digit after '.'",
+ action);
+ parse_digits(action);
+ }
+
+ void parse_exp_part(number_adapter& action) {
+ if (!have(&Encoding::is_eE, action)) {
+ return;
+ }
+ have(&Encoding::is_plusminus, action);
+ expect(&Encoding::is_digit, "need at least one digit in exponent",
+ action);
+ parse_digits(action);
+ }
+
+ void parse_digits(number_adapter& action) {
+ while (have(&Encoding::is_digit, action)) {
+ }
+ }
+
+ void parse_escape() {
+ if (have(&Encoding::is_quote)) {
+ feed(0x22);
+ } else if (have(&Encoding::is_backslash)) {
+ feed(0x5c);
+ } else if (have(&Encoding::is_slash)) {
+ feed(0x2f);
+ } else if (have(&Encoding::is_b)) {
+ feed(0x08); // backspace
+ } else if (have(&Encoding::is_f)) {
+ feed(0x0c); // formfeed
+ } else if (have(&Encoding::is_n)) {
+ feed(0x0a); // line feed
+ } else if (have(&Encoding::is_r)) {
+ feed(0x0d); // carriage return
+ } else if (have(&Encoding::is_t)) {
+ feed(0x09); // horizontal tab
+ } else if (have(&Encoding::is_u)) {
+ parse_codepoint_ref();
+ } else {
+ parse_error("invalid escape sequence");
+ }
+ }
+
+ unsigned parse_hex_quad() {
+ unsigned codepoint = 0;
+ for (int i = 0; i < 4; ++i) {
+ int value = encoding.decode_hexdigit(
+ need_cur("invalid escape sequence"));
+ if (value < 0) {
+ parse_error("invalid escape sequence");
+ }
+ codepoint *= 16;
+ codepoint += value;
+ next();
+ }
+ return codepoint;
+ }
+
+ static bool is_surrogate_high(unsigned codepoint) {
+ return (codepoint & 0xfc00) == 0xd800;
+ }
+ static bool is_surrogate_low(unsigned codepoint) {
+ return (codepoint & 0xfc00) == 0xdc00;
+ }
+ static unsigned combine_surrogates(unsigned high, unsigned low) {
+ return 0x010000 + (((high & 0x3ff) << 10) | (low & 0x3ff));
+ }
+
+ void parse_codepoint_ref() {
+ unsigned codepoint = parse_hex_quad();
+ if (is_surrogate_low(codepoint)) {
+ parse_error("invalid codepoint, stray low surrogate");
+ }
+ if (is_surrogate_high(codepoint)) {
+ expect(&Encoding::is_backslash,
+ "invalid codepoint, stray high surrogate");
+ expect(&Encoding::is_u,
+ "expected codepoint reference after high surrogate");
+ int low = parse_hex_quad();
+ if (!is_surrogate_low(low)) {
+ parse_error("expected low surrogate after high surrogate");
+ }
+ codepoint = combine_surrogates(codepoint, low);
+ }
+ feed(codepoint);
+ }
+
+ void feed(unsigned codepoint) {
+ encoding.feed_codepoint(codepoint,
+ boost::bind(&Callbacks::on_code_unit,
+ boost::ref(callbacks), _1));
+ }
+
+ Callbacks& callbacks;
+ Encoding& encoding;
+ source src;
+ };
+
+}}}}
+
+#endif
diff --git a/boost/property_tree/json_parser/detail/read.hpp b/boost/property_tree/json_parser/detail/read.hpp
new file mode 100644
index 0000000000..d7f0ba6790
--- /dev/null
+++ b/boost/property_tree/json_parser/detail/read.hpp
@@ -0,0 +1,90 @@
+// ----------------------------------------------------------------------------
+// Copyright (C) 2015 Sebastian Redl
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// For more information, see www.boost.org
+// ----------------------------------------------------------------------------
+#ifndef BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_READ_HPP
+#define BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_READ_HPP
+
+#include <boost/property_tree/json_parser/detail/parser.hpp>
+#include <boost/property_tree/json_parser/detail/narrow_encoding.hpp>
+#include <boost/property_tree/json_parser/detail/wide_encoding.hpp>
+#include <boost/property_tree/json_parser/detail/standard_callbacks.hpp>
+
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <istream>
+#include <iterator>
+#include <string>
+
+namespace boost { namespace property_tree {
+ namespace json_parser { namespace detail
+{
+
+ template <typename Iterator, typename Sentinel>
+ class minirange
+ {
+ public:
+ minirange(Iterator first, Sentinel last) : first(first), last(last) {}
+ Iterator begin() const { return first; }
+ Sentinel end() const { return last; }
+
+ private:
+ Iterator first;
+ Sentinel last;
+ };
+ template <typename Iterator, typename Sentinel>
+ minirange<Iterator, Sentinel> make_minirange(Iterator first, Sentinel last)
+ {
+ return minirange<Iterator, Sentinel>(first, last);
+ }
+
+ template <typename Iterator, typename Sentinel,
+ typename Encoding, typename Callbacks>
+ void read_json_internal(Iterator first, Sentinel last, Encoding& encoding,
+ Callbacks& callbacks, const std::string& filename)
+ {
+ BOOST_STATIC_ASSERT_MSG((boost::is_same<
+ typename std::iterator_traits<Iterator>::value_type,
+ typename Encoding::external_char>::value),
+ "Encoding is not capable of using the iterator's value type.");
+ BOOST_STATIC_ASSERT_MSG((boost::is_same<
+ typename Callbacks::char_type,
+ typename Encoding::internal_char>::value),
+ "Encoding is not capable of producing the needed character type.");
+
+ detail::parser<Callbacks, Encoding, Iterator, Sentinel>
+ parser(callbacks, encoding);
+ parser.set_input(filename, make_minirange(first, last));
+ parser.parse_value();
+ parser.finish();
+ }
+
+ template <typename Ch> struct encoding;
+ template <> struct encoding<char> : utf8_utf8_encoding {};
+ template <> struct encoding<wchar_t> : wide_wide_encoding {};
+
+ template <typename Ptree>
+ void read_json_internal(
+ std::basic_istream<typename Ptree::key_type::value_type> &stream,
+ Ptree &pt, const std::string &filename)
+ {
+ typedef typename Ptree::key_type::value_type char_type;
+ typedef standard_callbacks<Ptree> callbacks_type;
+ typedef detail::encoding<char_type> encoding_type;
+ typedef std::istreambuf_iterator<char_type> iterator;
+ callbacks_type callbacks;
+ encoding_type encoding;
+ read_json_internal(iterator(stream), iterator(),
+ encoding, callbacks, filename);
+ pt.swap(callbacks.output());
+ }
+
+}}}}
+
+#endif
diff --git a/boost/property_tree/detail/json_parser/standard_callbacks.hpp b/boost/property_tree/json_parser/detail/standard_callbacks.hpp
index 56c378ec9c..0ece280891 100644
--- a/boost/property_tree/detail/json_parser/standard_callbacks.hpp
+++ b/boost/property_tree/json_parser/detail/standard_callbacks.hpp
@@ -1,6 +1,7 @@
#ifndef BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_STANDARD_CALLBACKS_HPP
#define BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_STANDARD_CALLBACKS_HPP
+#include <boost/assert.hpp>
#include <boost/property_tree/ptree.hpp>
#include <vector>
@@ -116,7 +117,8 @@ namespace boost { namespace property_tree {
return *stack.back().t;
}
case object:
- assert(false); // must start with string, i.e. call new_value
+ default:
+ BOOST_ASSERT(false); // must start with string, i.e. call new_value
case key: {
l.t->push_back(std::make_pair(key_buffer, Ptree()));
l.k = object;
@@ -128,7 +130,6 @@ namespace boost { namespace property_tree {
stack.pop_back();
return new_tree();
}
- assert(false);
}
string& new_value() {
if (stack.empty()) return new_tree().data();
diff --git a/boost/property_tree/detail/json_parser/wide_encoding.hpp b/boost/property_tree/json_parser/detail/wide_encoding.hpp
index 0dec1c03b0..a213ae94c2 100644
--- a/boost/property_tree/detail/json_parser/wide_encoding.hpp
+++ b/boost/property_tree/json_parser/detail/wide_encoding.hpp
@@ -1,9 +1,9 @@
#ifndef BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_WIDE_ENCODING_HPP
#define BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_WIDE_ENCODING_HPP
+#include <boost/assert.hpp>
#include <boost/range/iterator_range_core.hpp>
-#include <cassert>
#include <utility>
namespace boost { namespace property_tree {
@@ -72,7 +72,7 @@ namespace boost { namespace property_tree {
}
wchar_t to_internal_trivial(wchar_t c) const {
- assert(!is_surrogate_high(c) && !is_surrogate_low(c));
+ BOOST_ASSERT(!is_surrogate_high(c) && !is_surrogate_low(c));
return c;
}
@@ -97,6 +97,14 @@ namespace boost { namespace property_tree {
feed_codepoint(codepoint, transcoded_fn, test_utf16());
}
+ template <typename Iterator, typename Sentinel>
+ void skip_introduction(Iterator& cur, Sentinel end) const {
+ // Endianness is already decoded at this level.
+ if (cur != end && *cur == 0xfeff) {
+ ++cur;
+ }
+ }
+
private:
struct DoNothing {
void operator ()(wchar_t) const {}
@@ -104,7 +112,7 @@ namespace boost { namespace property_tree {
template <typename Iterator, typename Sentinel, typename TranscodedFn,
typename EncodingErrorFn>
- void transcode_codepoint(Iterator& cur, Sentinel end,
+ void transcode_codepoint(Iterator& cur, Sentinel,
TranscodedFn transcoded_fn,
EncodingErrorFn error_fn,
is_utf16<false>) const {
@@ -131,6 +139,9 @@ namespace boost { namespace property_tree {
transcoded_fn(c);
++cur;
if (is_surrogate_high(c)) {
+ if (cur == end) {
+ error_fn();
+ }
c = *cur;
if (!is_surrogate_low(c)) {
error_fn();
diff --git a/boost/property_tree/detail/json_parser_write.hpp b/boost/property_tree/json_parser/detail/write.hpp
index 78dbfe4185..bba10038bb 100644
--- a/boost/property_tree/detail/json_parser_write.hpp
+++ b/boost/property_tree/json_parser/detail/write.hpp
@@ -51,10 +51,10 @@ namespace boost { namespace property_tree { namespace json_parser
unsigned long u = (std::min)(static_cast<unsigned long>(
static_cast<UCh>(*b)),
0xFFFFul);
- int d1 = u / 4096; u -= d1 * 4096;
- int d2 = u / 256; u -= d2 * 256;
- int d3 = u / 16; u -= d3 * 16;
- int d4 = u;
+ unsigned long d1 = u / 4096; u -= d1 * 4096;
+ unsigned long d2 = u / 256; u -= d2 * 256;
+ unsigned long d3 = u / 16; u -= d3 * 16;
+ unsigned long d4 = u;
result += Ch('\\'); result += Ch('u');
result += Ch(hexdigits[d1]); result += Ch(hexdigits[d2]);
result += Ch(hexdigits[d3]); result += Ch(hexdigits[d4]);
diff --git a/boost/property_tree/detail/json_parser_error.hpp b/boost/property_tree/json_parser/error.hpp
index d48c72f090..d48c72f090 100644
--- a/boost/property_tree/detail/json_parser_error.hpp
+++ b/boost/property_tree/json_parser/error.hpp
diff --git a/boost/python/converter/registered.hpp b/boost/python/converter/registered.hpp
index 68bb3c4a70..ad9a00b313 100644
--- a/boost/python/converter/registered.hpp
+++ b/boost/python/converter/registered.hpp
@@ -14,6 +14,11 @@
# include <boost/python/type_id.hpp>
# include <boost/type.hpp>
+#if defined(BOOST_PYTHON_TRACE_REGISTRY) \
+ || defined(BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND)
+# include <iostream>
+#endif
+
namespace boost {
// You'll see shared_ptr mentioned in this header because we need to
diff --git a/boost/python/detail/def_helper.hpp b/boost/python/detail/def_helper.hpp
index e68ca0cd7b..92db09ed7b 100644
--- a/boost/python/detail/def_helper.hpp
+++ b/boost/python/detail/def_helper.hpp
@@ -6,7 +6,6 @@
# define DEF_HELPER_DWA200287_HPP
# include <boost/python/args.hpp>
-# include <boost/type_traits/ice.hpp>
# include <boost/type_traits/same_traits.hpp>
# include <boost/python/detail/indirect_traits.hpp>
# include <boost/mpl/not.hpp>
diff --git a/boost/python/detail/wrap_python.hpp b/boost/python/detail/wrap_python.hpp
index eaef7841d5..9fdb222c68 100644
--- a/boost/python/detail/wrap_python.hpp
+++ b/boost/python/detail/wrap_python.hpp
@@ -85,13 +85,22 @@
#if defined(_WIN32) || defined(__CYGWIN__)
# if defined(__GNUC__) && defined(__CYGWIN__)
-# define SIZEOF_LONG 4
+# if defined(__LP64__)
+# define SIZEOF_LONG 8
+# else
+# define SIZEOF_LONG 4
+# endif
+
# if PY_MAJOR_VERSION < 2 || PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 2
typedef int pid_t;
-# define WORD_BIT 32
+# if defined(__LP64__)
+# define WORD_BIT 64
+# else
+# define WORD_BIT 32
+# endif
# define hypot _hypot
# include <stdio.h>
diff --git a/boost/python/object/class_metadata.hpp b/boost/python/object/class_metadata.hpp
index c71cf67c4e..5009c176e8 100644
--- a/boost/python/object/class_metadata.hpp
+++ b/boost/python/object/class_metadata.hpp
@@ -164,7 +164,7 @@ struct class_metadata
>::type held_type;
// Determine if the object will be held by value
- typedef is_convertible<held_type*,T*> use_value_holder;
+ typedef mpl::bool_<is_convertible<held_type*,T*>::value> use_value_holder;
// Compute the "wrapped type", that is, if held_type is a smart
// pointer, we're talking about the pointee.
@@ -175,10 +175,12 @@ struct class_metadata
>::type wrapped;
// Determine whether to use a "back-reference holder"
- typedef mpl::or_<
- has_back_reference<T>
- , is_same<held_type_arg,T>
- , is_base_and_derived<T,wrapped>
+ typedef mpl::bool_<
+ mpl::or_<
+ has_back_reference<T>
+ , is_same<held_type_arg,T>
+ , is_base_and_derived<T,wrapped>
+ >::value
> use_back_reference;
// Select the holder.
diff --git a/boost/random/uniform_on_sphere.hpp b/boost/random/uniform_on_sphere.hpp
index 0f744551a2..72c25ef781 100644
--- a/boost/random/uniform_on_sphere.hpp
+++ b/boost/random/uniform_on_sphere.hpp
@@ -172,6 +172,7 @@ public:
} else {
*_container.begin() = 1;
}
+ break;
}
case 2:
{
diff --git a/boost/range/const_iterator.hpp b/boost/range/const_iterator.hpp
index 3413e59195..727fdad058 100644
--- a/boost/range/const_iterator.hpp
+++ b/boost/range/const_iterator.hpp
@@ -36,7 +36,7 @@ namespace boost
BOOST_RANGE_EXTRACT_OPTIONAL_TYPE( const_iterator )
template< typename C >
-struct range_const_iterator
+struct range_const_iterator_helper
: extract_const_iterator<C>
{};
@@ -45,7 +45,7 @@ struct range_const_iterator
//////////////////////////////////////////////////////////////////////////
template< typename Iterator >
-struct range_const_iterator<std::pair<Iterator,Iterator> >
+struct range_const_iterator_helper<std::pair<Iterator,Iterator> >
{
typedef Iterator type;
};
@@ -55,7 +55,7 @@ struct range_const_iterator<std::pair<Iterator,Iterator> >
//////////////////////////////////////////////////////////////////////////
template< typename T, std::size_t sz >
-struct range_const_iterator< T[sz] >
+struct range_const_iterator_helper< T[sz] >
{
typedef const T* type;
};
@@ -64,7 +64,7 @@ struct range_const_iterator< T[sz] >
template<typename C, typename Enabler=void>
struct range_const_iterator
- : range_detail::range_const_iterator<
+ : range_detail::range_const_iterator_helper<
BOOST_DEDUCED_TYPENAME remove_reference<C>::type
>
{
diff --git a/boost/regex/config.hpp b/boost/regex/config.hpp
index 4fd1fd94a8..9dc48dc8ab 100644
--- a/boost/regex/config.hpp
+++ b/boost/regex/config.hpp
@@ -149,7 +149,7 @@
/* disable our own file-iterators and mapfiles if we can't
* support them: */
#if defined(_WIN32)
-# if defined(BOOST_REGEX_NO_W32) || BOOST_PLAT_WINDOWS_STORE
+# if defined(BOOST_REGEX_NO_W32) || BOOST_PLAT_WINDOWS_RUNTIME
# define BOOST_REGEX_NO_FILEITER
# endif
#else // defined(_WIN32)
diff --git a/boost/regex/v4/basic_regex_parser.hpp b/boost/regex/v4/basic_regex_parser.hpp
index 4a80ab9c32..d097eed959 100644
--- a/boost/regex/v4/basic_regex_parser.hpp
+++ b/boost/regex/v4/basic_regex_parser.hpp
@@ -2650,7 +2650,7 @@ option_group_jump:
//
// allow backrefs to this mark:
//
- if((markid > 0) && (markid < (int)(sizeof(unsigned) * CHAR_BIT)))
+ if(markid < (int)(sizeof(unsigned) * CHAR_BIT))
this->m_backrefs |= 1u << (markid - 1);
}
return true;
diff --git a/boost/regex/v4/fileiter.hpp b/boost/regex/v4/fileiter.hpp
index 4873a0a85e..256a7e4606 100644
--- a/boost/regex/v4/fileiter.hpp
+++ b/boost/regex/v4/fileiter.hpp
@@ -225,11 +225,11 @@ public:
mapfile_iterator() { node = 0; file = 0; offset = 0; }
mapfile_iterator(const mapfile* f, long arg_position)
{
+ BOOST_ASSERT(f);
file = f;
node = f->_first + arg_position / mapfile::buf_size;
offset = arg_position % mapfile::buf_size;
- if(file)
- file->lock(node);
+ file->lock(node);
}
mapfile_iterator(const mapfile_iterator& i)
{
diff --git a/boost/regex/v4/match_flags.hpp b/boost/regex/v4/match_flags.hpp
index e21de6cf6a..1c0046b75f 100644
--- a/boost/regex/v4/match_flags.hpp
+++ b/boost/regex/v4/match_flags.hpp
@@ -22,6 +22,7 @@
#ifdef __cplusplus
# include <boost/cstdint.hpp>
#endif
+#include <boost/detail/workaround.hpp>
#ifdef __cplusplus
namespace boost{
@@ -71,7 +72,7 @@ typedef enum _match_flags
} match_flags;
-#if defined(__BORLANDC__)
+#if defined(__BORLANDC__) || BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
typedef unsigned long match_flag_type;
#else
typedef match_flags match_flag_type;
diff --git a/boost/regex/v4/mem_block_cache.hpp b/boost/regex/v4/mem_block_cache.hpp
index dc54915062..50af421ea2 100644
--- a/boost/regex/v4/mem_block_cache.hpp
+++ b/boost/regex/v4/mem_block_cache.hpp
@@ -27,9 +27,54 @@
# include BOOST_ABI_PREFIX
#endif
+#ifndef BOOST_NO_CXX11_HDR_ATOMIC
+ #include <atomic>
+ #if ATOMIC_POINTER_LOCK_FREE == 2
+ #define BOOST_REGEX_MEM_BLOCK_CACHE_LOCK_FREE
+ #define BOOST_REGEX_ATOMIC_POINTER std::atomic
+ #endif
+#endif
+
namespace boost{
namespace BOOST_REGEX_DETAIL_NS{
+#ifdef BOOST_REGEX_MEM_BLOCK_CACHE_LOCK_FREE /* lock free implementation */
+struct mem_block_cache
+{
+ std::atomic<void*> cache[BOOST_REGEX_MAX_CACHE_BLOCKS];
+
+ ~mem_block_cache()
+ {
+ for (size_t i = 0;i < BOOST_REGEX_MAX_CACHE_BLOCKS; ++i) {
+ if (cache[i].load()) ::operator delete(cache[i].load());
+ }
+ }
+ void* get()
+ {
+ for (size_t i = 0;i < BOOST_REGEX_MAX_CACHE_BLOCKS; ++i) {
+ void* p = cache[i].load();
+ if (p != NULL) {
+ if (cache[i].compare_exchange_strong(p, NULL)) return p;
+ }
+ }
+ return ::operator new(BOOST_REGEX_BLOCKSIZE);
+ }
+ void put(void* ptr)
+ {
+ for (size_t i = 0;i < BOOST_REGEX_MAX_CACHE_BLOCKS; ++i) {
+ void* p = cache[i].load();
+ if (p == NULL) {
+ if (cache[i].compare_exchange_strong(p, ptr)) return;
+ }
+ }
+ ::operator delete(ptr);
+ }
+};
+
+
+#else /* lock-based implementation */
+
+
struct mem_block_node
{
mem_block_node* next;
@@ -85,6 +130,7 @@ struct mem_block_cache
}
}
};
+#endif
extern mem_block_cache block_cache;
diff --git a/boost/serialization/archive_input_unordered_map.hpp b/boost/serialization/archive_input_unordered_map.hpp
index 7ea06e1a68..ef0fd93ebd 100644
--- a/boost/serialization/archive_input_unordered_map.hpp
+++ b/boost/serialization/archive_input_unordered_map.hpp
@@ -37,10 +37,13 @@ struct archive_input_unordered_map
){
typedef typename Container::value_type type;
detail::stack_construct<Archive, type> t(ar, v);
- // borland fails silently w/o full namespace
ar >> boost::serialization::make_nvp("item", t.reference());
std::pair<typename Container::const_iterator, bool> result =
- s.insert(t.reference());
+ #ifdef BOOST_NO_CXX11_HDR_UNORDERED_MAP
+ s.insert(t.reference());
+ #else
+ s.emplace(t.reference());
+ #endif
// note: the following presumes that the map::value_type was NOT tracked
// in the archive. This is the usual case, but here there is no way
// to determine that.
@@ -64,10 +67,13 @@ struct archive_input_unordered_multimap
){
typedef typename Container::value_type type;
detail::stack_construct<Archive, type> t(ar, v);
- // borland fails silently w/o full namespace
ar >> boost::serialization::make_nvp("item", t.reference());
- typename Container::const_iterator result
- = s.insert(t.reference());
+ typename Container::const_iterator result =
+ #ifdef BOOST_NO_CXX11_HDR_UNORDERED_MAP
+ s.insert(t.reference());
+ #else
+ s.emplace(t.reference());
+ #endif
// note: the following presumes that the map::value_type was NOT tracked
// in the archive. This is the usual case, but here there is no way
// to determine that.
diff --git a/boost/serialization/archive_input_unordered_set.hpp b/boost/serialization/archive_input_unordered_set.hpp
index 353507e3a2..961b58f1a8 100644
--- a/boost/serialization/archive_input_unordered_set.hpp
+++ b/boost/serialization/archive_input_unordered_set.hpp
@@ -17,9 +17,7 @@
// See http://www.boost.org for updates, documentation, and revision history.
-#include <boost/config.hpp>
-
-namespace boost {
+namespace boost {
namespace serialization {
namespace stl {
@@ -38,7 +36,11 @@ struct archive_input_unordered_set
// borland fails silently w/o full namespace
ar >> boost::serialization::make_nvp("item", t.reference());
std::pair<typename Container::const_iterator, bool> result =
- s.insert(t.reference());
+ #ifdef BOOST_NO_CXX11_HDR_UNORDERED_SET
+ s.insert(t.reference());
+ #else
+ s.emplace(t.reference());
+ #endif
if(result.second)
ar.reset_object_address(& (* result.first), & t.reference());
}
@@ -55,10 +57,13 @@ struct archive_input_unordered_multiset
){
typedef typename Container::value_type type;
detail::stack_construct<Archive, type> t(ar, v);
- // borland fails silently w/o full namespace
ar >> boost::serialization::make_nvp("item", t.reference());
- typename Container::const_iterator result
- = s.insert(t.reference());
+ typename Container::const_iterator result =
+ #ifdef BOOST_NO_CXX11_HDR_UNORDERED_SET
+ s.insert(t.reference());
+ #else
+ s.emplace(t.reference());
+ #endif
ar.reset_object_address(& (* result), & t.reference());
}
};
diff --git a/boost/serialization/array.hpp b/boost/serialization/array.hpp
index 97ac0c2501..2cd023aca9 100644
--- a/boost/serialization/array.hpp
+++ b/boost/serialization/array.hpp
@@ -6,13 +6,9 @@
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#include <boost/config.hpp> // msvc 6.0 needs this for warning suppression
+//#include <iostream>
-#include <iostream>
-#include <cstddef> // std::size_t
-#ifndef BOOST_NO_CXX11_HDR_ARRAY
-#include <array>
-#endif
+#include <boost/config.hpp> // msvc 6.0 needs this for warning suppression
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std{
@@ -23,11 +19,13 @@ namespace std{
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/split_member.hpp>
#include <boost/serialization/wrapper.hpp>
+#include <boost/serialization/collection_size_type.hpp>
#include <boost/mpl/always.hpp>
#include <boost/mpl/apply.hpp>
-#include <boost/mpl/bool.hpp>
+#include <boost/mpl/bool_fwd.hpp>
#include <boost/type_traits/remove_const.hpp>
-#include <boost/array.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/static_assert.hpp>
namespace boost { namespace serialization {
@@ -37,24 +35,27 @@ template <class Archive>
struct use_array_optimization : boost::mpl::always<boost::mpl::false_> {};
template<class T>
-class array :
- public wrapper_traits<const array< T > >
+class array_wrapper :
+ public wrapper_traits<const array_wrapper< T > >
{
-public:
- typedef T value_type;
-
- array(value_type* t, std::size_t s) :
- m_t(t),
- m_element_count(s)
- {}
- array(const array & rhs) :
+private:
+ array_wrapper & operator=(const array_wrapper & rhs);
+public:
+ // note: I would like to make the copy constructor private but this breaks
+ // make_array. So I try to make make_array a friend - but that doesn't
+ // build. Need a C++ guru to explain this!
+ template<class S>
+ friend const boost::serialization::array_wrapper<T> make_array( T* t, S s);
+
+ array_wrapper(const array_wrapper & rhs) :
m_t(rhs.m_t),
m_element_count(rhs.m_element_count)
{}
- array & operator=(const array & rhs){
- m_t = rhs.m_t;
- m_element_count = rhs.m_element_count;
- }
+public:
+ array_wrapper(T * t, std::size_t s) :
+ m_t(t),
+ m_element_count(s)
+ {}
// default implementation
template<class Archive>
@@ -62,7 +63,7 @@ public:
{
// default implemention does the loop
std::size_t c = count();
- value_type * t = address();
+ T * t = address();
while(0 < c--)
ar & boost::serialization::make_nvp("item", *t++);
}
@@ -99,7 +100,7 @@ public:
serialize_optimized(ar,version,use_optimized());
}
- value_type* address() const
+ T * address() const
{
return m_t;
}
@@ -108,26 +109,32 @@ public:
{
return m_element_count;
}
-
+
private:
- value_type* m_t;
- std::size_t m_element_count;
+ T * const m_t;
+ const std::size_t m_element_count;
};
-template<class T>
+template<class T, class S>
inline
-const array< T > make_array( T* t, std::size_t s){
- return array< T >(t, s);
+const array_wrapper< T > make_array( T* t, S s){
+ const array_wrapper< T > a(t, s);
+ return a;
}
-// implement serialization for boost::array
-template <class Archive, class T, std::size_t N>
-void serialize(Archive& ar, boost::array<T,N>& a, const unsigned int /* version */)
-{
- ar & boost::serialization::make_nvp("elems", a.elems);
-}
+} } // end namespace boost::serialization
+
+// I can't figure out why BOOST_NO_CXX11_HDR_ARRAY
+// has been set for clang-11. So just make sure
+// it's reset now. Needs further research!!!
+
+#if defined(_LIBCPP_VERSION)
+#undef BOOST_NO_CXX11_HDR_ARRAY
+#endif
#ifndef BOOST_NO_CXX11_HDR_ARRAY
+#include <array>
+namespace boost { namespace serialization {
// implement serialization for std::array
template <class Archive, class T, std::size_t N>
void serialize(Archive& ar, std::array<T,N>& a, const unsigned int /* version */)
@@ -138,8 +145,19 @@ void serialize(Archive& ar, std::array<T,N>& a, const unsigned int /* version */
);
}
+} } // end namespace boost::serialization
#endif
+#include <boost/array.hpp>
+
+namespace boost { namespace serialization {
+// implement serialization for boost::array
+template <class Archive, class T, std::size_t N>
+void serialize(Archive& ar, boost::array<T,N>& a, const unsigned int /* version */)
+{
+ ar & boost::serialization::make_nvp("elems", a.elems);
+}
+
} } // end namespace boost::serialization
#define BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(Archive) \
diff --git a/boost/serialization/assume_abstract.hpp b/boost/serialization/assume_abstract.hpp
index a5cb2f55a4..632f9312f5 100644
--- a/boost/serialization/assume_abstract.hpp
+++ b/boost/serialization/assume_abstract.hpp
@@ -19,6 +19,7 @@
// this is useful for compilers which don't support the boost::is_abstract
#include <boost/type_traits/is_abstract.hpp>
+#include <boost/mpl/bool_fwd.hpp>
#ifndef BOOST_NO_IS_ABSTRACT
diff --git a/boost/serialization/base_object.hpp b/boost/serialization/base_object.hpp
index 7ede6473e0..1a82cecd4b 100644
--- a/boost/serialization/base_object.hpp
+++ b/boost/serialization/base_object.hpp
@@ -25,7 +25,6 @@
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/int.hpp>
-#include <boost/mpl/bool.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
diff --git a/boost/serialization/collection_traits.hpp b/boost/serialization/collection_traits.hpp
index b3fe843426..3ec9401eff 100644
--- a/boost/serialization/collection_traits.hpp
+++ b/boost/serialization/collection_traits.hpp
@@ -23,7 +23,7 @@
// exists for archives to be non-portable if class information for primitive
// types is included. This is addressed by the following macros.
#include <boost/config.hpp>
-#include <boost/mpl/integral_c.hpp>
+//#include <boost/mpl/integral_c.hpp>
#include <boost/mpl/integral_c_tag.hpp>
#include <boost/cstdint.hpp>
diff --git a/boost/serialization/detail/stack_constructor.hpp b/boost/serialization/detail/stack_constructor.hpp
index 9027717a92..806b8877d7 100644
--- a/boost/serialization/detail/stack_constructor.hpp
+++ b/boost/serialization/detail/stack_constructor.hpp
@@ -17,6 +17,7 @@
// See http://www.boost.org for updates, documentation, and revision history.
#include <boost/aligned_storage.hpp>
+#include <boost/serialization/serialization.hpp>
namespace boost{
namespace serialization {
diff --git a/boost/serialization/export.hpp b/boost/serialization/export.hpp
index 9da9434a5f..9eef440df4 100644
--- a/boost/serialization/export.hpp
+++ b/boost/serialization/export.hpp
@@ -32,7 +32,7 @@
#include <boost/mpl/assert.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/not.hpp>
-#include <boost/mpl/bool.hpp>
+#include <boost/mpl/bool_fwd.hpp>
#include <boost/serialization/extended_type_info.hpp> // for guid_defined only
#include <boost/serialization/static_warning.hpp>
diff --git a/boost/serialization/forward_list.hpp b/boost/serialization/forward_list.hpp
index fd52f860b7..e17405383c 100644
--- a/boost/serialization/forward_list.hpp
+++ b/boost/serialization/forward_list.hpp
@@ -19,6 +19,11 @@
#include <forward_list>
#include <iterator> // distance
+#include <boost/config.hpp>
+#ifdef BOOST_NO_CXX11_HDR_FORWARD_LIST
+#error "not supported for versions earlier than c++11
+#endif
+
#include <boost/serialization/collections_save_imp.hpp>
#include <boost/serialization/collections_load_imp.hpp>
#include <boost/archive/detail/basic_iarchive.hpp>
@@ -36,7 +41,7 @@ template<class Archive, class U, class Allocator>
inline void save(
Archive & ar,
const std::forward_list<U, Allocator> &t,
- const unsigned int file_version
+ const unsigned int /*file_version*/
){
const collection_size_type count(std::distance(t.cbegin(), t.cend()));
boost::serialization::stl::save_collection<
@@ -67,14 +72,14 @@ collection_load_impl(
t.clear();
boost::serialization::detail::stack_construct<Archive, T> u(ar, item_version);
ar >> boost::serialization::make_nvp("item", u.reference());
- t.push_front(u.reference());
+ t.emplace_front(u.reference());
typename std::forward_list<T, Allocator>::iterator last;
last = t.begin();
ar.reset_object_address(&(*t.begin()) , & u.reference());
while(--count > 0){
detail::stack_construct<Archive, T> u(ar, item_version);
ar >> boost::serialization::make_nvp("item", u.reference());
- last = t.insert_after(last, u.reference());
+ last = t.emplace_after(last, u.reference());
ar.reset_object_address(&(*last) , & u.reference());
}
}
@@ -85,7 +90,7 @@ template<class Archive, class U, class Allocator>
inline void load(
Archive & ar,
std::forward_list<U, Allocator> &t,
- const unsigned int file_version
+ const unsigned int /*file_version*/
){
const boost::archive::library_version_type library_version(
ar.get_library_version()
diff --git a/boost/serialization/is_bitwise_serializable.hpp b/boost/serialization/is_bitwise_serializable.hpp
index dac597ec2c..7e24a2cb6d 100644
--- a/boost/serialization/is_bitwise_serializable.hpp
+++ b/boost/serialization/is_bitwise_serializable.hpp
@@ -21,7 +21,7 @@
# pragma once
#endif
-#include <boost/mpl/bool.hpp>
+#include <boost/mpl/bool_fwd.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
namespace boost {
diff --git a/boost/serialization/map.hpp b/boost/serialization/map.hpp
index 1358d49b7a..2582f9aced 100644
--- a/boost/serialization/map.hpp
+++ b/boost/serialization/map.hpp
@@ -57,11 +57,16 @@ inline void load_map_collection(Archive & ar, Container &s)
while(count-- > 0){
typedef typename Container::value_type type;
detail::stack_construct<Archive, type> t(ar, item_version);
- // borland fails silently w/o full namespace
ar >> boost::serialization::make_nvp("item", t.reference());
- typename Container::iterator result = s.insert(hint, t.reference());
+ typename Container::iterator result =
+ #ifdef BOOST_NO_CXX11_HDR_UNORDERED_MAP
+ s.insert(hint, t.reference());
+ #else
+ s.emplace_hint(hint, t.reference());
+ #endif
ar.reset_object_address(& (result->second), & t.reference().second);
hint = result;
+ ++hint;
}
}
diff --git a/boost/serialization/nvp.hpp b/boost/serialization/nvp.hpp
index 6a1eb82656..4e2297b3cc 100644
--- a/boost/serialization/nvp.hpp
+++ b/boost/serialization/nvp.hpp
@@ -21,9 +21,6 @@
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
-#include <boost/mpl/integral_c.hpp>
-#include <boost/mpl/integral_c_tag.hpp>
-
#include <boost/serialization/level.hpp>
#include <boost/serialization/tracking.hpp>
#include <boost/serialization/split_member.hpp>
@@ -39,14 +36,14 @@ struct nvp :
public std::pair<const char *, T *>,
public wrapper_traits<const nvp< T > >
{
+//private:
+ nvp(const nvp & rhs) :
+ std::pair<const char *, T *>(rhs.first, rhs.second)
+ {}
+public:
explicit nvp(const char * name_, T & t) :
- // note: redundant cast works around borland issue
// note: added _ to suppress useless gcc warning
- std::pair<const char *, T *>(name_, (T*)(& t))
- {}
- nvp(const nvp & rhs) :
- // note: redundant cast works around borland issue
- std::pair<const char *, T *>(rhs.first, (T*)rhs.second)
+ std::pair<const char *, T *>(name_, & t)
{}
const char * name() const {
@@ -60,26 +57,18 @@ struct nvp :
return *(this->second);
}
- // True64 compiler complains with a warning about the use of
- // the name "Archive" hiding some higher level usage. I'm sure this
- // is an error but I want to accomodated as it generates a long warning
- // listing and might be related to a lot of test failures.
- // default treatment for name-value pairs. The name is
- // just discarded and only the value is serialized.
- template<class Archivex>
+ template<class Archive>
void save(
- Archivex & ar,
+ Archive & ar,
const unsigned int /* file_version */
) const {
- // CodeWarrior 8.x can't seem to resolve the << op for a rhs of "const T *"
ar.operator<<(const_value());
}
- template<class Archivex>
+ template<class Archive>
void load(
- Archivex & ar,
+ Archive & ar,
const unsigned int /* file_version */
){
- // CodeWarrior 8.x can't seem to resolve the >> op for a rhs of "const T *"
ar.operator>>(value());
}
BOOST_SERIALIZATION_SPLIT_MEMBER()
@@ -115,7 +104,6 @@ struct tracking_level<nvp< T > >
BOOST_STATIC_CONSTANT(int, value = tracking_level::type::value);
};
-
} // seralization
} // boost
diff --git a/boost/serialization/set.hpp b/boost/serialization/set.hpp
index 01289d5e36..6b957d470e 100644
--- a/boost/serialization/set.hpp
+++ b/boost/serialization/set.hpp
@@ -54,7 +54,12 @@ inline void load_set_collection(Archive & ar, Container &s)
detail::stack_construct<Archive, type> t(ar, item_version);
// borland fails silently w/o full namespace
ar >> boost::serialization::make_nvp("item", t.reference());
- typename Container::iterator result = s.insert(hint, t.reference());
+ typename Container::iterator result =
+ #ifdef BOOST_NO_CXX11_HDR_UNORDERED_SET
+ s.insert(hint, t.reference());
+ #else
+ s.emplace_hint(hint, t.reference());
+ #endif
ar.reset_object_address(& (* result), & t.reference());
hint = result;
}
diff --git a/boost/serialization/singleton.hpp b/boost/serialization/singleton.hpp
index db32395ce2..fcb79c3694 100644
--- a/boost/serialization/singleton.hpp
+++ b/boost/serialization/singleton.hpp
@@ -39,6 +39,10 @@
#include <boost/noncopyable.hpp>
#include <boost/serialization/force_include.hpp>
+#include <boost/archive/detail/auto_link_archive.hpp>
+#include <boost/serialization/config.hpp>
+#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
+
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4511 4512)
@@ -81,25 +85,15 @@ class BOOST_SYMBOL_VISIBLE singleton_module :
public boost::noncopyable
{
private:
- static bool & get_lock(){
- static bool lock = false;
- return lock;
- }
+ static bool & get_lock();
public:
-// static const void * get_module_handle(){
-// return static_cast<const void *>(get_module_handle);
-// }
- static void lock(){
- get_lock() = true;
- }
- static void unlock(){
- get_lock() = false;
- }
- static bool is_locked() {
- return get_lock();
- }
+ BOOST_SERIALIZATION_DECL static void lock();
+ BOOST_SERIALIZATION_DECL static void unlock();
+ BOOST_SERIALIZATION_DECL static bool is_locked();
};
+#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
namespace detail {
template<class T>
diff --git a/boost/serialization/static_warning.hpp b/boost/serialization/static_warning.hpp
index 2d49de1c2d..1d9238fc4d 100644
--- a/boost/serialization/static_warning.hpp
+++ b/boost/serialization/static_warning.hpp
@@ -66,6 +66,7 @@
#include <boost/mpl/bool.hpp>
#include <boost/mpl/print.hpp>
#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/bool_fwd.hpp>
#include <boost/static_assert.hpp>
namespace boost {
diff --git a/boost/serialization/traits.hpp b/boost/serialization/traits.hpp
index d338b1b123..9e114fdd3d 100644
--- a/boost/serialization/traits.hpp
+++ b/boost/serialization/traits.hpp
@@ -28,7 +28,7 @@
#include <boost/static_assert.hpp>
#include <boost/mpl/int.hpp>
-#include <boost/mpl/bool.hpp>
+#include <boost/mpl/bool_fwd.hpp>
#include <boost/serialization/level_enum.hpp>
#include <boost/serialization/tracking_enum.hpp>
diff --git a/boost/serialization/unique_ptr.hpp b/boost/serialization/unique_ptr.hpp
index ac615b9d19..8d8703ef4f 100644
--- a/boost/serialization/unique_ptr.hpp
+++ b/boost/serialization/unique_ptr.hpp
@@ -30,7 +30,7 @@ template<class Archive, class T>
inline void save(
Archive & ar,
const std::unique_ptr< T > &t,
- const unsigned int file_version
+ const unsigned int /*file_version*/
){
// only the raw pointer has to be saved
// the ref count is rebuilt automatically on load
@@ -42,7 +42,7 @@ template<class Archive, class T>
inline void load(
Archive & ar,
std::unique_ptr< T > &t,
- const unsigned int file_version
+ const unsigned int /*file_version*/
){
T *tx;
ar >> BOOST_SERIALIZATION_NVP(tx);
diff --git a/boost/serialization/valarray.hpp b/boost/serialization/valarray.hpp
index d24fda5437..efe102f6cf 100644
--- a/boost/serialization/valarray.hpp
+++ b/boost/serialization/valarray.hpp
@@ -40,20 +40,20 @@ namespace serialization {
template<class Archive, class U>
void save( Archive & ar, const STD::valarray<U> &t, const unsigned int /*file_version*/ )
{
- const collection_size_type count(t.size());
- ar << BOOST_SERIALIZATION_NVP(count);
- if (t.size())
- ar << make_array(detail::get_data(t), t.size());
+ const collection_size_type count(t.size());
+ ar << BOOST_SERIALIZATION_NVP(count);
+ if (t.size())
+ ar << make_array(detail::get_data(t), t.size());
}
template<class Archive, class U>
void load( Archive & ar, STD::valarray<U> &t, const unsigned int /*file_version*/ )
{
- collection_size_type count;
- ar >> BOOST_SERIALIZATION_NVP(count);
- t.resize(count);
- if (t.size())
- ar >> make_array(detail::get_data(t), t.size());
+ collection_size_type count;
+ ar >> BOOST_SERIALIZATION_NVP(count);
+ t.resize(count);
+ if (t.size())
+ ar >> make_array(detail::get_data(t), t.size());
}
// split non-intrusive serialization function member into separate
diff --git a/boost/serialization/vector.hpp b/boost/serialization/vector.hpp
index 6e49bff38a..a1737548ef 100644
--- a/boost/serialization/vector.hpp
+++ b/boost/serialization/vector.hpp
@@ -34,7 +34,7 @@
#include <boost/serialization/array.hpp>
#include <boost/serialization/detail/get_data.hpp>
#include <boost/serialization/detail/stack_constructor.hpp>
-#include <boost/mpl/bool.hpp>
+#include <boost/mpl/bool_fwd.hpp>
#include <boost/mpl/if.hpp>
// default is being compatible with version 1.34.1 files, not 1.35 files
@@ -103,7 +103,7 @@ inline void save(
const collection_size_type count(t.size());
ar << BOOST_SERIALIZATION_NVP(count);
if (!t.empty())
- ar << make_array(detail::get_data(t),t.size());
+ ar << boost::serialization::make_array(detail::get_data(t),t.size());
}
template<class Archive, class U, class Allocator>
@@ -121,7 +121,7 @@ inline void load(
ar >> BOOST_SERIALIZATION_NVP(item_version);
}
if (!t.empty())
- ar >> make_array(detail::get_data(t),t.size());
+ ar >> boost::serialization::make_array(detail::get_data(t),t.size());
}
// dispatch to either default or optimized versions
diff --git a/boost/serialization/vector_135.hpp b/boost/serialization/vector_135.hpp
index 2097cf641e..fd1a7393d1 100644
--- a/boost/serialization/vector_135.hpp
+++ b/boost/serialization/vector_135.hpp
@@ -15,7 +15,7 @@
#ifdef BOOST_SERIALIZATION_VECTOR_VERSIONED
#if BOOST_SERIALIZATION_VECTOR_VERSION != 4
-#error Boost.Serialization cannot be compatible with both 1.35 and 1.36-1.40 files
+#error "Boost.Serialization cannot be compatible with both 1.35 and 1.36-1.40 files"
#endif
#else
#define BOOST_SERIALIZATION_VECTOR_VERSIONED(V) (V>4)
diff --git a/boost/serialization/wrapper.hpp b/boost/serialization/wrapper.hpp
index 6a2a730dde..60d7910b17 100644
--- a/boost/serialization/wrapper.hpp
+++ b/boost/serialization/wrapper.hpp
@@ -9,7 +9,7 @@
#include <boost/serialization/traits.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/mpl/eval_if.hpp>
-#include <boost/mpl/bool.hpp>
+#include <boost/mpl/bool_fwd.hpp>
namespace boost { namespace serialization {
diff --git a/boost/signals2/detail/variadic_slot_invoker.hpp b/boost/signals2/detail/variadic_slot_invoker.hpp
index ab1dfeea6c..59739b3f36 100644
--- a/boost/signals2/detail/variadic_slot_invoker.hpp
+++ b/boost/signals2/detail/variadic_slot_invoker.hpp
@@ -84,21 +84,21 @@ namespace boost
typedef R result_type;
template<typename Func, typename ... Args, std::size_t N>
- R operator()(Func &func, BOOST_SIGNALS2_TUPLE<Args...> args, mpl::size_t<N>) const
+ R operator()(Func &func, const BOOST_SIGNALS2_TUPLE<Args...> & args, mpl::size_t<N>) const
{
typedef typename make_unsigned_meta_array<N>::type indices_type;
return m_invoke<Func>(func, indices_type(), args);
}
private:
template<typename Func, unsigned ... indices, typename ... Args>
- R m_invoke(Func &func, unsigned_meta_array<indices...>, BOOST_SIGNALS2_TUPLE<Args...> args,
+ R m_invoke(Func &func, unsigned_meta_array<indices...>, const BOOST_SIGNALS2_TUPLE<Args...> & args,
typename boost::disable_if<boost::is_void<typename Func::result_type> >::type * = 0
) const
{
return func(BOOST_SIGNALS2_GET<indices>(args)...);
}
template<typename Func, unsigned ... indices, typename ... Args>
- R m_invoke(Func &func, unsigned_meta_array<indices...>, BOOST_SIGNALS2_TUPLE<Args...> args,
+ R m_invoke(Func &func, unsigned_meta_array<indices...>, const BOOST_SIGNALS2_TUPLE<Args...> & args,
typename boost::enable_if<boost::is_void<typename Func::result_type> >::type * = 0
) const
{
@@ -110,9 +110,9 @@ namespace boost
// only exists to quiet some unused parameter warnings
// on certain compilers (some versions of gcc and msvc)
template<typename Func>
- R m_invoke(Func &func, unsigned_meta_array<>, BOOST_SIGNALS2_TUPLE<>,
- typename boost::enable_if<boost::is_void<typename Func::result_type> >::type * = 0
- ) const
+ R m_invoke(Func &func, unsigned_meta_array<>, const BOOST_SIGNALS2_TUPLE<> &,
+ typename boost::enable_if<boost::is_void<typename Func::result_type> >::type * = 0
+ ) const
{
func();
return R();
diff --git a/boost/smart_ptr/detail/up_if_array.hpp b/boost/smart_ptr/detail/up_if_array.hpp
deleted file mode 100644
index 7e62d106b4..0000000000
--- a/boost/smart_ptr/detail/up_if_array.hpp
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2014 Glen Joseph Fernandes
- * glenfe at live dot com
- *
- * Distributed under the Boost Software License,
- * Version 1.0. (See accompanying file LICENSE_1_0.txt
- * or copy at http://boost.org/LICENSE_1_0.txt)
- */
-#ifndef BOOST_SMART_PTR_DETAIL_UP_IF_ARRAY_HPP
-#define BOOST_SMART_PTR_DETAIL_UP_IF_ARRAY_HPP
-
-#include <memory>
-
-namespace boost {
- namespace detail {
- template<class T>
- struct up_if_array;
-
- template<class T>
- struct up_if_array<T[]> {
- typedef std::unique_ptr<T[]> type;
- };
- }
-}
-
-#endif
diff --git a/boost/smart_ptr/detail/up_if_not_array.hpp b/boost/smart_ptr/detail/up_if_not_array.hpp
deleted file mode 100644
index fd74f25318..0000000000
--- a/boost/smart_ptr/detail/up_if_not_array.hpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2014 Glen Joseph Fernandes
- * glenfe at live dot com
- *
- * Distributed under the Boost Software License,
- * Version 1.0. (See accompanying file LICENSE_1_0.txt
- * or copy at http://boost.org/LICENSE_1_0.txt)
- */
-#ifndef BOOST_SMART_PTR_DETAIL_UP_IF_NOT_ARRAY_HPP
-#define BOOST_SMART_PTR_DETAIL_UP_IF_NOT_ARRAY_HPP
-
-#include <memory>
-
-namespace boost {
- namespace detail {
- template<class T>
- struct up_if_not_array {
- typedef std::unique_ptr<T> type;
- };
-
- template<class T>
- struct up_if_not_array<T[]> {
- };
-
- template<class T, std::size_t N>
- struct up_if_not_array<T[N]> {
- };
- }
-}
-
-#endif
diff --git a/boost/smart_ptr/make_unique.hpp b/boost/smart_ptr/make_unique.hpp
index 90402e2baa..d054e3dfe1 100644
--- a/boost/smart_ptr/make_unique.hpp
+++ b/boost/smart_ptr/make_unique.hpp
@@ -1,15 +1,105 @@
/*
- * Copyright (c) 2014 Glen Joseph Fernandes
- * glenfe at live dot com
- *
- * Distributed under the Boost Software License,
- * Version 1.0. (See accompanying file LICENSE_1_0.txt
- * or copy at http://boost.org/LICENSE_1_0.txt)
- */
+(c) 2014-2015 Glen Joseph Fernandes
+<glenjofe -at- gmail.com>
+
+Distributed under the Boost Software
+License, Version 1.0.
+http://boost.org/LICENSE_1_0.txt
+*/
#ifndef BOOST_SMART_PTR_MAKE_UNIQUE_HPP
#define BOOST_SMART_PTR_MAKE_UNIQUE_HPP
-#include <boost/smart_ptr/make_unique_array.hpp>
-#include <boost/smart_ptr/make_unique_object.hpp>
+#include <boost/config.hpp>
+#include <memory>
+#include <utility>
+
+namespace boost {
+namespace detail {
+template<class T>
+struct up_if_object {
+ typedef std::unique_ptr<T> type;
+};
+
+template<class T>
+struct up_if_object<T[]> { };
+
+template<class T, std::size_t N>
+struct up_if_object<T[N]> { };
+
+template<class T>
+struct up_if_array { };
+
+template<class T>
+struct up_if_array<T[]> {
+ typedef std::unique_ptr<T[]> type;
+};
+
+template<class T>
+struct up_remove_reference {
+ typedef T type;
+};
+
+template<class T>
+struct up_remove_reference<T&> {
+ typedef T type;
+};
+
+template<class T>
+struct up_remove_reference<T&&> {
+ typedef T type;
+};
+
+template<class T>
+struct up_element { };
+
+template<class T>
+struct up_element<T[]> {
+ typedef T type;
+};
+} /* detail */
+
+template<class T>
+inline typename detail::up_if_object<T>::type make_unique()
+{
+ return std::unique_ptr<T>(new T());
+}
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+template<class T, class... Args>
+inline typename detail::up_if_object<T>::type
+ make_unique(Args&&... args)
+{
+ return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+}
+#endif
+
+template<class T>
+inline typename detail::up_if_object<T>::type
+ make_unique(typename detail::up_remove_reference<T>::type&& value)
+{
+ return std::unique_ptr<T>(new T(std::move(value)));
+}
+
+template<class T>
+inline typename detail::up_if_object<T>::type make_unique_noinit()
+{
+ return std::unique_ptr<T>(new T);
+}
+
+template<class T>
+inline typename detail::up_if_array<T>::type make_unique(std::size_t n)
+{
+ return std::unique_ptr<T>(new
+ typename detail::up_element<T>::type[n]());
+}
+
+template<class T>
+inline typename detail::up_if_array<T>::type
+ make_unique_noinit(std::size_t n)
+{
+ return std::unique_ptr<T>(new
+ typename detail::up_element<T>::type[n]);
+}
+} /* boost */
#endif
diff --git a/boost/smart_ptr/make_unique_array.hpp b/boost/smart_ptr/make_unique_array.hpp
deleted file mode 100644
index eb0528e63d..0000000000
--- a/boost/smart_ptr/make_unique_array.hpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2014 Glen Joseph Fernandes
- * glenfe at live dot com
- *
- * Distributed under the Boost Software License,
- * Version 1.0. (See accompanying file LICENSE_1_0.txt
- * or copy at http://boost.org/LICENSE_1_0.txt)
- */
-#ifndef BOOST_SMART_PTR_MAKE_UNIQUE_ARRAY_HPP
-#define BOOST_SMART_PTR_MAKE_UNIQUE_ARRAY_HPP
-
-#include <boost/smart_ptr/detail/up_if_array.hpp>
-#include <boost/smart_ptr/detail/array_traits.hpp>
-
-namespace boost {
- template<class T>
- inline typename boost::detail::up_if_array<T>::type
- make_unique(std::size_t size) {
- typedef typename boost::detail::array_inner<T>::type U;
- return std::unique_ptr<T>(new U[size]());
- }
-
- template<class T>
- inline typename boost::detail::up_if_array<T>::type
- make_unique_noinit(std::size_t size) {
- typedef typename boost::detail::array_inner<T>::type U;
- return std::unique_ptr<T>(new U[size]);
- }
-}
-
-#endif
diff --git a/boost/smart_ptr/make_unique_object.hpp b/boost/smart_ptr/make_unique_object.hpp
deleted file mode 100644
index 9e6108a36a..0000000000
--- a/boost/smart_ptr/make_unique_object.hpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2014 Glen Joseph Fernandes
- * glenfe at live dot com
- *
- * Distributed under the Boost Software License,
- * Version 1.0. (See accompanying file LICENSE_1_0.txt
- * or copy at http://boost.org/LICENSE_1_0.txt)
- */
-#ifndef BOOST_SMART_PTR_MAKE_UNIQUE_OBJECT_HPP
-#define BOOST_SMART_PTR_MAKE_UNIQUE_OBJECT_HPP
-
-#include <boost/config.hpp>
-#include <boost/smart_ptr/detail/up_if_not_array.hpp>
-#include <boost/type_traits/add_rvalue_reference.hpp>
-#include <utility>
-
-namespace boost {
- template<class T>
- inline typename boost::detail::up_if_not_array<T>::type
- make_unique() {
- return std::unique_ptr<T>(new T());
- }
-
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- template<class T, class... Args>
- inline typename boost::detail::up_if_not_array<T>::type
- make_unique(Args&&... args) {
- return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
- }
-#endif
-
- template<class T>
- inline typename boost::detail::up_if_not_array<T>::type
- make_unique(typename add_rvalue_reference<T>::type value) {
- return std::unique_ptr<T>(new T(std::move(value)));
- }
-
- template<class T>
- inline typename boost::detail::up_if_not_array<T>::type
- make_unique_noinit() {
- return std::unique_ptr<T>(new T);
- }
-}
-
-#endif
diff --git a/boost/smart_ptr/shared_ptr.hpp b/boost/smart_ptr/shared_ptr.hpp
index 47bc33d517..bcefda8897 100644
--- a/boost/smart_ptr/shared_ptr.hpp
+++ b/boost/smart_ptr/shared_ptr.hpp
@@ -1065,7 +1065,7 @@ template< class T > struct hash;
template< class T > std::size_t hash_value( boost::shared_ptr<T> const & p ) BOOST_NOEXCEPT
{
- return boost::hash< T* >()( p.get() );
+ return boost::hash< typename boost::shared_ptr<T>::element_type* >()( p.get() );
}
} // namespace boost
diff --git a/boost/sort/spreadsort/detail/string_sort.hpp b/boost/sort/spreadsort/detail/string_sort.hpp
index ef943b8ec4..582508fb7b 100644
--- a/boost/sort/spreadsort/detail/string_sort.hpp
+++ b/boost/sort/spreadsort/detail/string_sort.hpp
@@ -285,7 +285,7 @@ namespace spreadsort {
++last;
//Offsetting on identical characters. This section works
//a few characters at a time for optimal worst-case performance.
- update_offset<RandomAccessIter, Unsigned_char_type>(first, last,
+ update_offset<RandomAccessIter, Unsigned_char_type>(curr, last,
char_offset);
RandomAccessIter * target_bin;
diff --git a/boost/spirit/home/classic/core/non_terminal/impl/grammar.ipp b/boost/spirit/home/classic/core/non_terminal/impl/grammar.ipp
index 1f18b3255c..002d221eeb 100644
--- a/boost/spirit/home/classic/core/non_terminal/impl/grammar.ipp
+++ b/boost/spirit/home/classic/core/non_terminal/impl/grammar.ipp
@@ -281,17 +281,19 @@ struct grammar_definition
grammar_destruct(GrammarT* self)
{
#if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE)
- typedef impl::grammar_helper_base<GrammarT> helper_base_t;
typedef grammar_helper_list<GrammarT> helper_list_t;
- typedef typename helper_list_t::vector_t::reverse_iterator iterator_t;
helper_list_t& helpers =
grammartract_helper_list::do_(self);
# if defined(BOOST_INTEL_CXX_VERSION)
+ typedef typename helper_list_t::vector_t::reverse_iterator iterator_t;
+
for (iterator_t i = helpers.rbegin(); i != helpers.rend(); ++i)
(*i)->undefine(self);
# else
+ typedef impl::grammar_helper_base<GrammarT> helper_base_t;
+
std::for_each(helpers.rbegin(), helpers.rend(),
std::bind2nd(std::mem_fun(&helper_base_t::undefine), self));
# endif
diff --git a/boost/spirit/home/classic/core/non_terminal/impl/rule.ipp b/boost/spirit/home/classic/core/non_terminal/impl/rule.ipp
index 9f10306f7c..137694ef2f 100644
--- a/boost/spirit/home/classic/core/non_terminal/impl/rule.ipp
+++ b/boost/spirit/home/classic/core/non_terminal/impl/rule.ipp
@@ -24,6 +24,7 @@
#include <boost/spirit/home/classic/core/non_terminal/parser_context.hpp>
#include <boost/spirit/home/classic/core/non_terminal/parser_id.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
+#include <boost/mpl/if.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit {
diff --git a/boost/spirit/home/classic/core/non_terminal/impl/subrule.ipp b/boost/spirit/home/classic/core/non_terminal/impl/subrule.ipp
index f6bdaaf40d..fc952fedea 100644
--- a/boost/spirit/home/classic/core/non_terminal/impl/subrule.ipp
+++ b/boost/spirit/home/classic/core/non_terminal/impl/subrule.ipp
@@ -10,6 +10,8 @@
#if !defined(BOOST_SPIRIT_SUBRULE_IPP)
#define BOOST_SPIRIT_SUBRULE_IPP
+#include <boost/mpl/if.hpp>
+
namespace boost { namespace spirit {
BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
diff --git a/boost/spirit/home/classic/core/non_terminal/subrule.hpp b/boost/spirit/home/classic/core/non_terminal/subrule.hpp
index 8b25d8d0e3..1d16d70aea 100644
--- a/boost/spirit/home/classic/core/non_terminal/subrule.hpp
+++ b/boost/spirit/home/classic/core/non_terminal/subrule.hpp
@@ -11,6 +11,9 @@
#include <boost/config.hpp>
#include <boost/static_assert.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/type_traits/is_same.hpp>
#include <boost/spirit/home/classic/namespace.hpp>
#include <boost/spirit/home/classic/core/parser.hpp>
diff --git a/boost/spirit/home/classic/iterator/position_iterator.hpp b/boost/spirit/home/classic/iterator/position_iterator.hpp
index e352f883ae..5607047264 100644
--- a/boost/spirit/home/classic/iterator/position_iterator.hpp
+++ b/boost/spirit/home/classic/iterator/position_iterator.hpp
@@ -95,7 +95,7 @@ BOOST_SPIRIT_CLASSIC_NAMESPACE_END
// This must be included here for full compatibility with old MSVC
-#include "boost/spirit/home/classic/iterator/impl/position_iterator.ipp"
+#include <boost/spirit/home/classic/iterator/impl/position_iterator.ipp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit {
diff --git a/boost/spirit/home/classic/tree/parse_tree_utils.hpp b/boost/spirit/home/classic/tree/parse_tree_utils.hpp
index 105d80eb13..b9e52e3a2d 100644
--- a/boost/spirit/home/classic/tree/parse_tree_utils.hpp
+++ b/boost/spirit/home/classic/tree/parse_tree_utils.hpp
@@ -59,6 +59,6 @@ BOOST_SPIRIT_CLASSIC_NAMESPACE_END
} // namespace spirit
} // namespace boost
-#include "boost/spirit/home/classic/tree/impl/parse_tree_utils.ipp"
+#include <boost/spirit/home/classic/tree/impl/parse_tree_utils.ipp>
#endif // !defined(PARSE_TREE_UTILS_HPP)
diff --git a/boost/spirit/home/qi/string/tst_map.hpp b/boost/spirit/home/qi/string/tst_map.hpp
index a3208f2743..19f977ddce 100644
--- a/boost/spirit/home/qi/string/tst_map.hpp
+++ b/boost/spirit/home/qi/string/tst_map.hpp
@@ -11,14 +11,13 @@
#pragma once
#endif
+#include <boost/spirit/home/qi/string/tst.hpp>
#include <boost/spirit/home/qi/string/detail/tst.hpp>
#include <boost/unordered_map.hpp>
#include <boost/pool/object_pool.hpp>
namespace boost { namespace spirit { namespace qi
{
- struct tst_pass_through; // declared in tst.hpp
-
template <typename Char, typename T>
struct tst_map
{
diff --git a/boost/spirit/home/support/extended_variant.hpp b/boost/spirit/home/support/extended_variant.hpp
index 4d3ae599d6..bb2ea0d353 100644
--- a/boost/spirit/home/support/extended_variant.hpp
+++ b/boost/spirit/home/support/extended_variant.hpp
@@ -104,6 +104,11 @@ namespace boost { namespace spirit
{
return var;
}
+
+ void swap(extended_variant& rhs) BOOST_NOEXCEPT
+ {
+ var.swap(rhs.var);
+ }
variant_type var;
};
diff --git a/boost/spirit/home/support/terminal.hpp b/boost/spirit/home/support/terminal.hpp
index 0497d5faf4..dd52da9c25 100644
--- a/boost/spirit/home/support/terminal.hpp
+++ b/boost/spirit/home/support/terminal.hpp
@@ -13,6 +13,7 @@
#pragma once
#endif
+#include <boost/config.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/proto/proto.hpp>
@@ -261,6 +262,12 @@ namespace boost { namespace spirit
: base_type(proto::terminal<Terminal>::type::make(t))
{}
+#if defined(BOOST_MSVC)
+#pragma warning(push)
+// warning C4348: 'boost::spirit::terminal<...>::result_helper': redefinition of default parameter: parameter 3, 4
+#pragma warning(disable: 4348)
+#endif
+
template <
bool Lazy
, typename A0
@@ -269,6 +276,10 @@ namespace boost { namespace spirit
>
struct result_helper;
+#if defined(BOOST_MSVC)
+#pragma warning(pop)
+#endif
+
template <
typename A0
>
diff --git a/boost/spirit/home/x3/auxiliary/eol.hpp b/boost/spirit/home/x3/auxiliary/eol.hpp
index 00e4488937..69a58ec60e 100644
--- a/boost/spirit/home/x3/auxiliary/eol.hpp
+++ b/boost/spirit/home/x3/auxiliary/eol.hpp
@@ -16,7 +16,7 @@ namespace boost { namespace spirit { namespace x3
{
struct eol_parser : parser<eol_parser>
{
- typedef unused_type attribute_type;
+ typedef unused_type attribute_type;
static bool const has_attribute = false;
template <typename Iterator, typename Context, typename Attribute>
diff --git a/boost/spirit/home/x3/binary/binary.hpp b/boost/spirit/home/x3/binary/binary.hpp
index b3d3a79473..551e5b3865 100644
--- a/boost/spirit/home/x3/binary/binary.hpp
+++ b/boost/spirit/home/x3/binary/binary.hpp
@@ -30,6 +30,7 @@ namespace boost { namespace spirit { namespace x3
: parser<binary_lit_parser<V, T, endian, bits> >
{
static bool const has_attribute = false;
+ typedef unused_type attribute_type;
binary_lit_parser(V n_)
: n(n_) {}
diff --git a/boost/spirit/home/x3/char/any_char.hpp b/boost/spirit/home/x3/char/any_char.hpp
index 380645d2ff..6add7b6473 100644
--- a/boost/spirit/home/x3/char/any_char.hpp
+++ b/boost/spirit/home/x3/char/any_char.hpp
@@ -54,7 +54,7 @@ namespace boost { namespace spirit { namespace x3
template <typename Char>
char_range<Encoding> operator()(Char (&from)[2], Char (&to)[2]) const
{
- return { from[0], to[0] };
+ return { static_cast<char_type>(from[0]), static_cast<char_type>(to[0]) };
}
template <typename Char>
diff --git a/boost/spirit/home/x3/core/parse.hpp b/boost/spirit/home/x3/core/parse.hpp
index 234903037f..63878e0756 100644
--- a/boost/spirit/home/x3/core/parse.hpp
+++ b/boost/spirit/home/x3/core/parse.hpp
@@ -106,6 +106,9 @@ namespace boost { namespace spirit { namespace x3
// calling this function. You need to supply at least a forward_iterator
// instead.
BOOST_CONCEPT_ASSERT((ForwardIterator<Iterator>));
+
+ static_assert(!std::is_same<Skipper, unused_type>::value,
+ "Error! Skipper cannot be unused_type.");
// If you get an error no matching function for call to 'as_parser'
// here, for either p or s, then p or s is not a parser or there is
diff --git a/boost/spirit/home/x3/directive/expect.hpp b/boost/spirit/home/x3/directive/expect.hpp
index 879d92c2df..fe4491a22e 100644
--- a/boost/spirit/home/x3/directive/expect.hpp
+++ b/boost/spirit/home/x3/directive/expect.hpp
@@ -9,6 +9,8 @@
#include <boost/spirit/home/x3/support/context.hpp>
#include <boost/spirit/home/x3/core/parser.hpp>
+#include <boost/spirit/home/x3/core/detail/parse_into_container.hpp>
+
#include <boost/throw_exception.hpp>
#include <stdexcept>
@@ -24,10 +26,10 @@ namespace boost { namespace spirit { namespace x3
, where_(where), which_(which)
{}
~expectation_failure() throw() {}
-
+
std::string which() const { return which_; }
Iterator const& where() const { return where_; }
-
+
private:
Iterator where_;
@@ -73,4 +75,30 @@ namespace boost { namespace spirit { namespace x3
auto const expect = expect_gen{};
}}}
+namespace boost { namespace spirit { namespace x3 { namespace detail
+{
+ // Special case handling for expect expressions.
+ template <typename Subject, typename Context, typename RContext>
+ struct parse_into_container_impl<expect_directive<Subject>, Context, RContext>
+ {
+ template <typename Iterator, typename Attribute>
+ static bool call(
+ expect_directive<Subject> const& parser
+ , Iterator& first, Iterator const& last
+ , Context const& context, RContext& rcontext, Attribute& attr)
+ {
+ bool r = parse_into_container(
+ parser.subject, first, last, context, rcontext, attr);
+
+ if (!r)
+ {
+ boost::throw_exception(
+ expectation_failure<Iterator>(
+ first, what(parser.subject)));
+ }
+ return r;
+ }
+ };
+}}}}
+
#endif
diff --git a/boost/spirit/home/x3/directive/with.hpp b/boost/spirit/home/x3/directive/with.hpp
index 359f5adf1c..153c236b22 100644
--- a/boost/spirit/home/x3/directive/with.hpp
+++ b/boost/spirit/home/x3/directive/with.hpp
@@ -72,7 +72,7 @@ namespace boost { namespace spirit { namespace x3
template <typename ID, typename T>
struct with_context<ID, T, unused_type>
{
- typedef context<ID, T> const type;
+ typedef context<ID, T> type;
};
template <typename ID, typename T>
diff --git a/boost/spirit/home/x3/nonterminal/detail/rule.hpp b/boost/spirit/home/x3/nonterminal/detail/rule.hpp
index 71dc4c549f..e07b067718 100644
--- a/boost/spirit/home/x3/nonterminal/detail/rule.hpp
+++ b/boost/spirit/home/x3/nonterminal/detail/rule.hpp
@@ -318,17 +318,18 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
//called inside the following scope.
;
{
- //Create a scope to cause the dbg variable below (within
- //the #if...#endif) to call it's DTOR before any
- //modifications are made to the attribute, attr_ passed
- //to parse_rhs (such as might be done in
- //traits::post_transform when, for example,
- //ActualAttribute is a recursive variant).
+ // Create a scope to cause the dbg variable below (within
+ // the #if...#endif) to call it's DTOR before any
+ // modifications are made to the attribute, attr_ passed
+ // to parse_rhs (such as might be done in
+ // traits::post_transform when, for example,
+ // ActualAttribute is a recursive variant).
#if defined(BOOST_SPIRIT_X3_DEBUG)
- context_debug<Iterator, typename make_attribute::value_type>
- dbg(rule_name, first, last, attr_, ok_parse);
+ typedef typename make_attribute::type dbg_attribute_type;
+ context_debug<Iterator, dbg_attribute_type>
+ dbg(rule_name, first, last, dbg_attribute_type(attr_), ok_parse);
#endif
- ok_parse=parse_rhs(rhs, first, last, context, attr_, attr_
+ ok_parse = parse_rhs(rhs, first, last, context, attr_, attr_
, mpl::bool_
< ( RHS::has_action
&& !ExplicitAttrPropagation::value
@@ -336,11 +337,11 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
>()
);
}
- if(ok_parse)
+ if (ok_parse)
{
// do up-stream transformation, this integrates the results
// back into the original attribute value, if appropriate
- traits::post_transform(attr, attr_);
+ traits::post_transform(attr, std::forward<transform_attr>(attr_));
}
return ok_parse;
}
diff --git a/boost/spirit/home/x3/nonterminal/detail/transform_attribute.hpp b/boost/spirit/home/x3/nonterminal/detail/transform_attribute.hpp
index b1929f8993..88ba3ea5bb 100644
--- a/boost/spirit/home/x3/nonterminal/detail/transform_attribute.hpp
+++ b/boost/spirit/home/x3/nonterminal/detail/transform_attribute.hpp
@@ -10,6 +10,7 @@
#include <boost/spirit/home/x3/support/traits/transform_attribute.hpp>
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
+#include <utility>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace x3
@@ -23,9 +24,9 @@ namespace boost { namespace spirit { namespace x3
static Transformed pre(Exposed&) { return Transformed(); }
- static void post(Exposed& val, Transformed& attr)
+ static void post(Exposed& val, Transformed&& attr)
{
- traits::move_to(attr, val);
+ traits::move_to(std::forward<Transformed>(attr), val);
}
};
@@ -101,7 +102,8 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
template <typename Exposed, typename Transformed>
void post_transform(Exposed& dest, Transformed&& attr)
{
- return transform_attribute<Exposed, Transformed, x3::parser_id>::post(dest, attr);
+ return transform_attribute<Exposed, Transformed, x3::parser_id>
+ ::post(dest, std::forward<Transformed>(attr));
}
}}}}
diff --git a/boost/spirit/home/x3/nonterminal/simple_trace.hpp b/boost/spirit/home/x3/nonterminal/simple_trace.hpp
index dd369c811b..2b7969a71f 100644
--- a/boost/spirit/home/x3/nonterminal/simple_trace.hpp
+++ b/boost/spirit/home/x3/nonterminal/simple_trace.hpp
@@ -14,7 +14,7 @@
#include <boost/spirit/home/x3/nonterminal/debug_handler_state.hpp>
#include <boost/fusion/include/out.hpp>
#include <boost/type_traits/is_same.hpp>
-#include <ostream>
+#include <iostream>
// The stream to use for debug output
#if !defined(BOOST_SPIRIT_X3_DEBUG_OUT)
diff --git a/boost/spirit/home/x3/operator/detail/sequence.hpp b/boost/spirit/home/x3/operator/detail/sequence.hpp
index e54a8f6a9e..2c804cc78a 100644
--- a/boost/spirit/home/x3/operator/detail/sequence.hpp
+++ b/boost/spirit/home/x3/operator/detail/sequence.hpp
@@ -103,30 +103,30 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
}
};
- template <typename Parser, typename Attribute>
+ template <typename Parser, typename Attribute, bool pass_through>
struct pass_sequence_attribute_used :
- mpl::if_<
- traits::is_size_one_sequence<Attribute>
+ mpl::if_c<
+ (!pass_through && traits::is_size_one_sequence<Attribute>::value)
, pass_sequence_attribute_front<Attribute>
, pass_through_sequence_attribute<Attribute>>::type {};
- template <typename Parser, typename Attribute, typename Enable = void>
+ template <typename Parser, typename Attribute, bool pass_through = false, typename Enable = void>
struct pass_sequence_attribute :
mpl::if_<
fusion::result_of::empty<Attribute>
, pass_sequence_attribute_unused
- , pass_sequence_attribute_used<Parser, Attribute>>::type {};
+ , pass_sequence_attribute_used<Parser, Attribute, pass_through>>::type {};
- template <typename L, typename R, typename Attribute>
- struct pass_sequence_attribute<sequence<L, R>, Attribute>
+ template <typename L, typename R, typename Attribute, bool pass_through>
+ struct pass_sequence_attribute<sequence<L, R>, Attribute, pass_through>
: pass_through_sequence_attribute<Attribute> {};
template <typename Parser, typename Attribute>
struct pass_sequence_attribute_subject :
pass_sequence_attribute<typename Parser::subject_type, Attribute> {};
- template <typename Parser, typename Attribute>
- struct pass_sequence_attribute<Parser, Attribute
+ template <typename Parser, typename Attribute, bool pass_through>
+ struct pass_sequence_attribute<Parser, Attribute, pass_through
, typename enable_if_c<(Parser::is_pass_through_unary)>::type>
: pass_sequence_attribute_subject<Parser, Attribute> {};
@@ -150,8 +150,8 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
typedef typename fusion::result_of::end<Attribute>::type r_end;
typedef fusion::iterator_range<l_begin, l_end> l_part;
typedef fusion::iterator_range<l_end, r_end> r_part;
- typedef pass_sequence_attribute<L, l_part> l_pass;
- typedef pass_sequence_attribute<R, r_part> r_pass;
+ typedef pass_sequence_attribute<L, l_part, false> l_pass;
+ typedef pass_sequence_attribute<R, r_part, false> r_pass;
static l_part left(Attribute& s)
{
@@ -175,7 +175,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
typedef unused_type l_part;
typedef Attribute& r_part;
typedef pass_sequence_attribute_unused l_pass;
- typedef pass_sequence_attribute<R, Attribute> r_pass;
+ typedef pass_sequence_attribute<R, Attribute, true> r_pass;
static unused_type left(Attribute&)
{
@@ -195,7 +195,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
{
typedef Attribute& l_part;
typedef unused_type r_part;
- typedef pass_sequence_attribute<L, Attribute> l_pass;
+ typedef pass_sequence_attribute<L, Attribute, true> l_pass;
typedef pass_sequence_attribute_unused r_pass;
static Attribute& left(Attribute& s)
diff --git a/boost/spirit/home/x3/string/literal_string.hpp b/boost/spirit/home/x3/string/literal_string.hpp
index c562721b2e..5066fe18a9 100644
--- a/boost/spirit/home/x3/string/literal_string.hpp
+++ b/boost/spirit/home/x3/string/literal_string.hpp
@@ -70,10 +70,10 @@ namespace boost { namespace spirit { namespace x3
}
template <typename Char>
- literal_string<Char const*, char_encoding::standard, unused_type>
+ literal_string<std::basic_string<Char>, char_encoding::standard, unused_type>
lit(std::basic_string<Char> const& s)
{
- return { s.c_str() };
+ return { s };
}
}
@@ -97,10 +97,10 @@ namespace boost { namespace spirit { namespace x3
return { s };
}
- inline literal_string<wchar_t const*, char_encoding::standard_wide, unused_type>
+ inline literal_string<std::basic_string<wchar_t>, char_encoding::standard_wide, unused_type>
lit(std::basic_string<wchar_t> const& s)
{
- return { s.c_str() };
+ return { s };
}
}
@@ -125,10 +125,10 @@ namespace boost { namespace spirit { namespace x3
}
template <typename Char>
- literal_string<Char const*, char_encoding::ascii, unused_type>
+ literal_string<std::basic_string<Char>, char_encoding::ascii, unused_type>
lit(std::basic_string<Char> const& s)
{
- return { s.c_str() };
+ return { s };
}
}
@@ -153,10 +153,10 @@ namespace boost { namespace spirit { namespace x3
}
template <typename Char>
- literal_string<Char const*, char_encoding::iso8859_1, unused_type>
+ literal_string<std::basic_string<Char>, char_encoding::iso8859_1, unused_type>
lit(std::basic_string<Char> const& s)
{
- return { s.c_str() };
+ return { s };
}
}
diff --git a/boost/spirit/home/x3/string/symbols.hpp b/boost/spirit/home/x3/string/symbols.hpp
index 2d00944be2..1846c57bad 100644
--- a/boost/spirit/home/x3/string/symbols.hpp
+++ b/boost/spirit/home/x3/string/symbols.hpp
@@ -198,6 +198,7 @@ namespace boost { namespace spirit { namespace x3
}
private:
+
template <typename Iterator>
value_type* find_impl(Iterator begin, Iterator end)
{
@@ -213,13 +214,14 @@ namespace boost { namespace spirit { namespace x3
}
public:
+
template <typename Iterator, typename Context, typename Attribute>
bool parse(Iterator& first, Iterator const& last
, Context const& context, unused_type, Attribute& attr) const
{
x3::skip_over(first, last, context);
- if (value_type* val_ptr
+ if (value_type const* val_ptr
= lookup->find(first, last, get_case_compare<Encoding>(context)))
{
x3::traits::move_to(*val_ptr, attr);
diff --git a/boost/spirit/home/x3/support/ast/variant.hpp b/boost/spirit/home/x3/support/ast/variant.hpp
index 52e565d1d4..052e6e5f8a 100644
--- a/boost/spirit/home/x3/support/ast/variant.hpp
+++ b/boost/spirit/home/x3/support/ast/variant.hpp
@@ -214,6 +214,11 @@ namespace boost { namespace spirit { namespace x3
return var;
}
+ void swap(variant& rhs) BOOST_NOEXCEPT
+ {
+ var.swap(rhs.var);
+ }
+
variant_type var;
};
}}}
diff --git a/boost/spirit/home/x3/support/traits/container_traits.hpp b/boost/spirit/home/x3/support/traits/container_traits.hpp
index ed9213b68c..b05764969c 100644
--- a/boost/spirit/home/x3/support/traits/container_traits.hpp
+++ b/boost/spirit/home/x3/support/traits/container_traits.hpp
@@ -13,12 +13,11 @@
#include <boost/spirit/home/x3/support/unused.hpp>
#include <boost/detail/iterator.hpp>
#include <boost/fusion/include/deque.hpp>
-#include <boost/mpl/has_xxx.hpp>
-#include <boost/mpl/bool.hpp>
+#include <boost/tti/has_type.hpp>
+#include <boost/tti/has_member_function.hpp>
#include <boost/mpl/identity.hpp>
#include <vector>
-#include <map>
#include <string>
#include <iterator>
#include <algorithm>
@@ -31,20 +30,28 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
namespace detail
{
- BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type)
- BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator)
- BOOST_MPL_HAS_XXX_TRAIT_DEF(size_type)
- BOOST_MPL_HAS_XXX_TRAIT_DEF(reference)
+ BOOST_TTI_HAS_TYPE(value_type)
+ BOOST_TTI_HAS_TYPE(iterator)
+ BOOST_TTI_HAS_TYPE(size_type)
+ BOOST_TTI_HAS_TYPE(reference)
+ BOOST_TTI_HAS_TYPE(key_type)
+ BOOST_TTI_HAS_MEMBER_FUNCTION(reserve)
}
- template <typename T, typename Enable = void>
- struct is_container
- : mpl::bool_<
- detail::has_value_type<T>::value &&
- detail::has_iterator<T>::value &&
- detail::has_size_type<T>::value &&
- detail::has_reference<T>::value>
- {};
+ template <typename T>
+ using is_container = mpl::bool_<
+ detail::has_type_value_type<T>::value &&
+ detail::has_type_iterator<T>::value &&
+ detail::has_type_size_type<T>::value &&
+ detail::has_type_reference<T>::value>;
+
+ template <typename T>
+ using is_associative = mpl::bool_<
+ detail::has_type_key_type<T>::value>;
+
+ template <typename T>
+ using is_reservable = mpl::bool_<
+ detail::has_member_function_reserve<T, void, mpl::vector<size_t>>::value>;
///////////////////////////////////////////////////////////////////////////
namespace detail
@@ -112,22 +119,10 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
template <typename Container, typename Enable = void>
struct push_back_container
{
- template <typename Key, typename Value, typename Compare, typename Allocator, typename T>
- static void push_back(std::map<Key, Value, Compare, Allocator>& c, T&& val)
- {
- c.insert(std::move(val));
- }
-
- template <typename Container_, typename T>
- static void push_back(Container_& c, T&& val)
- {
- c.push_back(std::move(val));
- }
-
template <typename T>
static bool call(Container& c, T&& val)
{
- push_back(c, std::move(val));
+ c.insert(c.end(), std::move(val));
return true;
}
};
@@ -145,7 +140,7 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
}
template <typename T>
- inline bool push_back(unused_type, T const&)
+ inline bool push_back(unused_type, T&&)
{
return true;
}
@@ -162,27 +157,37 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
template <typename Container, typename Enable = void>
struct append_container
{
- // Not all containers have "reserve"
- template <typename Container_>
- static void reserve(Container_& c, std::size_t size) {}
+ private:
+ template <typename Iterator>
+ static void reserve(Container& c, Iterator first, Iterator last, mpl::false_)
+ {
+ // Not all containers have "reserve"
+ }
+
+ template <typename Iterator>
+ static void reserve(Container& c, Iterator first, Iterator last, mpl::true_)
+ {
+ c.reserve(c.size() + std::distance(first, last));
+ }
- template <typename T, typename Allocator>
- static void reserve(std::vector<T, Allocator>& c, std::size_t size)
+ template <typename Iterator>
+ static void insert(Container& c, Iterator first, Iterator last, mpl::false_)
{
- c.reserve(size);
+ c.insert(c.end(), first, last);
}
-
- template <typename Container_, typename Iterator>
- static void insert(Container_& c, Iterator first, Iterator last)
+
+ template <typename Iterator>
+ static void insert(Container& c, Iterator first, Iterator last, mpl::true_)
{
- std::copy(first, last, std::inserter(c, c.end()));
+ c.insert(first, last);
}
+ public:
template <typename Iterator>
static bool call(Container& c, Iterator first, Iterator last)
{
- reserve(c, c.size() + std::distance(first, last));
- insert(c, first, last);
+ reserve(c, first, last, is_reservable<Container>{});
+ insert(c, first, last, is_associative<Container>{});
return true;
}
};
diff --git a/boost/spirit/home/x3/support/traits/move_to.hpp b/boost/spirit/home/x3/support/traits/move_to.hpp
index fd3d59d7e2..2e3665bd0b 100644
--- a/boost/spirit/home/x3/support/traits/move_to.hpp
+++ b/boost/spirit/home/x3/support/traits/move_to.hpp
@@ -23,7 +23,19 @@
namespace boost { namespace spirit { namespace x3 { namespace traits
{
template <typename Source, typename Dest>
- void move_to(Source&& src, Dest& dest);
+ inline void move_to(Source&& src, Dest& dest);
+
+ template <typename T>
+ inline void move_to(T& src, T& dest);
+
+ template <typename T>
+ inline void move_to(T const& src, T& dest);
+
+ template <typename T>
+ inline void move_to(T&& src, T& dest);
+
+ template <typename Iterator, typename Dest>
+ inline void move_to(Iterator first, Iterator last, Dest& dest);
template <typename Dest>
inline void move_to(unused_type, Dest&) {}
@@ -33,10 +45,6 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
inline void move_to(unused_type, unused_type) {}
- template <typename Iterator, typename Dest>
- void
- move_to(Iterator first, Iterator last, Dest& dest);
-
template <typename Iterator>
inline void
move_to(Iterator, Iterator, unused_type) {}
@@ -70,7 +78,7 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
is_size_one_sequence<Source> >
is_single_element_sequence;
- move_to_plain(std::move(src), dest, is_single_element_sequence);
+ move_to_plain(std::forward<Source>(src), dest, is_single_element_sequence);
}
template <typename Source, typename Dest>
@@ -88,7 +96,7 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
>::type
move_to(Source&& src, Dest& dest, tuple_attribute)
{
- fusion::move(std::move(src), dest);
+ fusion::move(std::forward<Source>(src), dest);
}
template <typename Source, typename Dest>
@@ -97,7 +105,7 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
>::type
move_to(Source&& src, Dest& dest, tuple_attribute)
{
- traits::move_to(src, fusion::front(dest));
+ traits::move_to(std::forward<Source>(src), fusion::front(dest));
}
template <typename Source, typename Dest>
@@ -167,8 +175,7 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
}
template <typename Source, typename Dest>
- inline void
- move_to(Source&& src, Dest& dest)
+ inline void move_to(Source&& src, Dest& dest)
{
detail::move_to(std::move(src), dest
, typename attribute_category<Dest>::type());
@@ -191,13 +198,12 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
template <typename T>
inline void move_to(T&& src, T& dest)
{
- if (&src != &dest)
+ if (boost::addressof(src) != boost::addressof(dest))
dest = std::move(src);
}
template <typename Iterator, typename Dest>
- inline void
- move_to(Iterator first, Iterator last, Dest& dest)
+ inline void move_to(Iterator first, Iterator last, Dest& dest)
{
// $$$ Use std::move_iterator when iterator is not a const-iterator $$$
detail::move_to(first, last, dest, typename attribute_category<Dest>::type());
diff --git a/boost/test/data/for_each_sample.hpp b/boost/test/data/for_each_sample.hpp
index 8bc1964311..b3bc1ffc78 100644
--- a/boost/test/data/for_each_sample.hpp
+++ b/boost/test/data/for_each_sample.hpp
@@ -14,10 +14,14 @@
// Boost.Test
#include <boost/test/data/config.hpp>
-#include <boost/test/data/traits.hpp>
#include <boost/test/data/size.hpp>
+#include <boost/test/data/index_sequence.hpp>
+#include <boost/test/data/monomorphic/sample_merge.hpp>
#include <boost/test/data/monomorphic/fwd.hpp>
+// STL
+#include <tuple>
+
#include <boost/test/detail/suppress_warnings.hpp>
// needed for std::min
@@ -30,12 +34,48 @@ namespace unit_test {
namespace data {
// ************************************************************************** //
+// ************** data::invoke_action ************** //
+// ************************************************************************** //
+
+template<typename Action, typename T>
+inline void
+invoke_action( Action const& action, T && arg, std::false_type /* is_tuple */ )
+{
+ action( std::forward<T>(arg) );
+}
+
+//____________________________________________________________________________//
+
+template<typename Action, typename T, std::size_t ...I>
+inline void
+invoke_action_impl( Action const& action,
+ T && args,
+ index_sequence<I...> const& )
+{
+ action( std::get<I>(std::forward<T>(args))... );
+}
+
+//____________________________________________________________________________//
+
+template<typename Action, typename T>
+inline void
+invoke_action( Action const& action, T&& args, std::true_type /* is_tuple */ )
+{
+ invoke_action_impl( action,
+ std::forward<T>(args),
+ typename make_index_sequence< 0, std::tuple_size<T>::value >::type{} );
+
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
// ************** for_each_sample ************** //
// ************************************************************************** //
template<typename DataSet, typename Action>
inline typename std::enable_if<monomorphic::is_dataset<DataSet>::value,void>::type
-for_each_sample( DataSet const& samples,
+for_each_sample( DataSet && samples,
Action const& act,
data::size_t number_of_samples = BOOST_TEST_DS_INFINITE_SIZE )
{
@@ -45,7 +85,9 @@ for_each_sample( DataSet const& samples,
auto it = samples.begin();
while( size-- > 0 ) {
- data::traits<typename DataSet::sample>::invoke_action( *it, act );
+ invoke_action( act,
+ *it,
+ typename monomorphic::ds_detail::is_tuple<decltype(*it)>::type());
++it;
}
}
@@ -54,11 +96,13 @@ for_each_sample( DataSet const& samples,
template<typename DataSet, typename Action>
inline typename std::enable_if<!monomorphic::is_dataset<DataSet>::value,void>::type
-for_each_sample( DataSet const& samples,
+for_each_sample( DataSet && samples,
Action const& act,
data::size_t number_of_samples = BOOST_TEST_DS_INFINITE_SIZE )
{
- data::for_each_sample( data::make( samples ), act, number_of_samples );
+ data::for_each_sample( data::make( std::forward<DataSet>(samples) ),
+ act,
+ number_of_samples );
}
} // namespace data
diff --git a/boost/test/data/index_sequence.hpp b/boost/test/data/index_sequence.hpp
new file mode 100644
index 0000000000..21af7e504c
--- /dev/null
+++ b/boost/test/data/index_sequence.hpp
@@ -0,0 +1,62 @@
+// (C) Copyright Gennadiy Rozental 2001.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/test for the library home page.
+//
+/// @file
+/// Defines c++14 index_sequence implementation
+// ***************************************************************************
+
+#ifndef BOOST_TEST_DATA_INDEX_SEQUENCE_HPP
+#define BOOST_TEST_DATA_INDEX_SEQUENCE_HPP
+
+// Boost.Test
+#include <boost/test/data/config.hpp>
+
+#include <boost/test/detail/suppress_warnings.hpp>
+
+//____________________________________________________________________________//
+
+namespace boost {
+namespace unit_test {
+namespace data {
+
+// ************************************************************************** //
+// ************** data::index_sequence ************** //
+// ************************************************************************** //
+
+template <std::size_t... Ns>
+struct index_sequence {};
+
+template<typename IS1, typename IS2>
+struct merge_index_sequence;
+
+template <std::size_t... Ns1, std::size_t... Ns2>
+struct merge_index_sequence<index_sequence<Ns1...>, index_sequence<Ns2...>> {
+ typedef index_sequence<Ns1..., Ns2...> type;
+};
+
+template <std::size_t B, std::size_t E, typename Enabler = void>
+struct make_index_sequence {
+ typedef typename merge_index_sequence<typename make_index_sequence<B,(B+E)/2>::type,
+ typename make_index_sequence<(B+E)/2,E>::type>::type type;
+};
+
+template <std::size_t B, std::size_t E>
+struct make_index_sequence<B,E,typename std::enable_if<E==B+1,void>::type> {
+ typedef index_sequence<B> type;
+};
+
+template <typename... T>
+using index_sequence_for = typename make_index_sequence<0, sizeof...(T)>::type;
+
+} // namespace data
+} // namespace unit_test
+} // namespace boost
+
+#include <boost/test/detail/enable_warnings.hpp>
+
+#endif // BOOST_TEST_DATA_INDEX_SEQUENCE_HPP
+
diff --git a/boost/test/data/monomorphic/fwd.hpp b/boost/test/data/monomorphic/fwd.hpp
index 26c36743df..cf6d3b0000 100644
--- a/boost/test/data/monomorphic/fwd.hpp
+++ b/boost/test/data/monomorphic/fwd.hpp
@@ -24,6 +24,9 @@
#include <boost/type_traits/is_array.hpp>
#include <boost/mpl/bool.hpp>
+// STL
+#include <tuple>
+
#include <boost/test/detail/suppress_warnings.hpp>
// STL
diff --git a/boost/test/data/monomorphic/grid.hpp b/boost/test/data/monomorphic/grid.hpp
index 6af906c62c..3e1b36abad 100644
--- a/boost/test/data/monomorphic/grid.hpp
+++ b/boost/test/data/monomorphic/grid.hpp
@@ -19,8 +19,8 @@
#if !defined(BOOST_TEST_NO_GRID_COMPOSITION_AVAILABLE) || defined(BOOST_TEST_DOXYGEN_DOC__)
-#include <boost/test/data/traits.hpp>
#include <boost/test/data/monomorphic/fwd.hpp>
+#include <boost/test/data/monomorphic/sample_merge.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
@@ -31,53 +31,6 @@ namespace unit_test {
namespace data {
namespace monomorphic {
-namespace ds_detail {
-
-// !! ?? variadic template implementation; use forward_as_tuple?
-template<typename T1, typename T2>
-struct grid_traits {
- typedef std::tuple<T1,T2> type;
- typedef typename data::traits<type>::ref_type ref_type;
-
- static ref_type
- tuple_merge(T1 const& a1, T2 const& a2)
- {
- return ref_type(a1,a2);
- }
-};
-
-//____________________________________________________________________________//
-
-template<typename T1, typename T2,typename T3>
-struct grid_traits<T1,std::tuple<T2,T3>> {
- typedef std::tuple<T1,T2,T3> type;
- typedef typename data::traits<type>::ref_type ref_type;
-
- static ref_type
- tuple_merge(T1 const& a1, std::tuple<T2 const&,T3 const&> const& a2)
- {
- return ref_type(a1,get<0>(a2),get<1>(a2));
- }
-};
-
-//____________________________________________________________________________//
-
-template<typename T1, typename T2,typename T3>
-struct grid_traits<std::tuple<T1,T2>,T3> {
- typedef std::tuple<T1,T2,T3> type;
- typedef typename data::traits<type>::ref_type ref_type;
-
- static ref_type
- tuple_merge(std::tuple<T1 const&,T2 const&> const& a1, T3 const& a2)
- {
- return ref_type(get<0>(a1),get<1>(a1),a2);
- }
-};
-
-//____________________________________________________________________________//
-
-} // namespace ds_detail
-
// ************************************************************************** //
// ************** grid ************** //
// ************************************************************************** //
@@ -88,21 +41,15 @@ struct grid_traits<std::tuple<T1,T2>,T3> {
//! The arity of the resulting dataset is the sum of the arity of its operands.
template<typename DataSet1, typename DataSet2>
class grid {
- typedef typename boost::decay<DataSet1>::type dataset1_decay;
- typedef typename boost::decay<DataSet2>::type dataset2_decay;
-
- typedef typename dataset1_decay::iterator dataset1_iter;
- typedef typename dataset2_decay::iterator dataset2_iter;
+ typedef typename boost::decay<DataSet1>::type dataset1_decay;
+ typedef typename boost::decay<DataSet2>::type dataset2_decay;
- typedef typename dataset1_decay::sample sample1;
- typedef typename dataset2_decay::sample sample2;
+ typedef typename dataset1_decay::iterator dataset1_iter;
+ typedef typename dataset2_decay::iterator dataset2_iter;
public:
- typedef typename ds_detail::grid_traits<sample1,sample2>::type sample;
struct iterator {
- typedef typename data::traits<sample>::ref_type ref_type;
-
// Constructor
explicit iterator( dataset1_iter iter1, DataSet2 const& ds2 )
: m_iter1( std::move( iter1 ) )
@@ -111,8 +58,14 @@ public:
, m_ds2_pos( 0 )
{}
+ using iterator_sample = decltype(
+ sample_merge( *std::declval<dataset1_iter>(),
+ *std::declval<dataset2_iter>()) );
+
// forward iterator interface
- ref_type operator*() const { return ds_detail::grid_traits<sample1,sample2>::tuple_merge( *m_iter1, *m_iter2 ); }
+ auto operator*() const -> iterator_sample {
+ return sample_merge( *m_iter1, *m_iter2 );
+ }
void operator++()
{
++m_ds2_pos;
diff --git a/boost/test/data/monomorphic/sample_merge.hpp b/boost/test/data/monomorphic/sample_merge.hpp
new file mode 100644
index 0000000000..d7535beff7
--- /dev/null
+++ b/boost/test/data/monomorphic/sample_merge.hpp
@@ -0,0 +1,103 @@
+// (C) Copyright Gennadiy Rozental 2001.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/test for the library home page.
+//
+/// @file
+/// Defines helper routines and types for merging monomorphic samples
+// ***************************************************************************
+
+#ifndef BOOST_TEST_DATA_MONOMORPHIC_SAMPLE_MERGE_HPP
+#define BOOST_TEST_DATA_MONOMORPHIC_SAMPLE_MERGE_HPP
+
+// Boost.Test
+#include <boost/test/data/config.hpp>
+#include <boost/test/data/index_sequence.hpp>
+
+#include <boost/test/data/monomorphic/fwd.hpp>
+
+#include <boost/test/detail/suppress_warnings.hpp>
+
+namespace boost {
+namespace unit_test {
+namespace data {
+namespace monomorphic {
+
+//____________________________________________________________________________//
+
+namespace ds_detail {
+
+template <class T>
+struct is_tuple : std::false_type {};
+
+template <class ...T>
+struct is_tuple<std::tuple<T...>> : std::true_type {};
+
+template <class T>
+struct is_tuple<T&&> : is_tuple<typename std::decay<T>::type> {};
+
+template <class T>
+struct is_tuple<T&> : is_tuple<typename std::decay<T>::type> {};
+
+template<typename T>
+inline auto as_tuple_impl_xvalues( T const & arg, std::false_type /* is_rvalue_ref */ )
+ -> decltype(std::tuple<T const&>(arg)) {
+ //return std::tuple<T const&>(arg);
+ return std::forward_as_tuple(arg);
+}
+
+template<typename T>
+inline auto as_tuple_impl_xvalues( T && arg, std::true_type /* is_rvalue_ref */ )
+ -> decltype(std::make_tuple(std::forward<T>(arg))) {
+ return std::make_tuple(std::forward<T>(arg));
+}
+
+
+template<typename T>
+inline auto as_tuple_impl( T && arg, std::false_type /* is_tuple = nullptr */ )
+ -> decltype(as_tuple_impl_xvalues(std::forward<T>(arg),
+ typename std::is_rvalue_reference<T&&>::type())) {
+ return as_tuple_impl_xvalues(std::forward<T>(arg),
+ typename std::is_rvalue_reference<T&&>::type());
+}
+
+//____________________________________________________________________________//
+
+template<typename T>
+inline T &&
+as_tuple_impl(T && arg, std::true_type /* is_tuple */ ) {
+ return std::forward<T>(arg);
+}
+
+template<typename T>
+inline auto as_tuple( T && arg )
+ -> decltype( as_tuple_impl(std::forward<T>(arg),
+ typename ds_detail::is_tuple<T>::type()) ) {
+ return as_tuple_impl(std::forward<T>(arg),
+ typename ds_detail::is_tuple<T>::type());
+}
+
+//____________________________________________________________________________//
+
+} // namespace ds_detail
+
+template<typename T1, typename T2>
+inline auto
+sample_merge( T1 && a1, T2 && a2 )
+ -> decltype( std::tuple_cat(ds_detail::as_tuple(std::forward<T1>(a1)),
+ ds_detail::as_tuple(std::forward<T2>(a2)) ) ) {
+ return std::tuple_cat(ds_detail::as_tuple(std::forward<T1>(a1)),
+ ds_detail::as_tuple(std::forward<T2>(a2)));
+}
+
+} // namespace monomorphic
+} // namespace data
+} // namespace unit_test
+} // namespace boost
+
+#include <boost/test/detail/enable_warnings.hpp>
+
+#endif // BOOST_TEST_DATA_MONOMORPHIC_SAMPLE_MERGE_HPP
+
diff --git a/boost/test/data/monomorphic/zip.hpp b/boost/test/data/monomorphic/zip.hpp
index 1c7f46472c..5fc65d0e20 100644
--- a/boost/test/data/monomorphic/zip.hpp
+++ b/boost/test/data/monomorphic/zip.hpp
@@ -17,8 +17,8 @@
#if !defined(BOOST_TEST_NO_ZIP_COMPOSITION_AVAILABLE) || defined(BOOST_TEST_DOXYGEN_DOC__)
-#include <boost/test/data/traits.hpp>
#include <boost/test/data/monomorphic/fwd.hpp>
+#include <boost/test/data/monomorphic/sample_merge.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
@@ -28,51 +28,6 @@ namespace unit_test {
namespace data {
namespace monomorphic {
-namespace ds_detail {
-
-// !! ?? variadic template implementation; use forward_as_tuple?
-template<typename T1, typename T2>
-struct zip_traits {
- typedef std::tuple<T1,T2> type;
- typedef typename data::traits<type>::ref_type ref_type;
-
- static ref_type
- tuple_merge(T1 const& a1, T2 const& a2)
- {
- return ref_type(a1,a2);
- }
-};
-
-//____________________________________________________________________________//
-
-template<typename T1, typename T2,typename T3>
-struct zip_traits<T1,std::tuple<T2,T3>> {
- typedef std::tuple<T1,T2,T3> type;
- typedef typename data::traits<type>::ref_type ref_type;
-
- static ref_type
- tuple_merge(T1 const& a1, std::tuple<T2 const&,T3 const&> const& a2)
- {
- return ref_type(a1,std::get<0>(a2),std::get<1>(a2));
- }
-};
-
-//____________________________________________________________________________//
-
-template<typename T1, typename T2,typename T3>
-struct zip_traits<std::tuple<T1,T2>,T3> {
- typedef std::tuple<T1,T2,T3> type;
- typedef typename data::traits<type>::ref_type ref_type;
-
- static ref_type
- tuple_merge(std::tuple<T1 const&,T2 const&> const& a1, T3 const& a2)
- {
- return ref_type(std::get<0>(a1),std::get<1>(a1),a2);
- }
-};
-
-} // namespace ds_detail
-
// ************************************************************************** //
// ************** zip ************** //
// ************************************************************************** //
@@ -89,25 +44,24 @@ class zip {
typedef typename dataset1_decay::iterator dataset1_iter;
typedef typename dataset2_decay::iterator dataset2_iter;
- typedef typename dataset1_decay::sample sample1;
- typedef typename dataset2_decay::sample sample2;
-
public:
- typedef typename ds_detail::zip_traits<sample1,sample2>::type sample;
-
enum { arity = dataset1_decay::arity + dataset2_decay::arity };
struct iterator {
- typedef typename data::traits<sample>::ref_type ref_type;
-
// Constructor
explicit iterator( dataset1_iter iter1, dataset2_iter iter2 )
: m_iter1( std::move( iter1 ) )
, m_iter2( std::move( iter2 ) )
{}
+ using iterator_sample = decltype(
+ sample_merge( *std::declval<dataset1_iter>(),
+ *std::declval<dataset2_iter>()) );
+
// forward iterator interface
- ref_type operator*() const { return ds_detail::zip_traits<sample1,sample2>::tuple_merge( *m_iter1, *m_iter2 ); }
+ auto operator*() const -> iterator_sample {
+ return sample_merge( *m_iter1, *m_iter2 );
+ }
void operator++() { ++m_iter1; ++m_iter2; }
private:
@@ -116,6 +70,8 @@ public:
dataset2_iter m_iter2;
};
+ typedef typename iterator::iterator_sample sample;
+
//! Constructor
//!
//! The datasets are moved and not copied.
diff --git a/boost/test/data/test_case.hpp b/boost/test/data/test_case.hpp
index 112be06c54..9564816ee4 100644
--- a/boost/test/data/test_case.hpp
+++ b/boost/test/data/test_case.hpp
@@ -33,9 +33,16 @@
#include <boost/bind.hpp>
+#include <boost/type_traits/is_copy_constructible.hpp>
+
#include <boost/test/detail/suppress_warnings.hpp>
#include <boost/test/tools/detail/print_helper.hpp>
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) \
+ && !defined(BOOST_TEST_DATASET_MAX_ARITY)
+# define BOOST_TEST_DATASET_MAX_ARITY 10
+#endif
+
//____________________________________________________________________________//
namespace boost {
@@ -57,6 +64,53 @@ struct seed {
}
};
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
+ !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_CXX11_DECLTYPE) && \
+ !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && \
+ !defined(BOOST_NO_CXX11_SMART_PTR)
+
+#define BOOST_TEST_DATASET_VARIADIC
+template <class T>
+struct parameter_holder {
+ std::shared_ptr<T> value;
+
+ parameter_holder(T && value_)
+ : value(std::make_shared<T>(std::move(value_)))
+ {}
+
+ operator T const&() const {
+ return *value;
+ }
+};
+
+template <class T>
+parameter_holder<typename std::remove_reference<T>::type>
+boost_bind_rvalue_holder_helper_impl(T&& value, boost::false_type /* is copy constructible */) {
+ return parameter_holder<typename std::remove_reference<T>::type>(std::forward<T>(value));
+}
+
+template <class T>
+T&& boost_bind_rvalue_holder_helper_impl(T&& value, boost::true_type /* is copy constructible */) {
+ return std::forward<T>(value);
+}
+
+template <class T>
+auto boost_bind_rvalue_holder_helper(T&& value)
+ -> decltype(boost_bind_rvalue_holder_helper_impl(
+ std::forward<T>(value),
+ typename boost::is_copy_constructible<typename std::remove_reference<T>::type>::type()))
+{
+ // need to use boost::is_copy_constructible because std::is_copy_constructible is broken on MSVC12
+ return boost_bind_rvalue_holder_helper_impl(
+ std::forward<T>(value),
+ typename boost::is_copy_constructible<typename std::remove_reference<T>::type>::type());
+}
+
+#endif
+
+
// ************************************************************************** //
// ************** test_case_gen ************** //
// ************************************************************************** //
@@ -94,7 +148,8 @@ public:
return res;
}
- // !! ?? variadics based implementation
+#if !defined(BOOST_TEST_DATASET_VARIADIC)
+ /// make this variadic
#define TC_MAKE(z,arity,_) \
template<BOOST_PP_ENUM_PARAMS(arity, typename Arg)> \
void operator()( BOOST_PP_ENUM_BINARY_PARAMS(arity, Arg, const& arg) ) const \
@@ -104,7 +159,20 @@ public:
BOOST_PP_ENUM_PARAMS(arity, arg) ) ) ); \
} \
- BOOST_PP_REPEAT_FROM_TO(1, 4, TC_MAKE, _)
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_TEST_DATASET_MAX_ARITY, TC_MAKE, _)
+#else
+
+ template<typename ...Arg>
+ void operator()(Arg&& ... arg) const
+ {
+ m_test_cases.push_back(
+ new test_case( m_tc_name,
+ m_tc_file,
+ m_tc_line,
+ boost::bind( &TestCase::template test_method<Arg...>,
+ boost_bind_rvalue_holder_helper(std::forward<Arg>(arg))...)));
+ }
+#endif
private:
// Data members
@@ -148,18 +216,22 @@ make_test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_l
BOOST_PP_SEQ_FOR_EACH_I(BOOST_DATA_TEST_CASE_PARAM, _, params)) \
/**/
-#define BOOST_DATA_TEST_CASE_IMPL( arity, test_name, dataset, params ) \
-struct test_name { \
+#define BOOST_DATA_TEST_CASE_IMPL(arity, F, test_name, dataset, params) \
+struct test_name : public F { \
template<BOOST_PP_ENUM_PARAMS(arity, typename Arg)> \
static void test_method( BOOST_DATA_TEST_CASE_PARAMS( params ) ) \
{ \
+ BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture entry.");\
+ test_name t; \
+ BOOST_TEST_CHECKPOINT('"' << #test_name << "\" entry."); \
BOOST_TEST_CONTEXT( "" \
BOOST_PP_SEQ_FOR_EACH(BOOST_DATA_TEST_CONTEXT, _, params)) \
- _impl(BOOST_PP_SEQ_ENUM(params)); \
+ t._impl(BOOST_PP_SEQ_ENUM(params)); \
+ BOOST_TEST_CHECKPOINT('"' << #test_name << "\" exit."); \
} \
private: \
template<BOOST_PP_ENUM_PARAMS(arity, typename Arg)> \
- static void _impl(BOOST_DATA_TEST_CASE_PARAMS( params )); \
+ void _impl(BOOST_DATA_TEST_CASE_PARAMS( params )); \
}; \
\
BOOST_AUTO_TU_REGISTRAR( test_name )( \
@@ -173,13 +245,13 @@ BOOST_AUTO_TU_REGISTRAR( test_name )( \
void test_name::_impl( BOOST_DATA_TEST_CASE_PARAMS( params ) ) \
/**/
-#define BOOST_DATA_TEST_CASE_WITH_PARAMS( test_name, dataset, ... ) \
+#define BOOST_DATA_TEST_CASE_WITH_PARAMS( F, test_name, dataset, ... ) \
BOOST_DATA_TEST_CASE_IMPL( BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), \
- test_name, dataset, \
+ F, test_name, dataset, \
BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__) ) \
/**/
-#define BOOST_DATA_TEST_CASE_NO_PARAMS( test_name, dataset ) \
- BOOST_DATA_TEST_CASE_WITH_PARAMS( test_name, dataset, sample ) \
+#define BOOST_DATA_TEST_CASE_NO_PARAMS( F, test_name, dataset ) \
+ BOOST_DATA_TEST_CASE_WITH_PARAMS( F, test_name, dataset, sample ) \
/**/
#if BOOST_PP_VARIADICS_MSVC
@@ -188,14 +260,32 @@ BOOST_AUTO_TU_REGISTRAR( test_name )( \
BOOST_PP_CAT( \
BOOST_PP_IIF(BOOST_PP_EQUAL(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__),2), \
BOOST_DATA_TEST_CASE_NO_PARAMS, \
- BOOST_DATA_TEST_CASE_WITH_PARAMS) (__VA_ARGS__), ) \
+ BOOST_DATA_TEST_CASE_WITH_PARAMS) ( \
+ BOOST_AUTO_TEST_CASE_FIXTURE, __VA_ARGS__), ) \
+/**/
+
+#define BOOST_DATA_TEST_CASE_F( F, ... ) \
+ BOOST_PP_CAT( \
+ BOOST_PP_IIF(BOOST_PP_EQUAL(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__),2), \
+ BOOST_DATA_TEST_CASE_NO_PARAMS, \
+ BOOST_DATA_TEST_CASE_WITH_PARAMS) ( \
+ F, __VA_ARGS__), ) \
/**/
+
#else
#define BOOST_DATA_TEST_CASE( ... ) \
BOOST_PP_IIF(BOOST_PP_EQUAL(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__),2), \
BOOST_DATA_TEST_CASE_NO_PARAMS, \
- BOOST_DATA_TEST_CASE_WITH_PARAMS) (__VA_ARGS__) \
+ BOOST_DATA_TEST_CASE_WITH_PARAMS) ( \
+ BOOST_AUTO_TEST_CASE_FIXTURE, __VA_ARGS__) \
+/**/
+
+#define BOOST_DATA_TEST_CASE_F( F, ... ) \
+ BOOST_PP_IIF(BOOST_PP_EQUAL(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__),2), \
+ BOOST_DATA_TEST_CASE_NO_PARAMS, \
+ BOOST_DATA_TEST_CASE_WITH_PARAMS) ( \
+ F, __VA_ARGS__) \
/**/
#endif
diff --git a/boost/test/data/traits.hpp b/boost/test/data/traits.hpp
deleted file mode 100644
index eee52fdab5..0000000000
--- a/boost/test/data/traits.hpp
+++ /dev/null
@@ -1,87 +0,0 @@
-// (C) Copyright Gennadiy Rozental 2001.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-// See http://www.boost.org/libs/test for the library home page.
-//
-/// @file
-/// Defines helper traits
-// ***************************************************************************
-
-#ifndef BOOST_TEST_DATA_TRAITS_HPP_102211GER
-#define BOOST_TEST_DATA_TRAITS_HPP_102211GER
-
-// Boost.Test
-#include <boost/test/data/config.hpp>
-#include <boost/test/data/monomorphic/fwd.hpp>
-
-// STL
-#include <tuple>
-
-#include <boost/test/detail/suppress_warnings.hpp>
-
-//____________________________________________________________________________//
-
-namespace boost {
-namespace unit_test {
-namespace data {
-
-// ************************************************************************** //
-// ************** data::traits ************** //
-// ************************************************************************** //
-
-template<typename T>
-struct traits {
- // type of the reference to sample returned by iterator
- typedef T const& ref_type;
-
- template<typename Action>
- static void
- invoke_action( ref_type arg, Action const& action )
- {
- action( arg );
- }
-};
-
-//____________________________________________________________________________//
-
-// !! ?? reimplement using variadics
-template<typename T1, typename T2>
-struct traits<std::tuple<T1,T2>> {
- // type of the reference to sample returned by iterator
- typedef std::tuple<T1 const&,T2 const&> ref_type;
-
- template<typename Action>
- static void
- invoke_action( ref_type arg, Action const& action )
- {
- action( std::get<0>(arg), std::get<1>(arg) );
- }
-};
-
-//____________________________________________________________________________//
-
-template<typename T1, typename T2, typename T3>
-struct traits<std::tuple<T1,T2,T3>> {
- // type of the reference to sample returned by iterator
- typedef std::tuple<T1 const&,T2 const&,T3 const&> ref_type;
-
- template<typename Action>
- static void
- invoke_action( ref_type arg, Action const& action )
- {
- action( std::get<0>(arg), std::get<1>(arg), std::get<2>(arg) );
- }
-};
-
-//____________________________________________________________________________//
-
-} // namespace data
-} // namespace unit_test
-} // namespace boost
-
-#include <boost/test/detail/enable_warnings.hpp>
-
-#endif // BOOST_TEST_DATA_TRAITS_HPP_102211GER
-
diff --git a/boost/test/impl/debug.ipp b/boost/test/impl/debug.ipp
index f4ee4971ce..f547052ded 100644
--- a/boost/test/impl/debug.ipp
+++ b/boost/test/impl/debug.ipp
@@ -752,6 +752,29 @@ set_debugger( unit_test::const_string, dbg_starter )
// ************** attach debugger to the current process ************** //
// ************************************************************************** //
+#if defined(BOOST_WIN32_BASED_DEBUG)
+
+struct safe_handle_helper
+{
+ HANDLE& handle;
+ safe_handle_helper(HANDLE &handle_) : handle(handle_) {}
+
+ void close_handle()
+ {
+ if( handle != INVALID_HANDLE_VALUE )
+ {
+ ::CloseHandle( handle );
+ handle = INVALID_HANDLE_VALUE;
+ }
+ }
+
+ ~safe_handle_helper()
+ {
+ close_handle();
+ }
+};
+#endif
+
bool
attach_debugger( bool break_or_continue )
{
@@ -781,6 +804,8 @@ attach_debugger( bool break_or_continue )
if( !dbg_init_done_ev )
return false;
+
+ safe_handle_helper safe_handle_obj( dbg_init_done_ev );
// *************************************************** //
// Debugger command line format
@@ -797,17 +822,20 @@ attach_debugger( bool break_or_continue )
DWORD format_size = MAX_CMD_LINE;
DWORD type = REG_SZ;
- if( !s_info.m_reg_query_value || (*s_info.m_reg_query_value)(
+ bool b_read_key = s_info.m_reg_query_value &&
+ ((*s_info.m_reg_query_value)(
reg_key, // handle of open key
"Debugger", // name of subkey to query
0, // reserved
&type, // value type
(LPBYTE)format, // buffer for returned string
- &format_size ) != ERROR_SUCCESS ) // in: buffer size; out: actual size of returned string
- return false;
+ &format_size ) == ERROR_SUCCESS ); // in: buffer size; out: actual size of returned string
if( !s_info.m_reg_close_key || (*s_info.m_reg_close_key)( reg_key ) != ERROR_SUCCESS )
return false;
+
+ if( !b_read_key )
+ return false;
// *************************************************** //
// Debugger command line
@@ -841,12 +869,16 @@ attach_debugger( bool break_or_continue )
&debugger_info // pointer to PROCESS_INFORMATION that will contain the new process identification
);
+ bool debugger_run_ok = false;
if( created )
- ::WaitForSingleObject( dbg_init_done_ev, INFINITE );
+ {
+ DWORD ret_code = ::WaitForSingleObject( dbg_init_done_ev, INFINITE );
+ debugger_run_ok = ( ret_code == WAIT_OBJECT_0 );
+ }
- ::CloseHandle( dbg_init_done_ev );
+ safe_handle_obj.close_handle();
- if( !created )
+ if( !created || !debugger_run_ok )
return false;
if( break_or_continue )
diff --git a/boost/test/impl/execution_monitor.ipp b/boost/test/impl/execution_monitor.ipp
index b3e873efbe..f7fc8ea4e2 100644
--- a/boost/test/impl/execution_monitor.ipp
+++ b/boost/test/impl/execution_monitor.ipp
@@ -1137,6 +1137,8 @@ execution_monitor::catch_signals( boost::function<int ()> const& F )
detail::system_signal_exception SSE( this );
int ret_val = 0;
+ // clang windows workaround: this not available in __finally scope
+ bool l_catch_system_errors = p_catch_system_errors;
__try {
__try {
@@ -1147,7 +1149,7 @@ execution_monitor::catch_signals( boost::function<int ()> const& F )
}
}
__finally {
- if( p_catch_system_errors ) {
+ if( l_catch_system_errors ) {
BOOST_TEST_CRT_SET_HOOK( old_crt_hook );
_set_invalid_parameter_handler( old_iph );
@@ -1380,8 +1382,8 @@ enable( unsigned mask )
return ~old_cw & BOOST_FPE_ALL;
#elif defined(__GLIBC__) && defined(__USE_GNU) && !defined(BOOST_CLANG) && !defined(BOOST_NO_FENV_H)
- ::feclearexcept(BOOST_FPE_ALL);
- int res = ::feenableexcept( mask );
+ feclearexcept(BOOST_FPE_ALL);
+ int res = feenableexcept( mask );
return res == -1 ? (unsigned)BOOST_FPE_INV : (unsigned)res;
#else
/* Not Implemented */
@@ -1417,8 +1419,8 @@ disable( unsigned mask )
return ~old_cw & BOOST_FPE_ALL;
#elif defined(__GLIBC__) && defined(__USE_GNU) && !defined(BOOST_CLANG) && !defined(BOOST_NO_FENV_H)
- ::feclearexcept(BOOST_FPE_ALL);
- int res = ::fedisableexcept( mask );
+ feclearexcept(BOOST_FPE_ALL);
+ int res = fedisableexcept( mask );
return res == -1 ? (unsigned)BOOST_FPE_INV : (unsigned)res;
#else
/* Not Implemented */
diff --git a/boost/test/impl/framework.ipp b/boost/test/impl/framework.ipp
index f710828051..78459bac27 100644
--- a/boost/test/impl/framework.ipp
+++ b/boost/test/impl/framework.ipp
@@ -480,6 +480,7 @@ public:
BOOST_TEST_FOREACH( test_unit_id, chld_id, ts.m_children )
deduce_siblings_order( chld_id, master_tu_id, tuoi );
+ ts.m_ranked_children.clear();
BOOST_TEST_FOREACH( test_unit_id, chld_id, ts.m_children ) {
counter_t rank = assign_sibling_rank( chld_id, tuoi );
ts.m_ranked_children.insert( std::make_pair( rank, chld_id ) );
@@ -581,8 +582,17 @@ public:
typedef unit_test_monitor_t::error_level execution_result;
+ // Random generator using the std::rand function (seeded prior to the call)
+ struct random_generator_helper {
+ size_t operator()(size_t i) const {
+ return std::rand() % i;
+ }
+ };
+
// Executed the test tree with the root at specified test unit
- execution_result execute_test_tree( test_unit_id tu_id, unsigned timeout = 0 )
+ execution_result execute_test_tree( test_unit_id tu_id,
+ unsigned timeout = 0,
+ random_generator_helper const * const p_random_generator = 0)
{
test_unit const& tu = framework::get( tu_id, TUT_ANY );
@@ -662,12 +672,14 @@ public:
it++;
}
- std::random_shuffle( children_with_the_same_rank.begin(), children_with_the_same_rank.end() );
+ const random_generator_helper& rand_gen = p_random_generator ? *p_random_generator : random_generator_helper();
+
+ std::random_shuffle( children_with_the_same_rank.begin(), children_with_the_same_rank.end(), rand_gen );
BOOST_TEST_FOREACH( test_unit_id, chld, children_with_the_same_rank ) {
unsigned chld_timeout = child_timeout( timeout, tu_timer.elapsed() );
- result = (std::min)( result, execute_test_tree( chld, chld_timeout ) );
+ result = (std::min)( result, execute_test_tree( chld, chld_timeout, &rand_gen ) );
if( unit_test_monitor.is_critical_error( result ) )
break;
@@ -1221,7 +1233,7 @@ run( test_unit_id id, bool continue_test )
case 0:
break;
case 1:
- seed = static_cast<unsigned>( std::time( 0 ) );
+ seed = static_cast<unsigned>( std::rand() ^ std::time( 0 ) ); // better init using std::rand() ^ ...
default:
BOOST_TEST_MESSAGE( "Test cases order is shuffled using seed: " << seed );
std::srand( seed );
diff --git a/boost/test/impl/xml_report_formatter.ipp b/boost/test/impl/xml_report_formatter.ipp
index 08af9a3427..424ef4ba44 100644
--- a/boost/test/impl/xml_report_formatter.ipp
+++ b/boost/test/impl/xml_report_formatter.ipp
@@ -65,7 +65,7 @@ xml_report_formatter::test_unit_report_start( test_unit const& tu, std::ostream&
descr = "failed";
ostr << '<' << ( tu.p_type == TUT_CASE ? "TestCase" : "TestSuite" )
- << " name" << utils::attr_value() << tu.p_name
+ << " name" << utils::attr_value() << tu.p_name.get()
<< " result" << utils::attr_value() << descr
<< " assertions_passed" << utils::attr_value() << tr.p_assertions_passed
<< " assertions_failed" << utils::attr_value() << tr.p_assertions_failed
diff --git a/boost/test/tools/collection_comparison_op.hpp b/boost/test/tools/collection_comparison_op.hpp
index e5c5ca3bb8..9d5a7d8f7b 100644
--- a/boost/test/tools/collection_comparison_op.hpp
+++ b/boost/test/tools/collection_comparison_op.hpp
@@ -278,7 +278,7 @@ lexicographic_compare( Lhs const& lhs, Rhs const& rhs )
template <typename Lhs, typename Rhs, typename OP>
inline assertion_result
-compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<OP>* tp, mpl::true_ )
+compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<OP>*, mpl::true_ )
{
return lexicographic_compare<OP>( lhs, rhs );
}
@@ -287,7 +287,7 @@ compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<OP>* tp, mpl::t
template <typename Lhs, typename Rhs, typename L, typename R>
inline assertion_result
-compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::LT<L, R> >* tp, mpl::false_ )
+compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::LT<L, R> >*, mpl::false_ )
{
return lhs < rhs;
}
@@ -296,7 +296,7 @@ compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::LT<L, R> >*
template <typename Lhs, typename Rhs, typename L, typename R>
inline assertion_result
-compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::LE<L, R> >* tp, mpl::false_ )
+compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::LE<L, R> >*, mpl::false_ )
{
return lhs <= rhs;
}
@@ -305,7 +305,7 @@ compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::LE<L, R> >*
template <typename Lhs, typename Rhs, typename L, typename R>
inline assertion_result
-compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::GT<L, R> >* tp, mpl::false_ )
+compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::GT<L, R> >*, mpl::false_ )
{
return lhs > rhs;
}
@@ -314,7 +314,7 @@ compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::GT<L, R> >*
template <typename Lhs, typename Rhs, typename L, typename R>
inline assertion_result
-compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::GE<L, R> >* tp, mpl::false_ )
+compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::GE<L, R> >*, mpl::false_ )
{
return lhs >= rhs;
}
diff --git a/boost/test/tools/detail/print_helper.hpp b/boost/test/tools/detail/print_helper.hpp
index 77b936c44b..39ab707f36 100644
--- a/boost/test/tools/detail/print_helper.hpp
+++ b/boost/test/tools/detail/print_helper.hpp
@@ -22,9 +22,12 @@
// Boost
#include <boost/mpl/or.hpp>
+#include <boost/static_assert.hpp>
#include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/is_function.hpp>
#include <boost/type_traits/is_abstract.hpp>
+#include <boost/type_traits/has_left_shift.hpp>
+
#include <limits>
#include <boost/test/detail/suppress_warnings.hpp>
@@ -41,6 +44,9 @@ namespace tt_detail {
template<typename T>
struct print_log_value {
+ BOOST_STATIC_ASSERT_MSG( (boost::has_left_shift<std::ostream,T>::value),
+ "Type has to implement operator<< to be printable");
+
void operator()( std::ostream& ostr, T const& t )
{
typedef typename mpl::or_<is_array<T>,is_function<T>,is_abstract<T> >::type cant_use_nl;
diff --git a/boost/test/tools/interface.hpp b/boost/test/tools/interface.hpp
index 48d5affc4f..5e84f1c6d4 100644
--- a/boost/test/tools/interface.hpp
+++ b/boost/test/tools/interface.hpp
@@ -40,17 +40,9 @@
// ************** BOOST_TEST_<level> ************** //
// ************************************************************************** //
-#ifdef BOOST_NO_CXX11_AUTO_DECLARATIONS
-#define BOOST_TEST_BUILD_ASSERTION( P ) \
- ::boost::test_tools::tt_detail::expression_holder const& E= \
- ::boost::test_tools::tt_detail::hold_expression( \
- ::boost::test_tools::assertion::seed() ->* P ) \
-/**/
-#else
-#define BOOST_TEST_BUILD_ASSERTION( P ) \
- auto const& E = ::boost::test_tools::assertion::seed()->*P \
+#define BOOST_TEST_BUILD_ASSERTION( P ) \
+ (::boost::test_tools::assertion::seed()->*P) \
/**/
-#endif
//____________________________________________________________________________//
@@ -75,10 +67,10 @@ do { \
#define BOOST_TEST_TOOL_ET_IMPL( P, level ) \
do { \
BOOST_TEST_PASSPOINT(); \
- BOOST_TEST_BUILD_ASSERTION( P ); \
+ \
::boost::test_tools::tt_detail:: \
report_assertion( \
- E.evaluate(), \
+ BOOST_TEST_BUILD_ASSERTION( P ).evaluate(), \
BOOST_TEST_LAZY_MSG( BOOST_TEST_STRINGIZE( P ) ), \
BOOST_TEST_L(__FILE__), \
static_cast<std::size_t>(__LINE__), \
@@ -94,10 +86,11 @@ do { \
#define BOOST_TEST_TOOL_ET_IMPL_EX( P, level, arg ) \
do { \
BOOST_TEST_PASSPOINT(); \
- BOOST_TEST_BUILD_ASSERTION( P ); \
+ \
::boost::test_tools::tt_detail:: \
report_assertion( \
- ::boost::test_tools::tt_detail::assertion_evaluate(E) \
+ ::boost::test_tools::tt_detail::assertion_evaluate( \
+ BOOST_TEST_BUILD_ASSERTION( P ) ) \
<< arg, \
::boost::test_tools::tt_detail::assertion_text( \
BOOST_TEST_LAZY_MSG( BOOST_TEST_STRINGIZE(P) ), \
diff --git a/boost/test/utils/named_params.hpp b/boost/test/utils/named_params.hpp
index ebd5a6a751..88b8a883fe 100644
--- a/boost/test/utils/named_params.hpp
+++ b/boost/test/utils/named_params.hpp
@@ -331,7 +331,7 @@ struct typed_keyword<bool,unique_id,required>
template<typename T, typename Params, typename Keyword>
inline typename enable_if_c<!has_param<Params,Keyword>::value,void>::type
-opt_assign( T& target, Params const& p, Keyword k )
+opt_assign( T& /*target*/, Params const& /*p*/, Keyword /*k*/ )
{
}
diff --git a/boost/thread/future.hpp b/boost/thread/future.hpp
index 0ec484c2bf..6100c1606b 100644
--- a/boost/thread/future.hpp
+++ b/boost/thread/future.hpp
@@ -1434,6 +1434,10 @@ namespace boost
template <class F, class Rp, class Fp>
BOOST_THREAD_FUTURE<Rp>
+ make_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
+
+ template <class F, class Rp, class Fp>
+ BOOST_THREAD_FUTURE<Rp>
make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
template<typename F, typename Rp, typename Fp>
@@ -1444,6 +1448,11 @@ namespace boost
BOOST_THREAD_FUTURE<Rp>
make_shared_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
+ template<typename F, typename Rp, typename Fp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_shared_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
+
+
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
template<typename Ex, typename F, typename Rp, typename Fp>
BOOST_THREAD_FUTURE<Rp>
@@ -1518,6 +1527,10 @@ namespace boost
template <class F, class Rp, class Fp>
friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
+
+ template <class F, class Rp, class Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
detail::make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
template<typename F, typename Rp, typename Fp>
@@ -1528,6 +1541,10 @@ namespace boost
friend BOOST_THREAD_FUTURE<Rp>
detail::make_shared_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
+ template<typename F, typename Rp, typename Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_shared_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
+
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
template<typename Ex, typename F, typename Rp, typename Fp>
friend BOOST_THREAD_FUTURE<Rp>
@@ -1774,6 +1791,10 @@ namespace boost
template <class F, class Rp, class Fp>
friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
+
+ template <class F, class Rp, class Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
detail::make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
template<typename F, typename Rp, typename Fp>
@@ -1784,6 +1805,10 @@ namespace boost
friend BOOST_THREAD_FUTURE<Rp>
detail::make_shared_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
+ template<typename F, typename Rp, typename Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_shared_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F f, BOOST_THREAD_FWD_REF(Fp) c);
+
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
template<typename Ex, typename F, typename Rp, typename Fp>
friend BOOST_THREAD_FUTURE<Rp>
@@ -2007,6 +2032,10 @@ namespace boost
template <class F, class Rp, class Fp>
friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_sync_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
+
+ template <class F, class Rp, class Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
detail::make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
#endif
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
@@ -4210,12 +4239,6 @@ namespace detail {
////////////////////////////////
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
-#if defined BOOST_THREAD_CONTINUATION_SYNC
-#define continuation_shared_state_base shared_state
-#else
-#define continuation_shared_state_base future_async_shared_state_base
-#endif
-
namespace detail
{
//////////////////////
@@ -4345,27 +4368,44 @@ namespace detail
/////////////////////////
template<typename F, typename Rp, typename Fp>
- struct future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,continuation_shared_state_base<Rp> >
+ struct future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> >
{
- typedef continuation_shared_state<F,Rp,Fp,continuation_shared_state_base<Rp> > base_type;
+ typedef continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> > base_type;
public:
future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
: base_type(boost::move(f), boost::forward<Fp>(c))
{ }
void launch_continuation() {
-#if defined BOOST_THREAD_CONTINUATION_SYNC
- this->call();
-#elif defined BOOST_THREAD_FUTURE_BLOCKING
+#if defined BOOST_THREAD_FUTURE_BLOCKING
boost::lock_guard<boost::mutex> lk(this->mutex);
this->thr_ = thread(&future_async_continuation_shared_state::run, static_shared_from_this(this));
#else
- thread(&future_async_continuation_shared_state::run, static_shared_from_this(this)).detach();
+ thread(&base_type::run, static_shared_from_this(this)).detach();
#endif
}
};
/////////////////////////
+ /// future_sync_continuation_shared_state
+ /////////////////////////
+
+ template<typename F, typename Rp, typename Fp>
+ struct future_sync_continuation_shared_state: continuation_shared_state<F,Rp,Fp,shared_state<Rp> >
+ {
+ typedef continuation_shared_state<F,Rp,Fp,shared_state<Rp> > base_type;
+ public:
+ future_sync_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
+ : base_type(boost::move(f), boost::forward<Fp>(c))
+ { }
+
+ void launch_continuation() {
+ this->call();
+ }
+ };
+
+
+ /////////////////////////
/// future_executor_continuation_shared_state
/////////////////////////
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
@@ -4445,9 +4485,9 @@ namespace detail {
/////////////////////////
template<typename F, typename Rp, typename Fp>
- struct shared_future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,continuation_shared_state_base<Rp> >
+ struct shared_future_async_continuation_shared_state: continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> >
{
- typedef continuation_shared_state<F,Rp,Fp,continuation_shared_state_base<Rp> > base_type;
+ typedef continuation_shared_state<F,Rp,Fp,future_async_shared_state_base<Rp> > base_type;
public:
shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
@@ -4456,19 +4496,36 @@ namespace detail {
}
void launch_continuation() {
-#if defined BOOST_THREAD_CONTINUATION_SYNC
- this->call();
-#elif defined BOOST_THREAD_FUTURE_BLOCKING
+#if defined BOOST_THREAD_FUTURE_BLOCKING
boost::lock_guard<boost::mutex> lk(this->mutex);
- this->thr_ = thread(&shared_future_async_continuation_shared_state::run, static_shared_from_this(this));
+ this->thr_ = thread(&base_type::run, static_shared_from_this(this));
#else
- thread(&shared_future_async_continuation_shared_state::run, static_shared_from_this(this)).detach();
+ thread(&base_type::run, static_shared_from_this(this)).detach();
#endif
}
+ };
- ~shared_future_async_continuation_shared_state() {}
+ /////////////////////////
+ /// shared_future_async_continuation_shared_state
+ /////////////////////////
+
+ template<typename F, typename Rp, typename Fp>
+ struct shared_future_sync_continuation_shared_state: continuation_shared_state<F,Rp,Fp,shared_state<Rp> >
+ {
+ typedef continuation_shared_state<F,Rp,Fp,shared_state<Rp> > base_type;
+
+ public:
+ shared_future_sync_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
+ : base_type(boost::move(f), boost::forward<Fp>(c))
+ {
+ }
+
+ void launch_continuation() {
+ this->call();
+ }
};
+
/////////////////////////
/// shared_future_executor_continuation_shared_state
/////////////////////////
@@ -4577,6 +4634,21 @@ namespace detail {
return BOOST_THREAD_FUTURE<Rp>(h);
}
+ ////////////////////////////////
+ // make_future_sync_continuation_shared_state
+ ////////////////////////////////
+ template<typename F, typename Rp, typename Fp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_future_sync_continuation_shared_state(
+ boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f,
+ BOOST_THREAD_FWD_REF(Fp) c) {
+ typedef typename decay<Fp>::type Cont;
+ shared_ptr<future_sync_continuation_shared_state<F,Rp, Cont> >
+ h(new future_sync_continuation_shared_state<F,Rp, Cont>(boost::move(f), boost::forward<Fp>(c)));
+ h->init(lock);
+
+ return BOOST_THREAD_FUTURE<Rp>(h);
+ }
////////////////////////////////
// make_future_executor_continuation_shared_state
@@ -4628,6 +4700,21 @@ namespace detail {
return BOOST_THREAD_FUTURE<Rp>(h);
}
////////////////////////////////
+ // make_shared_future_sync_continuation_shared_state
+ ////////////////////////////////
+ template<typename F, typename Rp, typename Fp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_shared_future_sync_continuation_shared_state(
+ boost::unique_lock<boost::mutex> &lock, F f,
+ BOOST_THREAD_FWD_REF(Fp) c) {
+ typedef typename decay<Fp>::type Cont;
+ shared_ptr<shared_future_sync_continuation_shared_state<F,Rp, Cont> >
+ h(new shared_future_sync_continuation_shared_state<F,Rp, Cont>(f, boost::forward<Fp>(c)));
+ h->init(lock);
+
+ return BOOST_THREAD_FUTURE<Rp>(h);
+ }
+ ////////////////////////////////
// make_shared_future_executor_continuation_shared_state
////////////////////////////////
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
@@ -4787,6 +4874,10 @@ namespace detail {
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
lock, boost::move(*this), boost::forward<F>(func)
)));
+ } else if (underlying_cast<int>(policy) & int(launch::sync)) {
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
+ lock, boost::move(*this), boost::forward<F>(func)
+ )));
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
} else if (underlying_cast<int>(policy) & int(launch::executor)) {
assert(this->future_->get_executor());
@@ -4807,6 +4898,10 @@ namespace detail {
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
lock, boost::move(*this), boost::forward<F>(func)
)));
+ } else if (underlying_cast<int>(policy) & int(launch::sync)) {
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
+ lock, boost::move(*this), boost::forward<F>(func)
+ )));
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
} else if (underlying_cast<int>(policy) & int(launch::executor)) {
assert(this->future_->get_executor());
@@ -4878,7 +4973,7 @@ namespace detail {
lock, boost::move(*this), boost::forward<F>(func)
)));
} else {
- return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
lock, boost::move(*this), boost::forward<F>(func)
)));
}
@@ -4906,6 +5001,10 @@ namespace detail {
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type>(
lock, *this, boost::forward<F>(func)
)));
+ } else if (underlying_cast<int>(policy) & int(launch::sync)) {
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_sync_continuation_shared_state<shared_future<R>, future_type>(
+ lock, *this, boost::forward<F>(func)
+ )));
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
} else if (underlying_cast<int>(policy) & int(launch::executor)) {
typedef executor Ex;
@@ -4925,6 +5024,10 @@ namespace detail {
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type>(
lock, *this, boost::forward<F>(func)
)));
+ } else if (underlying_cast<int>(policy) & int(launch::sync)) {
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_sync_continuation_shared_state<shared_future<R>, future_type>(
+ lock, *this, boost::forward<F>(func)
+ )));
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
} else if (underlying_cast<int>(policy) & int(launch::executor)) {
typedef executor Ex;
@@ -4986,7 +5089,7 @@ namespace detail {
lock, *this, boost::forward<F>(func)
)));
} else {
- return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type>(
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_sync_continuation_shared_state<shared_future<R>, future_type>(
lock, *this, boost::forward<F>(func)
)));
}
diff --git a/boost/thread/futures/launch.hpp b/boost/thread/futures/launch.hpp
index 8eed42cf4d..329f40d8f3 100644
--- a/boost/thread/futures/launch.hpp
+++ b/boost/thread/futures/launch.hpp
@@ -23,6 +23,7 @@ namespace boost
executor = 4,
#endif
inherit = 8,
+ sync = 16,
any = async | deferred
}
BOOST_SCOPED_ENUM_DECLARE_END(launch)
diff --git a/boost/thread/pthread/condition_variable.hpp b/boost/thread/pthread/condition_variable.hpp
index a603351591..e8378c7d3e 100644
--- a/boost/thread/pthread/condition_variable.hpp
+++ b/boost/thread/pthread/condition_variable.hpp
@@ -336,14 +336,15 @@ namespace boost
cv_status::timeout;
}
+ template <class lock_type>
inline cv_status wait_until(
- unique_lock<mutex>& lk,
+ lock_type& lock,
chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();
timespec ts = boost::detail::to_timespec(d);
- if (do_wait_until(lk, ts)) return cv_status::no_timeout;
+ if (do_wait_until(lock, ts)) return cv_status::no_timeout;
else return cv_status::timeout;
}
@@ -391,7 +392,7 @@ namespace boost
private: // used by boost::thread::try_join_until
template <class lock_type>
- inline bool do_wait_until(
+ bool do_wait_until(
lock_type& m,
struct timespec const &timeout)
{
diff --git a/boost/thread/scoped_thread.hpp b/boost/thread/scoped_thread.hpp
index ae0d1efc53..c2da919728 100644
--- a/boost/thread/scoped_thread.hpp
+++ b/boost/thread/scoped_thread.hpp
@@ -197,6 +197,9 @@ namespace boost
*/
scoped_thread& operator=(BOOST_RV_REF(scoped_thread) x)
{
+ CallableThread on_destructor;
+
+ on_destructor(t_);
t_ = boost::move(BOOST_THREAD_RV(x).t_);
return *this;
}
diff --git a/boost/thread/win32/thread_primitives.hpp b/boost/thread/win32/thread_primitives.hpp
index b63503ad52..6d2ca7c2cf 100644
--- a/boost/thread/win32/thread_primitives.hpp
+++ b/boost/thread/win32/thread_primitives.hpp
@@ -156,7 +156,7 @@ namespace boost
{
struct _SECURITY_ATTRIBUTES;
# ifdef BOOST_NO_ANSI_APIS
-# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
+# if defined(BOOST_USE_WINAPI_VERSION) && ( BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA )
__declspec(dllimport) void* __stdcall CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*);
__declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*);
__declspec(dllimport) void* __stdcall CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*);
@@ -339,7 +339,7 @@ namespace boost
{
#if !defined(BOOST_NO_ANSI_APIS)
handle const res = win32::CreateEventA(0, type, state, mutex_name);
-#elif BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
+#elif defined(BOOST_USE_WINAPI_VERSION) && ( BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA )
handle const res = win32::CreateEventW(0, type, state, mutex_name);
#else
handle const res = win32::CreateEventExW(
@@ -366,7 +366,7 @@ namespace boost
#if !defined(BOOST_NO_ANSI_APIS)
handle const res=win32::CreateSemaphoreA(0,initial_count,max_count,0);
#else
-#if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
+#if defined(BOOST_USE_WINAPI_VERSION) && ( BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA )
handle const res=win32::CreateSemaphoreEx(0,initial_count,max_count,0,0);
#else
handle const res=win32::CreateSemaphoreExW(0,initial_count,max_count,0,0,semaphore_all_access);
diff --git a/boost/type_index/stl_type_index.hpp b/boost/type_index/stl_type_index.hpp
index c801e70f62..a5add88716 100644
--- a/boost/type_index/stl_type_index.hpp
+++ b/boost/type_index/stl_type_index.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) Antony Polukhin, 2013-2014.
+// Copyright (c) Antony Polukhin, 2013-2015.
//
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -200,7 +200,7 @@ inline bool stl_type_index::equal(const stl_type_index& rhs) const BOOST_NOEXCEP
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
return raw_name() == rhs.raw_name() || !std::strcmp(raw_name(), rhs.raw_name());
#else
- return *data_ == *rhs.data_;
+ return !!(*data_ == *rhs.data_);
#endif
}
diff --git a/boost/type_traits.hpp b/boost/type_traits.hpp
index 57680f89f6..7d651ce28d 100644
--- a/boost/type_traits.hpp
+++ b/boost/type_traits.hpp
@@ -10,141 +10,141 @@
#ifndef BOOST_TYPE_TRAITS_HPP
#define BOOST_TYPE_TRAITS_HPP
-#include "boost/type_traits/add_const.hpp"
-#include "boost/type_traits/add_cv.hpp"
-#include "boost/type_traits/add_lvalue_reference.hpp"
-#include "boost/type_traits/add_pointer.hpp"
-#include "boost/type_traits/add_reference.hpp"
-#include "boost/type_traits/add_rvalue_reference.hpp"
-#include "boost/type_traits/add_volatile.hpp"
-#include "boost/type_traits/aligned_storage.hpp"
-#include "boost/type_traits/alignment_of.hpp"
-#include "boost/type_traits/common_type.hpp"
-#include "boost/type_traits/conditional.hpp"
-#include "boost/type_traits/copy_cv.hpp"
-#include "boost/type_traits/decay.hpp"
-#include "boost/type_traits/declval.hpp"
-#include "boost/type_traits/extent.hpp"
-#include "boost/type_traits/floating_point_promotion.hpp"
-#include "boost/type_traits/function_traits.hpp"
+#include <boost/type_traits/add_const.hpp>
+#include <boost/type_traits/add_cv.hpp>
+#include <boost/type_traits/add_lvalue_reference.hpp>
+#include <boost/type_traits/add_pointer.hpp>
+#include <boost/type_traits/add_reference.hpp>
+#include <boost/type_traits/add_rvalue_reference.hpp>
+#include <boost/type_traits/add_volatile.hpp>
+#include <boost/type_traits/aligned_storage.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/common_type.hpp>
+#include <boost/type_traits/conditional.hpp>
+#include <boost/type_traits/copy_cv.hpp>
+#include <boost/type_traits/decay.hpp>
+#include <boost/type_traits/declval.hpp>
+#include <boost/type_traits/extent.hpp>
+#include <boost/type_traits/floating_point_promotion.hpp>
+#include <boost/type_traits/function_traits.hpp>
-#include "boost/type_traits/has_bit_and.hpp"
-#include "boost/type_traits/has_bit_and_assign.hpp"
-#include "boost/type_traits/has_bit_or.hpp"
-#include "boost/type_traits/has_bit_or_assign.hpp"
-#include "boost/type_traits/has_bit_xor.hpp"
-#include "boost/type_traits/has_bit_xor_assign.hpp"
-#include "boost/type_traits/has_complement.hpp"
-#include "boost/type_traits/has_dereference.hpp"
-#include "boost/type_traits/has_divides.hpp"
-#include "boost/type_traits/has_divides_assign.hpp"
-#include "boost/type_traits/has_equal_to.hpp"
-#include "boost/type_traits/has_greater.hpp"
-#include "boost/type_traits/has_greater_equal.hpp"
-#include "boost/type_traits/has_left_shift.hpp"
-#include "boost/type_traits/has_left_shift_assign.hpp"
-#include "boost/type_traits/has_less.hpp"
-#include "boost/type_traits/has_less_equal.hpp"
-#include "boost/type_traits/has_logical_and.hpp"
-#include "boost/type_traits/has_logical_not.hpp"
-#include "boost/type_traits/has_logical_or.hpp"
-#include "boost/type_traits/has_minus.hpp"
-#include "boost/type_traits/has_minus_assign.hpp"
-#include "boost/type_traits/has_modulus.hpp"
-#include "boost/type_traits/has_modulus_assign.hpp"
-#include "boost/type_traits/has_multiplies.hpp"
-#include "boost/type_traits/has_multiplies_assign.hpp"
-#include "boost/type_traits/has_negate.hpp"
+#include <boost/type_traits/has_bit_and.hpp>
+#include <boost/type_traits/has_bit_and_assign.hpp>
+#include <boost/type_traits/has_bit_or.hpp>
+#include <boost/type_traits/has_bit_or_assign.hpp>
+#include <boost/type_traits/has_bit_xor.hpp>
+#include <boost/type_traits/has_bit_xor_assign.hpp>
+#include <boost/type_traits/has_complement.hpp>
+#include <boost/type_traits/has_dereference.hpp>
+#include <boost/type_traits/has_divides.hpp>
+#include <boost/type_traits/has_divides_assign.hpp>
+#include <boost/type_traits/has_equal_to.hpp>
+#include <boost/type_traits/has_greater.hpp>
+#include <boost/type_traits/has_greater_equal.hpp>
+#include <boost/type_traits/has_left_shift.hpp>
+#include <boost/type_traits/has_left_shift_assign.hpp>
+#include <boost/type_traits/has_less.hpp>
+#include <boost/type_traits/has_less_equal.hpp>
+#include <boost/type_traits/has_logical_and.hpp>
+#include <boost/type_traits/has_logical_not.hpp>
+#include <boost/type_traits/has_logical_or.hpp>
+#include <boost/type_traits/has_minus.hpp>
+#include <boost/type_traits/has_minus_assign.hpp>
+#include <boost/type_traits/has_modulus.hpp>
+#include <boost/type_traits/has_modulus_assign.hpp>
+#include <boost/type_traits/has_multiplies.hpp>
+#include <boost/type_traits/has_multiplies_assign.hpp>
+#include <boost/type_traits/has_negate.hpp>
#if !defined(__BORLANDC__) && !defined(__CUDACC__)
-#include "boost/type_traits/has_new_operator.hpp"
+#include <boost/type_traits/has_new_operator.hpp>
#endif
-#include "boost/type_traits/has_not_equal_to.hpp"
-#include "boost/type_traits/has_nothrow_assign.hpp"
-#include "boost/type_traits/has_nothrow_constructor.hpp"
-#include "boost/type_traits/has_nothrow_copy.hpp"
-#include "boost/type_traits/has_nothrow_destructor.hpp"
-#include "boost/type_traits/has_plus.hpp"
-#include "boost/type_traits/has_plus_assign.hpp"
-#include "boost/type_traits/has_post_decrement.hpp"
-#include "boost/type_traits/has_post_increment.hpp"
-#include "boost/type_traits/has_pre_decrement.hpp"
-#include "boost/type_traits/has_pre_increment.hpp"
-#include "boost/type_traits/has_right_shift.hpp"
-#include "boost/type_traits/has_right_shift_assign.hpp"
-#include "boost/type_traits/has_trivial_assign.hpp"
-#include "boost/type_traits/has_trivial_constructor.hpp"
-#include "boost/type_traits/has_trivial_copy.hpp"
-#include "boost/type_traits/has_trivial_destructor.hpp"
-#include "boost/type_traits/has_trivial_move_assign.hpp"
-#include "boost/type_traits/has_trivial_move_constructor.hpp"
-#include "boost/type_traits/has_unary_minus.hpp"
-#include "boost/type_traits/has_unary_plus.hpp"
-#include "boost/type_traits/has_virtual_destructor.hpp"
+#include <boost/type_traits/has_not_equal_to.hpp>
+#include <boost/type_traits/has_nothrow_assign.hpp>
+#include <boost/type_traits/has_nothrow_constructor.hpp>
+#include <boost/type_traits/has_nothrow_copy.hpp>
+#include <boost/type_traits/has_nothrow_destructor.hpp>
+#include <boost/type_traits/has_plus.hpp>
+#include <boost/type_traits/has_plus_assign.hpp>
+#include <boost/type_traits/has_post_decrement.hpp>
+#include <boost/type_traits/has_post_increment.hpp>
+#include <boost/type_traits/has_pre_decrement.hpp>
+#include <boost/type_traits/has_pre_increment.hpp>
+#include <boost/type_traits/has_right_shift.hpp>
+#include <boost/type_traits/has_right_shift_assign.hpp>
+#include <boost/type_traits/has_trivial_assign.hpp>
+#include <boost/type_traits/has_trivial_constructor.hpp>
+#include <boost/type_traits/has_trivial_copy.hpp>
+#include <boost/type_traits/has_trivial_destructor.hpp>
+#include <boost/type_traits/has_trivial_move_assign.hpp>
+#include <boost/type_traits/has_trivial_move_constructor.hpp>
+#include <boost/type_traits/has_unary_minus.hpp>
+#include <boost/type_traits/has_unary_plus.hpp>
+#include <boost/type_traits/has_virtual_destructor.hpp>
-#include "boost/type_traits/integral_constant.hpp"
+#include <boost/type_traits/integral_constant.hpp>
-#include "boost/type_traits/is_abstract.hpp"
-#include "boost/type_traits/is_arithmetic.hpp"
-#include "boost/type_traits/is_array.hpp"
-#include "boost/type_traits/is_assignable.hpp"
-#include "boost/type_traits/is_base_and_derived.hpp"
-#include "boost/type_traits/is_base_of.hpp"
-#include "boost/type_traits/is_class.hpp"
-#include "boost/type_traits/is_complex.hpp"
-#include "boost/type_traits/is_compound.hpp"
-#include "boost/type_traits/is_const.hpp"
-#include "boost/type_traits/is_constructible.hpp"
-#include "boost/type_traits/is_convertible.hpp"
-#include "boost/type_traits/is_copy_assignable.hpp"
-#include "boost/type_traits/is_copy_constructible.hpp"
-#include "boost/type_traits/is_default_constructible.hpp"
-#include "boost/type_traits/is_destructible.hpp"
-#include "boost/type_traits/is_empty.hpp"
-#include "boost/type_traits/is_enum.hpp"
-#include "boost/type_traits/is_final.hpp"
-#include "boost/type_traits/is_float.hpp"
-#include "boost/type_traits/is_floating_point.hpp"
-#include "boost/type_traits/is_function.hpp"
-#include "boost/type_traits/is_fundamental.hpp"
-#include "boost/type_traits/is_integral.hpp"
-#include "boost/type_traits/is_lvalue_reference.hpp"
-#include "boost/type_traits/is_member_function_pointer.hpp"
-#include "boost/type_traits/is_member_object_pointer.hpp"
-#include "boost/type_traits/is_member_pointer.hpp"
-#include "boost/type_traits/is_nothrow_move_assignable.hpp"
-#include "boost/type_traits/is_nothrow_move_constructible.hpp"
-#include "boost/type_traits/is_object.hpp"
-#include "boost/type_traits/is_pod.hpp"
-#include "boost/type_traits/is_pointer.hpp"
-#include "boost/type_traits/is_polymorphic.hpp"
-#include "boost/type_traits/is_reference.hpp"
-#include "boost/type_traits/is_rvalue_reference.hpp"
-#include "boost/type_traits/is_same.hpp"
-#include "boost/type_traits/is_scalar.hpp"
-#include "boost/type_traits/is_signed.hpp"
-#include "boost/type_traits/is_stateless.hpp"
-#include "boost/type_traits/is_union.hpp"
-#include "boost/type_traits/is_unsigned.hpp"
-#include "boost/type_traits/is_virtual_base_of.hpp"
-#include "boost/type_traits/is_void.hpp"
-#include "boost/type_traits/is_volatile.hpp"
-#include "boost/type_traits/make_signed.hpp"
-#include "boost/type_traits/make_unsigned.hpp"
-#include "boost/type_traits/rank.hpp"
-#include "boost/type_traits/remove_all_extents.hpp"
-#include "boost/type_traits/remove_bounds.hpp"
-#include "boost/type_traits/remove_const.hpp"
-#include "boost/type_traits/remove_cv.hpp"
-#include "boost/type_traits/remove_extent.hpp"
-#include "boost/type_traits/remove_pointer.hpp"
-#include "boost/type_traits/remove_reference.hpp"
-#include "boost/type_traits/remove_volatile.hpp"
-#include "boost/type_traits/type_identity.hpp"
-#include "boost/type_traits/type_with_alignment.hpp"
+#include <boost/type_traits/is_abstract.hpp>
+#include <boost/type_traits/is_arithmetic.hpp>
+#include <boost/type_traits/is_array.hpp>
+#include <boost/type_traits/is_assignable.hpp>
+#include <boost/type_traits/is_base_and_derived.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/type_traits/is_class.hpp>
+#include <boost/type_traits/is_complex.hpp>
+#include <boost/type_traits/is_compound.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_constructible.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_copy_assignable.hpp>
+#include <boost/type_traits/is_copy_constructible.hpp>
+#include <boost/type_traits/is_default_constructible.hpp>
+#include <boost/type_traits/is_destructible.hpp>
+#include <boost/type_traits/is_empty.hpp>
+#include <boost/type_traits/is_enum.hpp>
+#include <boost/type_traits/is_final.hpp>
+#include <boost/type_traits/is_float.hpp>
+#include <boost/type_traits/is_floating_point.hpp>
+#include <boost/type_traits/is_function.hpp>
+#include <boost/type_traits/is_fundamental.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_lvalue_reference.hpp>
+#include <boost/type_traits/is_member_function_pointer.hpp>
+#include <boost/type_traits/is_member_object_pointer.hpp>
+#include <boost/type_traits/is_member_pointer.hpp>
+#include <boost/type_traits/is_nothrow_move_assignable.hpp>
+#include <boost/type_traits/is_nothrow_move_constructible.hpp>
+#include <boost/type_traits/is_object.hpp>
+#include <boost/type_traits/is_pod.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/type_traits/is_polymorphic.hpp>
+#include <boost/type_traits/is_reference.hpp>
+#include <boost/type_traits/is_rvalue_reference.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_scalar.hpp>
+#include <boost/type_traits/is_signed.hpp>
+#include <boost/type_traits/is_stateless.hpp>
+#include <boost/type_traits/is_union.hpp>
+#include <boost/type_traits/is_unsigned.hpp>
+#include <boost/type_traits/is_virtual_base_of.hpp>
+#include <boost/type_traits/is_void.hpp>
+#include <boost/type_traits/is_volatile.hpp>
+#include <boost/type_traits/make_signed.hpp>
+#include <boost/type_traits/make_unsigned.hpp>
+#include <boost/type_traits/rank.hpp>
+#include <boost/type_traits/remove_all_extents.hpp>
+#include <boost/type_traits/remove_bounds.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_extent.hpp>
+#include <boost/type_traits/remove_pointer.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/type_traits/remove_volatile.hpp>
+#include <boost/type_traits/type_identity.hpp>
+#include <boost/type_traits/type_with_alignment.hpp>
#if !(defined(__sgi) && defined(__EDG_VERSION__) && (__EDG_VERSION__ == 238))
-#include "boost/type_traits/integral_promotion.hpp"
-#include "boost/type_traits/promote.hpp"
+#include <boost/type_traits/integral_promotion.hpp>
+#include <boost/type_traits/promote.hpp>
#endif
#endif // BOOST_TYPE_TRAITS_HPP
diff --git a/boost/type_traits/add_reference.hpp b/boost/type_traits/add_reference.hpp
index 526f259c87..3c914154ee 100644
--- a/boost/type_traits/add_reference.hpp
+++ b/boost/type_traits/add_reference.hpp
@@ -49,9 +49,9 @@ template <class T> struct add_reference<T&>
// these full specialisations are always required:
template <> struct add_reference<void> { typedef void type; };
#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
-template <> struct add_reference<const void> { typedef void type; };
-template <> struct add_reference<const volatile void> { typedef void type; };
-template <> struct add_reference<volatile void> { typedef void type; };
+template <> struct add_reference<const void> { typedef const void type; };
+template <> struct add_reference<const volatile void> { typedef const volatile void type; };
+template <> struct add_reference<volatile void> { typedef volatile void type; };
#endif
} // namespace boost
diff --git a/boost/type_traits/aligned_storage.hpp b/boost/type_traits/aligned_storage.hpp
index 09f0c6b885..171f5d450b 100644
--- a/boost/type_traits/aligned_storage.hpp
+++ b/boost/type_traits/aligned_storage.hpp
@@ -15,12 +15,12 @@
#include <cstddef> // for std::size_t
-#include "boost/config.hpp"
-#include "boost/detail/workaround.hpp"
-#include "boost/type_traits/alignment_of.hpp"
-#include "boost/type_traits/type_with_alignment.hpp"
-#include "boost/type_traits/is_pod.hpp"
-#include "boost/type_traits/conditional.hpp"
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/type_with_alignment.hpp>
+#include <boost/type_traits/is_pod.hpp>
+#include <boost/type_traits/conditional.hpp>
namespace boost {
diff --git a/boost/type_traits/common_type.hpp b/boost/type_traits/common_type.hpp
index 5c4303b9ec..c887a897f8 100644
--- a/boost/type_traits/common_type.hpp
+++ b/boost/type_traits/common_type.hpp
@@ -12,6 +12,7 @@
#include <boost/config.hpp>
#include <boost/type_traits/decay.hpp>
#include <boost/type_traits/declval.hpp>
+#include <boost/detail/workaround.hpp>
#if defined(BOOST_NO_CXX11_DECLTYPE)
#include <boost/type_traits/detail/common_type_impl.hpp>
diff --git a/boost/type_traits/detail/common_arithmetic_type.hpp b/boost/type_traits/detail/common_arithmetic_type.hpp
index 7211002218..8c091583c5 100644
--- a/boost/type_traits/detail/common_arithmetic_type.hpp
+++ b/boost/type_traits/detail/common_arithmetic_type.hpp
@@ -35,12 +35,16 @@ template<> struct arithmetic_type<2>
typedef char (&result_type) [2];
};
+#ifndef BOOST_NO_INTRINSIC_WCHAR_T
+
template<> struct arithmetic_type<3>
{
typedef wchar_t type;
typedef char (&result_type) [3];
};
+#endif
+
// There are five standard signed integer types:
// “signed charâ€, “short intâ€, “intâ€, “long intâ€, and “long long intâ€.
@@ -170,7 +174,9 @@ private:
static arithmetic_type<1>::result_type select( arithmetic_type<1>::type );
static arithmetic_type<2>::result_type select( arithmetic_type<2>::type );
+#ifndef BOOST_NO_INTRINSIC_WCHAR_T
static arithmetic_type<3>::result_type select( arithmetic_type<3>::type );
+#endif
static arithmetic_type<4>::result_type select( arithmetic_type<4>::type );
static arithmetic_type<5>::result_type select( arithmetic_type<5>::type );
static arithmetic_type<6>::result_type select( arithmetic_type<6>::type );
diff --git a/boost/type_traits/detail/mp_defer.hpp b/boost/type_traits/detail/mp_defer.hpp
index 7910e545e1..f3beeb21bb 100644
--- a/boost/type_traits/detail/mp_defer.hpp
+++ b/boost/type_traits/detail/mp_defer.hpp
@@ -25,12 +25,12 @@ template<template<class...> class F, class... T>
struct mp_valid_impl
{
template<template<class...> class G, class = G<T...>>
- static boost::true_type check(int);
+ static boost::true_type check_s(int);
template<template<class...> class>
- static boost::false_type check(...);
+ static boost::false_type check_s(...);
- using type = decltype(check<F>(0));
+ using type = decltype(check_s<F>(0));
};
template<template<class...> class F, class... T>
diff --git a/boost/type_traits/has_nothrow_assign.hpp b/boost/type_traits/has_nothrow_assign.hpp
index a7312a19e9..65fbeefc39 100644
--- a/boost/type_traits/has_nothrow_assign.hpp
+++ b/boost/type_traits/has_nothrow_assign.hpp
@@ -24,7 +24,7 @@
#include <boost/type_traits/remove_reference.hpp>
#endif
#endif
-#if defined(__GNUC__) || defined(__SUNPRO_CC)
+#if defined(__GNUC__) || defined(__SUNPRO_CC) || defined(__clang__)
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_volatile.hpp>
#include <boost/type_traits/is_assignable.hpp>
diff --git a/boost/type_traits/has_nothrow_constructor.hpp b/boost/type_traits/has_nothrow_constructor.hpp
index e5af89fe59..a71d42e6e4 100644
--- a/boost/type_traits/has_nothrow_constructor.hpp
+++ b/boost/type_traits/has_nothrow_constructor.hpp
@@ -17,7 +17,7 @@
#if defined(BOOST_MSVC) || defined(BOOST_INTEL)
#include <boost/type_traits/has_trivial_constructor.hpp>
#endif
-#if defined(__GNUC__ ) || defined(__SUNPRO_CC)
+#if defined(__GNUC__ ) || defined(__SUNPRO_CC) || defined(__clang__)
#include <boost/type_traits/is_default_constructible.hpp>
#endif
diff --git a/boost/type_traits/has_trivial_assign.hpp b/boost/type_traits/has_trivial_assign.hpp
index a5e625d1ae..a434dae726 100644
--- a/boost/type_traits/has_trivial_assign.hpp
+++ b/boost/type_traits/has_trivial_assign.hpp
@@ -13,7 +13,7 @@
#include <boost/type_traits/intrinsics.hpp>
#include <boost/type_traits/integral_constant.hpp>
-#if !defined(BOOST_HAS_TRIVIAL_ASSIGN) || defined(BOOST_MSVC) || defined(__GNUC__) || defined(BOOST_INTEL) || defined(__SUNPRO_CC) || defined(__clang)
+#if !defined(BOOST_HAS_TRIVIAL_ASSIGN) || defined(BOOST_MSVC) || defined(__GNUC__) || defined(BOOST_INTEL) || defined(__SUNPRO_CC) || defined(__clang__)
#include <boost/type_traits/is_pod.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_volatile.hpp>
diff --git a/boost/type_traits/has_trivial_destructor.hpp b/boost/type_traits/has_trivial_destructor.hpp
index 763283d78c..9a3a61ff97 100644
--- a/boost/type_traits/has_trivial_destructor.hpp
+++ b/boost/type_traits/has_trivial_destructor.hpp
@@ -21,7 +21,7 @@
#include <boost/type_traits/is_same.hpp>
#endif
-#if defined(__GNUC__) || defined(__clang) || defined(__SUNPRO_CC)
+#if defined(__GNUC__) || defined(__clang__) || defined(__SUNPRO_CC)
#include <boost/type_traits/is_destructible.hpp>
#endif
diff --git a/boost/type_traits/is_default_constructible.hpp b/boost/type_traits/is_default_constructible.hpp
index 7fd63f8969..0b7d960e7d 100644
--- a/boost/type_traits/is_default_constructible.hpp
+++ b/boost/type_traits/is_default_constructible.hpp
@@ -12,6 +12,10 @@
#include <boost/type_traits/integral_constant.hpp>
#include <boost/detail/workaround.hpp>
+#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40700)
+#include <boost/type_traits/is_abstract.hpp>
+#endif
+
#if !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40500)
#include <boost/type_traits/detail/yes_no_type.hpp>
@@ -28,10 +32,25 @@ namespace boost{
template<typename>
static boost::type_traits::no_type test(...);
};
-
+#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40700)
+ template<class T, bool b>
+ struct is_default_constructible_abstract_filter
+ {
+ static const bool value = sizeof(is_default_constructible_imp::test<T>(0)) == sizeof(boost::type_traits::yes_type);
+ };
+ template<class T>
+ struct is_default_constructible_abstract_filter<T, true>
+ {
+ static const bool value = false;
+ };
+#endif
}
+#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40700)
+ template <class T> struct is_default_constructible : public integral_constant<bool, detail::is_default_constructible_abstract_filter<T, boost::is_abstract<T>::value>::value>{};
+#else
template <class T> struct is_default_constructible : public integral_constant<bool, sizeof(detail::is_default_constructible_imp::test<T>(0)) == sizeof(boost::type_traits::yes_type)>{};
+#endif
template <class T, std::size_t N> struct is_default_constructible<T[N]> : public is_default_constructible<T>{};
template <class T> struct is_default_constructible<T[]> : public is_default_constructible<T>{};
template <class T> struct is_default_constructible<T&> : public integral_constant<bool, false>{};
diff --git a/boost/type_traits/is_nothrow_move_assignable.hpp b/boost/type_traits/is_nothrow_move_assignable.hpp
index 9755430ecf..4fb5bd8a6d 100644
--- a/boost/type_traits/is_nothrow_move_assignable.hpp
+++ b/boost/type_traits/is_nothrow_move_assignable.hpp
@@ -33,7 +33,7 @@ template <class T> struct is_nothrow_move_assignable<T&> : public false_type{};
template <class T> struct is_nothrow_move_assignable<T&&> : public false_type{};
#endif
-#elif !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_SFINAE_EXPR)
+#elif !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40700)
namespace detail{
diff --git a/boost/type_traits/is_nothrow_move_constructible.hpp b/boost/type_traits/is_nothrow_move_constructible.hpp
index 8f4cee2cf9..4c8f734726 100644
--- a/boost/type_traits/is_nothrow_move_constructible.hpp
+++ b/boost/type_traits/is_nothrow_move_constructible.hpp
@@ -26,7 +26,7 @@ struct is_nothrow_move_constructible : public integral_constant<bool, BOOST_IS_N
template <class T> struct is_nothrow_move_constructible<volatile T> : public ::boost::false_type {};
template <class T> struct is_nothrow_move_constructible<const volatile T> : public ::boost::false_type{};
-#elif !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40700)
+#elif !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
#include <boost/type_traits/declval.hpp>
#include <boost/utility/enable_if.hpp>
diff --git a/boost/units/io.hpp b/boost/units/io.hpp
index 577635d0ee..338a919ea6 100644
--- a/boost/units/io.hpp
+++ b/boost/units/io.hpp
@@ -41,7 +41,7 @@ namespace serialization {
/// Boost Serialization library support for units.
template<class Archive,class System,class Dim>
-inline void serialize(Archive& ar,boost::units::unit<Dim,System>&,const unsigned int /*version*/)
+inline void serialize(Archive& /*ar*/,boost::units::unit<Dim,System>&,const unsigned int /*version*/)
{ }
/// Boost Serialization library support for quantities.
diff --git a/boost/utility/string_view.hpp b/boost/utility/string_view.hpp
new file mode 100644
index 0000000000..9de32ccc56
--- /dev/null
+++ b/boost/utility/string_view.hpp
@@ -0,0 +1,670 @@
+/*
+ © Copyright (c) Marshall Clow 2012-2015.
+ © Copyright Beman Dawes 2015
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+ For more information, see http://www.boost.org
+
+ Based on the StringRef implementation in LLVM (http://llvm.org) and
+ N3422 by Jeffrey Yasskin
+ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
+ Updated July 2015 to reflect the Library Fundamentals TS
+ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html
+*/
+
+#ifndef BOOST_STRING_VIEW_HPP
+#define BOOST_STRING_VIEW_HPP
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/utility/string_view_fwd.hpp>
+#include <boost/throw_exception.hpp>
+
+#include <cstddef>
+#include <stdexcept>
+#include <algorithm>
+#include <iterator>
+#include <string>
+#include <cstring>
+#include <iosfwd>
+
+namespace boost {
+
+ namespace detail {
+ // A helper functor because sometimes we don't have lambdas
+ template <typename charT, typename traits>
+ class string_view_traits_eq {
+ public:
+ string_view_traits_eq ( charT ch ) : ch_(ch) {}
+ bool operator()( charT val ) const { return traits::eq (ch_, val); }
+ charT ch_;
+ };
+ }
+
+ template<typename charT, typename traits> // traits defaulted in string_view_fwd.hpp
+ class basic_string_view {
+ public:
+ // types
+ typedef traits traits_type;
+ typedef charT value_type;
+ typedef charT* pointer;
+ typedef const charT* const_pointer;
+ typedef charT& reference;
+ typedef const charT& const_reference;
+ typedef const_pointer const_iterator; // impl-defined
+ typedef const_iterator iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef const_reverse_iterator reverse_iterator;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1);
+
+ // construct/copy
+ BOOST_CONSTEXPR basic_string_view() BOOST_NOEXCEPT
+ : ptr_(NULL), len_(0) {}
+
+ BOOST_CONSTEXPR basic_string_view(const basic_string_view &rhs) BOOST_NOEXCEPT
+ : ptr_(rhs.ptr_), len_(rhs.len_) {}
+
+ basic_string_view& operator=(const basic_string_view &rhs) BOOST_NOEXCEPT {
+ ptr_ = rhs.ptr_;
+ len_ = rhs.len_;
+ return *this;
+ }
+
+ template<typename Allocator>
+ basic_string_view(const std::basic_string<charT, traits,
+ Allocator>& str) BOOST_NOEXCEPT
+ : ptr_(str.data()), len_(str.length()) {}
+
+ BOOST_CONSTEXPR basic_string_view(const charT* str)
+ : ptr_(str), len_(traits::length(str)) {}
+
+ BOOST_CONSTEXPR basic_string_view(const charT* str, size_type len)
+ : ptr_(str), len_(len) {}
+
+ // iterators
+ BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT { return ptr_; }
+ BOOST_CONSTEXPR const_iterator cbegin() const BOOST_NOEXCEPT { return ptr_; }
+ BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT { return ptr_ + len_; }
+ BOOST_CONSTEXPR const_iterator cend() const BOOST_NOEXCEPT { return ptr_ + len_; }
+ const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); }
+ const_reverse_iterator crbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); }
+ const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); }
+ const_reverse_iterator crend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); }
+
+ // capacity
+ BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT { return len_; }
+ BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT { return len_; }
+ BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT { return len_; }
+ BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT { return len_ == 0; }
+
+ // element access
+ BOOST_CONSTEXPR const_reference operator[](size_type pos) const BOOST_NOEXCEPT { return ptr_[pos]; }
+
+ BOOST_CONSTEXPR const_reference at(size_t pos) const {
+ return pos >= len_ ? BOOST_THROW_EXCEPTION(std::out_of_range("boost::string_view::at")) : ptr_[pos];
+// if ( pos >= len_ )
+// BOOST_THROW_EXCEPTION( std::out_of_range ( "boost::string_view::at" ) );
+// return ptr_[pos];
+ }
+
+ BOOST_CONSTEXPR const_reference front() const { return ptr_[0]; }
+ BOOST_CONSTEXPR const_reference back() const { return ptr_[len_-1]; }
+ BOOST_CONSTEXPR const_pointer data() const BOOST_NOEXCEPT { return ptr_; }
+
+ // modifiers
+ void clear() BOOST_NOEXCEPT { len_ = 0; } // Boost extension
+
+ BOOST_CXX14_CONSTEXPR void remove_prefix(size_type n) {
+ if ( n > len_ )
+ n = len_;
+ ptr_ += n;
+ len_ -= n;
+ }
+
+ BOOST_CXX14_CONSTEXPR void remove_suffix(size_type n) {
+ if ( n > len_ )
+ n = len_;
+ len_ -= n;
+ }
+
+ BOOST_CXX14_CONSTEXPR void swap(basic_string_view& s) BOOST_NOEXCEPT {
+ std::swap(ptr_, s.ptr_);
+ std::swap(len_, s.len_);
+ }
+
+ // basic_string_view string operations
+#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
+ template<typename Allocator>
+ explicit operator std::basic_string<charT, traits, Allocator>() const {
+ return std::basic_string<charT, traits, Allocator>(begin(), end());
+ }
+#endif
+
+#ifndef BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS
+ template<typename Allocator = std::allocator<charT> >
+ std::basic_string<charT, traits> to_string(const Allocator& a = Allocator()) const {
+ return std::basic_string<charT, traits, Allocator>(begin(), end(), a);
+ }
+#else
+ std::basic_string<charT, traits> to_string() const {
+ return std::basic_string<charT, traits>(begin(), end());
+ }
+#endif
+
+ size_type copy(charT* s, size_type n, size_type pos=0) const {
+ if (pos > size())
+ BOOST_THROW_EXCEPTION(std::out_of_range("string_view::copy" ));
+ size_type rlen = (std::min)(n, len_ - pos);
+ // use std::copy(begin() + pos, begin() + pos + rlen, s) rather than
+ // std::copy_n(begin() + pos, rlen, s) to support pre-C++11 standard libraries
+ std::copy(begin() + pos, begin() + pos + rlen, s);
+ return rlen;
+ }
+
+ BOOST_CXX14_CONSTEXPR basic_string_view substr(size_type pos, size_type n=npos) const {
+ if ( pos > size())
+ BOOST_THROW_EXCEPTION( std::out_of_range ( "string_view::substr" ) );
+ if (n == npos || pos + n > size())
+ n = size () - pos;
+ return basic_string_view(data() + pos, n);
+ }
+
+ BOOST_CXX14_CONSTEXPR int compare(basic_string_view x) const BOOST_NOEXCEPT {
+ const int cmp = traits::compare(ptr_, x.ptr_, (std::min)(len_, x.len_));
+ return cmp != 0 ? cmp : (len_ == x.len_ ? 0 : len_ < x.len_ ? -1 : 1);
+ }
+
+ BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1, basic_string_view x)
+ const BOOST_NOEXCEPT {
+ return substr(pos1, n1).compare(x);
+ }
+
+ BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1,
+ basic_string_view x, size_type pos2, size_type n2) const {
+ return substr(pos1, n1).compare(x.substr(pos2, n2));
+ }
+
+ BOOST_CXX14_CONSTEXPR int compare(const charT* x) const {
+ return compare(basic_string_view(x));
+ }
+
+ BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1, const charT* x) const {
+ return substr(pos1, n1).compare(basic_string_view(x));
+ }
+
+ BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1,
+ const charT* x, size_type n2) const {
+ return substr(pos1, n1).compare(basic_string_view(x, n2));
+ }
+
+ // Searches
+ BOOST_CONSTEXPR bool starts_with(charT c) const BOOST_NOEXCEPT { // Boost extension
+ return !empty() && traits::eq(c, front());
+ }
+
+ BOOST_CONSTEXPR bool starts_with(basic_string_view x) const BOOST_NOEXCEPT { // Boost extension
+ return len_ >= x.len_ && traits::compare(ptr_, x.ptr_, x.len_) == 0;
+ }
+
+ BOOST_CONSTEXPR bool ends_with(charT c) const BOOST_NOEXCEPT { // Boost extension
+ return !empty() && traits::eq(c, back());
+ }
+
+ BOOST_CONSTEXPR bool ends_with(basic_string_view x) const BOOST_NOEXCEPT { // Boost extension
+ return len_ >= x.len_ &&
+ traits::compare(ptr_ + len_ - x.len_, x.ptr_, x.len_) == 0;
+ }
+
+ // find
+ BOOST_CXX14_CONSTEXPR size_type find(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT {
+ if (pos > size())
+ return npos;
+ if (s.empty())
+ return pos;
+ const_iterator iter = std::search(this->cbegin() + pos, this->cend(),
+ s.cbegin (), s.cend (), traits::eq);
+ return iter == this->cend () ? npos : std::distance(this->cbegin (), iter);
+ }
+ BOOST_CXX14_CONSTEXPR size_type find(charT c, size_type pos = 0) const BOOST_NOEXCEPT
+ { return find(basic_string_view(&c, 1), pos); }
+ BOOST_CXX14_CONSTEXPR size_type find(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
+ { return find(basic_string_view(s, n), pos); }
+ BOOST_CXX14_CONSTEXPR size_type find(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT
+ { return find(basic_string_view(s), pos); }
+
+ // rfind
+ BOOST_CXX14_CONSTEXPR size_type rfind(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT {
+ if (len_ < s.len_)
+ return npos;
+ if (pos > len_ - s.len_)
+ pos = len_ - s.len_;
+ if (s.len_ == 0u) // an empty string is always found
+ return pos;
+ for (const charT* cur = ptr_ + pos;; --cur) {
+ if (traits::compare(cur, s.ptr_, s.len_) == 0)
+ return cur - ptr_;
+ if (cur == ptr_)
+ return npos;
+ };
+ }
+ BOOST_CXX14_CONSTEXPR size_type rfind(charT c, size_type pos = npos) const BOOST_NOEXCEPT
+ { return rfind(basic_string_view(&c, 1), pos); }
+ BOOST_CXX14_CONSTEXPR size_type rfind(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
+ { return rfind(basic_string_view(s, n), pos); }
+ BOOST_CXX14_CONSTEXPR size_type rfind(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT
+ { return rfind(basic_string_view(s), pos); }
+
+ // find_first_of
+ BOOST_CXX14_CONSTEXPR size_type find_first_of(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT {
+ if (pos >= len_ || s.len_ == 0)
+ return npos;
+ const_iterator iter = std::find_first_of
+ (this->cbegin () + pos, this->cend (), s.cbegin (), s.cend (), traits::eq);
+ return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
+ }
+ BOOST_CXX14_CONSTEXPR size_type find_first_of(charT c, size_type pos = 0) const BOOST_NOEXCEPT
+ { return find_first_of(basic_string_view(&c, 1), pos); }
+ BOOST_CXX14_CONSTEXPR size_type find_first_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
+ { return find_first_of(basic_string_view(s, n), pos); }
+ BOOST_CXX14_CONSTEXPR size_type find_first_of(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT
+ { return find_first_of(basic_string_view(s), pos); }
+
+ // find_last_of
+ BOOST_CXX14_CONSTEXPR size_type find_last_of(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT {
+ if (s.len_ == 0u)
+ return npos;
+ if (pos >= len_)
+ pos = 0;
+ else
+ pos = len_ - (pos+1);
+ const_reverse_iterator iter = std::find_first_of
+ ( this->crbegin () + pos, this->crend (), s.cbegin (), s.cend (), traits::eq );
+ return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter);
+ }
+ BOOST_CXX14_CONSTEXPR size_type find_last_of(charT c, size_type pos = npos) const BOOST_NOEXCEPT
+ { return find_last_of(basic_string_view(&c, 1), pos); }
+ BOOST_CXX14_CONSTEXPR size_type find_last_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
+ { return find_last_of(basic_string_view(s, n), pos); }
+ BOOST_CXX14_CONSTEXPR size_type find_last_of(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT
+ { return find_last_of(basic_string_view(s), pos); }
+
+ // find_first_not_of
+ BOOST_CXX14_CONSTEXPR size_type find_first_not_of(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT {
+ if (pos >= len_)
+ return npos;
+ if (s.len_ == 0)
+ return pos;
+ const_iterator iter = find_not_of ( this->cbegin () + pos, this->cend (), s );
+ return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
+ }
+ BOOST_CXX14_CONSTEXPR size_type find_first_not_of(charT c, size_type pos = 0) const BOOST_NOEXCEPT
+ { return find_first_not_of(basic_string_view(&c, 1), pos); }
+ BOOST_CXX14_CONSTEXPR size_type find_first_not_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
+ { return find_first_not_of(basic_string_view(s, n), pos); }
+ BOOST_CXX14_CONSTEXPR size_type find_first_not_of(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT
+ { return find_first_not_of(basic_string_view(s), pos); }
+
+ // find_last_not_of
+ BOOST_CXX14_CONSTEXPR size_type find_last_not_of(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT {
+ if (pos >= len_)
+ pos = len_ - 1;;
+ if (s.len_ == 0u)
+ return pos;
+ pos = len_ - (pos+1);
+ const_reverse_iterator iter = find_not_of ( this->crbegin () + pos, this->crend (), s );
+ return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
+ }
+ BOOST_CXX14_CONSTEXPR size_type find_last_not_of(charT c, size_type pos = npos) const BOOST_NOEXCEPT
+ { return find_last_not_of(basic_string_view(&c, 1), pos); }
+ BOOST_CXX14_CONSTEXPR size_type find_last_not_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
+ { return find_last_not_of(basic_string_view(s, n), pos); }
+ BOOST_CXX14_CONSTEXPR size_type find_last_not_of(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT
+ { return find_last_not_of(basic_string_view(s), pos); }
+
+ private:
+ template <typename r_iter>
+ size_type reverse_distance(r_iter first, r_iter last) const BOOST_NOEXCEPT {
+ // Portability note here: std::distance is not NOEXCEPT, but calling it with a string_view::reverse_iterator will not throw.
+ return len_ - 1 - std::distance ( first, last );
+ }
+
+ template <typename Iterator>
+ Iterator find_not_of(Iterator first, Iterator last, basic_string_view s) const BOOST_NOEXCEPT {
+ for (; first != last ; ++first)
+ if ( 0 == traits::find(s.ptr_, s.len_, *first))
+ return first;
+ return last;
+ }
+
+ const charT *ptr_;
+ std::size_t len_;
+ };
+
+
+// Comparison operators
+// Equality
+ template<typename charT, typename traits>
+ inline bool operator==(basic_string_view<charT, traits> x,
+ basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
+ if (x.size () != y.size ()) return false;
+ return x.compare(y) == 0;
+ }
+
+// Inequality
+ template<typename charT, typename traits>
+ inline bool operator!=(basic_string_view<charT, traits> x,
+ basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
+ if ( x.size () != y.size ()) return true;
+ return x.compare(y) != 0;
+ }
+
+// Less than
+ template<typename charT, typename traits>
+ inline bool operator<(basic_string_view<charT, traits> x,
+ basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
+ return x.compare(y) < 0;
+ }
+
+// Greater than
+ template<typename charT, typename traits>
+ inline bool operator>(basic_string_view<charT, traits> x,
+ basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
+ return x.compare(y) > 0;
+ }
+
+// Less than or equal to
+ template<typename charT, typename traits>
+ inline bool operator<=(basic_string_view<charT, traits> x,
+ basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
+ return x.compare(y) <= 0;
+ }
+
+// Greater than or equal to
+ template<typename charT, typename traits>
+ inline bool operator>=(basic_string_view<charT, traits> x,
+ basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
+ return x.compare(y) >= 0;
+ }
+
+// "sufficient additional overloads of comparison functions"
+ template<typename charT, typename traits, typename Allocator>
+ inline bool operator==(basic_string_view<charT, traits> x,
+ const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
+ return x == basic_string_view<charT, traits>(y);
+ }
+
+ template<typename charT, typename traits, typename Allocator>
+ inline bool operator==(const std::basic_string<charT, traits, Allocator> & x,
+ basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
+ return basic_string_view<charT, traits>(x) == y;
+ }
+
+ template<typename charT, typename traits>
+ inline bool operator==(basic_string_view<charT, traits> x,
+ const charT * y) BOOST_NOEXCEPT {
+ return x == basic_string_view<charT, traits>(y);
+ }
+
+ template<typename charT, typename traits>
+ inline bool operator==(const charT * x,
+ basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
+ return basic_string_view<charT, traits>(x) == y;
+ }
+
+ template<typename charT, typename traits, typename Allocator>
+ inline bool operator!=(basic_string_view<charT, traits> x,
+ const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
+ return x != basic_string_view<charT, traits>(y);
+ }
+
+ template<typename charT, typename traits, typename Allocator>
+ inline bool operator!=(const std::basic_string<charT, traits, Allocator> & x,
+ basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
+ return basic_string_view<charT, traits>(x) != y;
+ }
+
+ template<typename charT, typename traits>
+ inline bool operator!=(basic_string_view<charT, traits> x,
+ const charT * y) BOOST_NOEXCEPT {
+ return x != basic_string_view<charT, traits>(y);
+ }
+
+ template<typename charT, typename traits>
+ inline bool operator!=(const charT * x,
+ basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
+ return basic_string_view<charT, traits>(x) != y;
+ }
+
+ template<typename charT, typename traits, typename Allocator>
+ inline bool operator<(basic_string_view<charT, traits> x,
+ const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
+ return x < basic_string_view<charT, traits>(y);
+ }
+
+ template<typename charT, typename traits, typename Allocator>
+ inline bool operator<(const std::basic_string<charT, traits, Allocator> & x,
+ basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
+ return basic_string_view<charT, traits>(x) < y;
+ }
+
+ template<typename charT, typename traits>
+ inline bool operator<(basic_string_view<charT, traits> x,
+ const charT * y) BOOST_NOEXCEPT {
+ return x < basic_string_view<charT, traits>(y);
+ }
+
+ template<typename charT, typename traits>
+ inline bool operator<(const charT * x,
+ basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
+ return basic_string_view<charT, traits>(x) < y;
+ }
+
+ template<typename charT, typename traits, typename Allocator>
+ inline bool operator>(basic_string_view<charT, traits> x,
+ const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
+ return x > basic_string_view<charT, traits>(y);
+ }
+
+ template<typename charT, typename traits, typename Allocator>
+ inline bool operator>(const std::basic_string<charT, traits, Allocator> & x,
+ basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
+ return basic_string_view<charT, traits>(x) > y;
+ }
+
+ template<typename charT, typename traits>
+ inline bool operator>(basic_string_view<charT, traits> x,
+ const charT * y) BOOST_NOEXCEPT {
+ return x > basic_string_view<charT, traits>(y);
+ }
+
+ template<typename charT, typename traits>
+ inline bool operator>(const charT * x,
+ basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
+ return basic_string_view<charT, traits>(x) > y;
+ }
+
+ template<typename charT, typename traits, typename Allocator>
+ inline bool operator<=(basic_string_view<charT, traits> x,
+ const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
+ return x <= basic_string_view<charT, traits>(y);
+ }
+
+ template<typename charT, typename traits, typename Allocator>
+ inline bool operator<=(const std::basic_string<charT, traits, Allocator> & x,
+ basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
+ return basic_string_view<charT, traits>(x) <= y;
+ }
+
+ template<typename charT, typename traits>
+ inline bool operator<=(basic_string_view<charT, traits> x,
+ const charT * y) BOOST_NOEXCEPT {
+ return x <= basic_string_view<charT, traits>(y);
+ }
+
+ template<typename charT, typename traits>
+ inline bool operator<=(const charT * x,
+ basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
+ return basic_string_view<charT, traits>(x) <= y;
+ }
+
+ template<typename charT, typename traits, typename Allocator>
+ inline bool operator>=(basic_string_view<charT, traits> x,
+ const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
+ return x >= basic_string_view<charT, traits>(y);
+ }
+
+ template<typename charT, typename traits, typename Allocator>
+ inline bool operator>=(const std::basic_string<charT, traits, Allocator> & x,
+ basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
+ return basic_string_view<charT, traits>(x) >= y;
+ }
+
+ template<typename charT, typename traits>
+ inline bool operator>=(basic_string_view<charT, traits> x,
+ const charT * y) BOOST_NOEXCEPT {
+ return x >= basic_string_view<charT, traits>(y);
+ }
+
+ template<typename charT, typename traits>
+ inline bool operator>=(const charT * x,
+ basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
+ return basic_string_view<charT, traits>(x) >= y;
+ }
+
+ namespace detail {
+
+ template<class charT, class traits>
+ inline void 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 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::insert_fill_chars(os, alignment_size);
+ if (os.good())
+ os.write(str.data(), size);
+ }
+ else {
+ os.write(str.data(), size);
+ if (os.good())
+ detail::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::insert_aligned(os, str);
+ os.width(0);
+ }
+ return os;
+ }
+
+#if 0
+ // numeric conversions
+ //
+ // These are short-term implementations.
+ // In a production environment, I would rather avoid the copying.
+ //
+ inline int stoi (string_view str, size_t* idx=0, int base=10) {
+ return std::stoi ( std::string(str), idx, base );
+ }
+
+ inline long stol (string_view str, size_t* idx=0, int base=10) {
+ return std::stol ( std::string(str), idx, base );
+ }
+
+ inline unsigned long stoul (string_view str, size_t* idx=0, int base=10) {
+ return std::stoul ( std::string(str), idx, base );
+ }
+
+ inline long long stoll (string_view str, size_t* idx=0, int base=10) {
+ return std::stoll ( std::string(str), idx, base );
+ }
+
+ inline unsigned long long stoull (string_view str, size_t* idx=0, int base=10) {
+ return std::stoull ( std::string(str), idx, base );
+ }
+
+ inline float stof (string_view str, size_t* idx=0) {
+ return std::stof ( std::string(str), idx );
+ }
+
+ inline double stod (string_view str, size_t* idx=0) {
+ return std::stod ( std::string(str), idx );
+ }
+
+ inline long double stold (string_view str, size_t* idx=0) {
+ return std::stold ( std::string(str), idx );
+ }
+
+ inline int stoi (wstring_view str, size_t* idx=0, int base=10) {
+ return std::stoi ( std::wstring(str), idx, base );
+ }
+
+ inline long stol (wstring_view str, size_t* idx=0, int base=10) {
+ return std::stol ( std::wstring(str), idx, base );
+ }
+
+ inline unsigned long stoul (wstring_view str, size_t* idx=0, int base=10) {
+ return std::stoul ( std::wstring(str), idx, base );
+ }
+
+ inline long long stoll (wstring_view str, size_t* idx=0, int base=10) {
+ return std::stoll ( std::wstring(str), idx, base );
+ }
+
+ inline unsigned long long stoull (wstring_view str, size_t* idx=0, int base=10) {
+ return std::stoull ( std::wstring(str), idx, base );
+ }
+
+ inline float stof (wstring_view str, size_t* idx=0) {
+ return std::stof ( std::wstring(str), idx );
+ }
+
+ inline double stod (wstring_view str, size_t* idx=0) {
+ return std::stod ( std::wstring(str), idx );
+ }
+
+ inline long double stold (wstring_view str, size_t* idx=0) {
+ return std::stold ( std::wstring(str), idx );
+ }
+#endif
+
+}
+
+#if 0
+namespace std {
+ // Hashing
+ template<> struct hash<boost::string_view>;
+ template<> struct hash<boost::u16string_view>;
+ template<> struct hash<boost::u32string_view>;
+ template<> struct hash<boost::wstring_view>;
+}
+#endif
+
+#endif
diff --git a/boost/utility/string_view_fwd.hpp b/boost/utility/string_view_fwd.hpp
new file mode 100644
index 0000000000..dbda0de46a
--- /dev/null
+++ b/boost/utility/string_view_fwd.hpp
@@ -0,0 +1,39 @@
+/*
+ Copyright (c) Marshall Clow 2012-2012.
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+ For more information, see http://www.boost.org
+
+ Based on the StringRef implementation in LLVM (http://llvm.org) and
+ N3422 by Jeffrey Yasskin
+ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
+ Updated July 2015 to reflect the Library Fundamentals TS
+ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html
+
+*/
+
+#ifndef BOOST_STRING_VIEW_FWD_HPP
+#define BOOST_STRING_VIEW_FWD_HPP
+
+#include <boost/config.hpp>
+#include <string>
+
+namespace boost {
+
+ template<typename charT, typename traits = std::char_traits<charT> > class basic_string_view;
+ typedef basic_string_view<char, std::char_traits<char> > string_view;
+ typedef basic_string_view<wchar_t, std::char_traits<wchar_t> > wstring_view;
+
+#ifndef BOOST_NO_CXX11_CHAR16_T
+ typedef basic_string_view<char16_t, std::char_traits<char16_t> > u16string_view;
+#endif
+
+#ifndef BOOST_NO_CXX11_CHAR32_T
+ typedef basic_string_view<char32_t, std::char_traits<char32_t> > u32string_view;
+#endif
+
+}
+
+#endif
diff --git a/boost/variant/recursive_wrapper_fwd.hpp b/boost/variant/recursive_wrapper_fwd.hpp
index b46774d92c..b42a68ffaf 100644
--- a/boost/variant/recursive_wrapper_fwd.hpp
+++ b/boost/variant/recursive_wrapper_fwd.hpp
@@ -15,6 +15,7 @@
#ifndef BOOST_VARIANT_RECURSIVE_WRAPPER_FWD_HPP
#define BOOST_VARIANT_RECURSIVE_WRAPPER_FWD_HPP
+#include <boost/mpl/bool.hpp>
#include "boost/mpl/aux_/config/ctps.hpp"
#include "boost/mpl/aux_/lambda_support.hpp"
#include <boost/type_traits/integral_constant.hpp>
diff --git a/boost/version.hpp b/boost/version.hpp
index fce02ec7ba..ce6f79f840 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 106000
+#define BOOST_VERSION 106100
//
// 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_60"
+#define BOOST_LIB_VERSION "1_61"
#endif