Skip to content

Instantly share code, notes, and snippets.

@dodheim
Created August 29, 2017 04:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dodheim/aeafdb2680bf1de575db42857675bb1c to your computer and use it in GitHub Desktop.
Save dodheim/aeafdb2680bf1de575db42857675bb1c to your computer and use it in GitHub Desktop.
Boost 1.65.0 patches (including MP11 and Range move algos)
Left base folder: C:\libs\boost_1_65_0_unpatched
Right base folder: C:\libs\boost_1_65_0_dod
--- boost\algorithm\cxx14\equal.hpp 2017-08-19 09:49:39.000000000 -0700
+++ boost\algorithm\cxx14\equal.hpp 2017-08-21 15:24:58.000000000 -0700
@@ -18,12 +18,15 @@
namespace boost { namespace algorithm {
namespace detail {
template <class T1, class T2>
struct eq {
+ typedef T1 first_argument_type;
+ typedef T2 second_argument_type;
+ typedef bool result_type;
bool operator () ( const T1& v1, const T2& v2 ) const { return v1 == v2 ;}
};
template <class RandomAccessIterator1, class RandomAccessIterator2, class BinaryPredicate>
bool equal ( RandomAccessIterator1 first1, RandomAccessIterator1 last1,
RandomAccessIterator2 first2, RandomAccessIterator2 last2, BinaryPredicate pred,
--- boost\algorithm\string\detail\case_conv.hpp 2017-08-19 09:49:39.000000000 -0700
+++ boost\algorithm\string\detail\case_conv.hpp 2017-08-21 15:25:28.000000000 -0700
@@ -10,13 +10,13 @@
#ifndef BOOST_STRING_CASE_CONV_DETAIL_HPP
#define BOOST_STRING_CASE_CONV_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
#include <locale>
-#include <functional>
+#include <algorithm>
#include <boost/type_traits/make_unsigned.hpp>
namespace boost {
namespace algorithm {
namespace detail {
--- boost\algorithm\string\detail\util.hpp 2017-08-19 09:49:39.000000000 -0700
+++ boost\algorithm\string\detail\util.hpp 2017-08-21 15:25:40.000000000 -0700
@@ -9,13 +9,13 @@
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_UTIL_DETAIL_HPP
#define BOOST_STRING_UTIL_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
-#include <functional>
+#include <cstddef>
#include <boost/range/iterator_range_core.hpp>
namespace boost {
namespace algorithm {
namespace detail {
--- boost\align\alignment_of.hpp 2017-08-19 09:49:39.000000000 -0700
+++ boost\align\alignment_of.hpp 2017-08-21 15:26:41.000000000 -0700
@@ -5,16 +5,17 @@
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_ALIGN_ALIGNMENT_OF_HPP
#define BOOST_ALIGN_ALIGNMENT_OF_HPP
+#include <boost/detail/workaround.hpp>
#include <boost/align/detail/element_type.hpp>
#include <boost/align/alignment_of_forward.hpp>
-#if defined(BOOST_MSVC)
+#if defined(BOOST_MSVC) && BOOST_WORKAROUND( BOOST_MSVC, < 1900 )
#include <boost/align/detail/alignment_of_msvc.hpp>
#elif defined(__GNUC__) && defined(__unix__) && !defined(__LP64__)
#include <boost/align/detail/alignment_of.hpp>
#elif defined(BOOST_CLANG) && !defined(__x86_64__)
#include <boost/align/detail/alignment_of.hpp>
#elif !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
--- boost\archive\iterators\xml_unescape.hpp 2017-08-19 09:49:48.000000000 -0700
+++ boost\archive\iterators\xml_unescape.hpp 2017-08-21 15:28:35.000000000 -0700
@@ -14,12 +14,13 @@
// License, Version 1.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 <boost/assert.hpp>
+#include <boost/detail/workaround.hpp>
#include <boost/serialization/throw_exception.hpp>
#include <boost/archive/iterators/unescape.hpp>
#include <boost/archive/iterators/dataflow_exception.hpp>
@@ -40,13 +41,13 @@
reference_type dereference() const {
return unescape<xml_unescape<Base>, Base>::dereference();
}
public:
// workaround msvc 7.1 ICU crash
- #if defined(BOOST_MSVC)
+ #if defined(BOOST_MSVC) && BOOST_WORKAROUND( BOOST_MSVC, < 1500 )
typedef int value_type;
#else
typedef typename this_t::value_type value_type;
#endif
void drain_residue(const char *literal);
--- boost\asio\impl\use_future.hpp 2017-08-19 09:49:39.000000000 -0700
+++ boost\asio\impl\use_future.hpp 2017-08-21 15:29:10.000000000 -0700
@@ -13,12 +13,13 @@
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
+#include <exception>
#include <future>
#include <boost/asio/async_result.hpp>
#include <boost/system/error_code.hpp>
#include <boost/asio/handler_type.hpp>
#include <boost/system/system_error.hpp>
#include <boost/asio/detail/memory.hpp>
@@ -43,23 +44,23 @@
BOOST_ASIO_REBIND_ALLOC(Alloc, char)(uf.get_allocator())))
{
}
void operator()(T t)
{
- promise_->set_value(t);
+ promise_->set_value(BOOST_ASIO_MOVE_CAST(T)(t));
}
void operator()(const boost::system::error_code& ec, T t)
{
if (ec)
promise_->set_exception(
std::make_exception_ptr(
boost::system::system_error(ec)));
else
- promise_->set_value(t);
+ promise_->set_value(BOOST_ASIO_MOVE_CAST(T)(t));
}
//private:
std::shared_ptr<std::promise<T> > promise_;
};
@@ -125,18 +126,18 @@
// The initiating function will return a future.
typedef std::future<T> type;
// Constructor creates a new promise for the async operation, and obtains the
// corresponding future.
explicit async_result(detail::promise_handler<T>& h)
+ : value_(h.promise_->get_future())
{
- value_ = h.promise_->get_future();
}
// Obtain the future to be returned from the initiating function.
- type get() { return std::move(value_); }
+ type get() { return BOOST_ASIO_MOVE_CAST(type)(value_); }
private:
type value_;
};
// Handler type specialisation for use_future.
--- boost\asio\buffer.hpp 2017-08-19 09:49:39.000000000 -0700
+++ boost\asio\buffer.hpp 2017-08-21 15:29:37.000000000 -0700
@@ -20,13 +20,14 @@
#include <cstring>
#include <string>
#include <vector>
#include <boost/asio/detail/array_fwd.hpp>
#if defined(BOOST_ASIO_MSVC)
-# if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0)
+# if (defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0)) \
+ || (defined(_ITERATOR_DEBUG_LEVEL) && (_ITERATOR_DEBUG_LEVEL == 2))
# if !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
# define BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
# endif // !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
# endif // defined(_HAS_ITERATOR_DEBUGGING)
#endif // defined(BOOST_ASIO_MSVC)
--- boost\chrono\duration.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\chrono\duration.hpp 2017-08-21 15:30:47.000000000 -0700
@@ -432,15 +432,15 @@
private:
rep rep_;
public:
#if defined BOOST_CHRONO_DURATION_DEFAULTS_TO_ZERO
BOOST_FORCEINLINE BOOST_CONSTEXPR
- duration() : rep_(duration_values<rep>::zero()) { }
+ duration() BOOST_NOEXCEPT_OR_NOTHROW : rep_(duration_values<rep>::zero()) { }
#elif defined BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
- BOOST_CONSTEXPR duration() {}
+ BOOST_CONSTEXPR duration() BOOST_NOEXCEPT_OR_NOTHROW {}
#else
BOOST_CONSTEXPR duration() = default;
#endif
template <class Rep2>
BOOST_SYMBOL_VISIBLE BOOST_FORCEINLINE BOOST_CONSTEXPR
explicit duration(const Rep2& r
@@ -455,13 +455,13 @@
>
>
>
>::type* = 0
) : rep_(r) { }
#if defined BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
- duration& operator=(const duration& rhs)
+ duration& operator=(const duration& rhs) BOOST_NOEXCEPT_OR_NOTHROW
{
if (&rhs != this) rep_= rhs.rep_;
return *this;
}
#else
duration& operator=(const duration& rhs) = default;
--- boost\config\compiler\clang.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\compiler\clang.hpp 2017-08-28 19:23:29.000000000 -0700
@@ -315,13 +315,18 @@
# define BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS
#endif
// Clang has supported the 'unused' attribute since the first release.
#define BOOST_ATTRIBUTE_UNUSED __attribute__((__unused__))
+// Type aliasing hint.
+#if __has_attribute(__may_alias__)
+# define BOOST_MAY_ALIAS __attribute__((__may_alias__))
+#endif
+
#ifndef BOOST_COMPILER
# define BOOST_COMPILER "Clang version " __clang_version__
#endif
// Macro used to identify the Clang compiler.
#define BOOST_CLANG 1
--- boost\config\compiler\cray.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\compiler\cray.hpp 2017-08-28 19:23:29.000000000 -0700
@@ -7,25 +7,25 @@
// See http://www.boost.org for most recent version.
// Greenhills C compiler setup:
#define BOOST_COMPILER "Cray C version " BOOST_STRINGIZE(_RELEASE)
-#if _RELEASE < 8
+#if _RELEASE_MAJOR < 8
# error "Boost is not configured for Cray compilers prior to version 8, please try the configure script."
#endif
//
// Check this is a recent EDG based compiler, otherwise we don't support it here:
//
#ifndef __EDG_VERSION__
# error "Unsupported Cray compiler, please try running the configure script."
#endif
+#if _RELEASE_MINOR < 5 || __cplusplus < 201100
#include <boost/config/compiler/common_edg.hpp>
-
//
//
#define BOOST_NO_CXX11_STATIC_ASSERT
#define BOOST_NO_CXX11_AUTO_DECLARATIONS
#define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS
@@ -87,8 +87,38 @@
#define __ATOMIC_ACQUIRE 2
#define __ATOMIC_RELEASE 3
#define __ATOMIC_ACQ_REL 4
#define __ATOMIC_SEQ_CST 5
#endif
+#else /* _RELEASE_MINOR */
+#define BOOST_HAS_VARIADIC_TMPL
+#define BOOST_HAS_UNISTD_H
+#define BOOST_HAS_TR1_COMPLEX_INVERSE_TRIG
+#define BOOST_HAS_TR1_COMPLEX_OVERLOADS
+#define BOOST_HAS_STDINT_H
+#define BOOST_HAS_STATIC_ASSERT
+#define BOOST_HAS_SIGACTION
+#define BOOST_HAS_SCHED_YIELD
+#define BOOST_HAS_RVALUE_REFS
+#define BOOST_HAS_PTHREADS
+#define BOOST_HAS_PTHREAD_YIELD
+#define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
+#define BOOST_HAS_PARTIAL_STD_ALLOCATOR
+#define BOOST_HAS_NRVO
+#define BOOST_HAS_NL_TYPES_H
+#define BOOST_HAS_NANOSLEEP
+#define BOOST_NO_CXX11_SMART_PTR
+#define BOOST_NO_CXX11_HDR_FUNCTIONAL
+#define BOOST_NO_CXX14_CONSTEXPR
+#define BOOST_HAS_LONG_LONG
+#define BOOST_HAS_FLOAT128
+#if __cplusplus < 201400
+#define BOOST_NO_CXX11_DECLTYPE_N3276
+#endif /* __cpluspus */
+
+#endif /* _RELEASE_MINOR */
+
+
+
--- boost\config\compiler\gcc.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\compiler\gcc.hpp 2017-08-28 19:23:29.000000000 -0700
@@ -312,12 +312,16 @@
//
// Unused attribute:
#if __GNUC__ >= 4
# define BOOST_ATTRIBUTE_UNUSED __attribute__((__unused__))
#endif
+
+// Type aliasing hint. Supported since gcc 3.3.
+#define BOOST_MAY_ALIAS __attribute__((__may_alias__))
+
//
// __builtin_unreachable:
#if BOOST_GCC_VERSION >= 40800
#define BOOST_UNREACHABLE_RETURN(x) __builtin_unreachable();
#endif
@@ -335,17 +339,17 @@
// versions check:
// we don't know gcc prior to version 3.30:
#if (BOOST_GCC_VERSION< 30300)
# error "Compiler not configured - please reconfigure"
#endif
//
-// last known and checked version is 4.9:
-#if (BOOST_GCC_VERSION > 40900)
+// last known and checked version is 7.1:
+#if (BOOST_GCC_VERSION > 70100)
# if defined(BOOST_ASSERT_CONFIG)
-# error "Unknown compiler version - please run the configure tests and report the results"
+# error "Boost.Config is older than your compiler - please check for an updated Boost release."
# else
// we don't emit warnings here anymore since there are no defect macros defined for
// gcc post 3.4, so any failures are gcc regressions...
//# warning "Unknown compiler version - please run the configure tests and report the results"
# endif
#endif
--- boost\config\compiler\intel.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\compiler\intel.hpp 2017-08-28 19:23:29.000000000 -0700
@@ -308,12 +308,18 @@
//
#if defined(__GNUC__) && (__GNUC__ >= 4)
# define BOOST_SYMBOL_EXPORT __attribute__((visibility("default")))
# define BOOST_SYMBOL_IMPORT
# define BOOST_SYMBOL_VISIBLE __attribute__((visibility("default")))
#endif
+
+// Type aliasing hint
+#if defined(__GNUC__) && (BOOST_INTEL_CXX_VERSION >= 1300)
+# define BOOST_MAY_ALIAS __attribute__((__may_alias__))
+#endif
+
//
// C++0x features
// For each feature we need to check both the Intel compiler version,
// and the version of MSVC or GCC that we are emulating.
// See http://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler/
// for a list of which features were implemented in which Intel releases.
@@ -542,16 +548,16 @@
#endif // defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500) && (defined(_MSC_VER) || defined(__GNUC__))
//
// last known and checked version:
#if (BOOST_INTEL_CXX_VERSION > 1700)
# if defined(BOOST_ASSERT_CONFIG)
-# error "Unknown compiler version - please run the configure tests and report the results"
+# error "Boost.Config is older than your compiler - please check for an updated Boost release."
# elif defined(_MSC_VER)
//
// We don't emit this warning any more, since we have so few
// defect macros set anyway (just the one).
//
//# pragma message("Unknown compiler version - please run the configure tests and report the results")
# endif
#endif
--- boost\config\compiler\nvcc.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\compiler\nvcc.hpp 2017-08-24 14:56:41.000000000 -0700
@@ -8,25 +8,32 @@
// NVIDIA CUDA C++ compiler setup
#ifndef BOOST_COMPILER
# define BOOST_COMPILER "NVIDIA CUDA C++ Compiler"
#endif
+#if defined(__CUDACC_VER_MAJOR__) && defined(__CUDACC_VER_MINOR__) && defined(__CUDACC_VER_BUILD__)
+# define BOOST_CUDA_VERSION __CUDACC_VER_MAJOR__ * 1000000 + __CUDACC_VER_MINOR__ * 10000 + __CUDACC_VER_BUILD__
+#else
+// We don't really know what the CUDA version is, but it's definitely before 7.5:
+# define BOOST_CUDA_VERSION 7000000
+#endif
+
// 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)
+#if BOOST_CUDA_VERSION < 7050000
# define BOOST_NO_CXX11_VARIADIC_TEMPLATES
#endif
// The same bug is back again in 8.0:
-#if (__CUDACC_VER__ > 80000) && (__CUDACC_VER__ < 80100)
+#if (BOOST_CUDA_VERSION > 8000000) && (BOOST_CUDA_VERSION < 8010000)
# define BOOST_NO_CXX11_VARIADIC_TEMPLATES
#endif
// Most recent CUDA (8.0) has no constexpr support in msvc mode:
#if defined(_MSC_VER)
# define BOOST_NO_CXX11_CONSTEXPR
#endif
@@ -40,12 +47,12 @@
# define BOOST_NO_CXX11_UNICODE_LITERALS
#endif
//
// And this one effects the NVCC front end,
// See https://svn.boost.org/trac/boost/ticket/13049
//
-#if (__CUDACC_VER__ >= 80000) && (__CUDACC_VER__ < 80100)
+#if (BOOST_CUDA_VERSION >= 8000000) && (BOOST_CUDA_VERSION < 8010000)
# define BOOST_NO_CXX11_NOEXCEPT
#endif
#endif
--- boost\config\compiler\pgi.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\compiler\pgi.hpp 2017-08-28 19:23:29.000000000 -0700
@@ -1,168 +1,23 @@
// (C) Copyright Noel Belcourt 2007.
+// Copyright 2017, NVIDIA CORPORATION.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
// PGI C++ compiler setup:
#define BOOST_COMPILER_VERSION __PGIC__##__PGIC_MINOR__
#define BOOST_COMPILER "PGI compiler version " BOOST_STRINGIZE(BOOST_COMPILER_VERSION)
-//
-// Threading support:
-// Turn this on unconditionally here, it will get turned off again later
-// if no threading API is detected.
-//
-
-#if __PGIC__ >= 11
-
-// options requested by configure --enable-test
-#define BOOST_HAS_PTHREADS
-#define BOOST_HAS_THREADS
-#define BOOST_HAS_PTHREAD_YIELD
-#define BOOST_HAS_NRVO
-#define BOOST_HAS_LONG_LONG
+// PGI is mostly GNU compatible. So start with that.
+#include <boost/config/compiler/gcc.hpp>
-// options --enable-test wants undefined
-#undef BOOST_NO_STDC_NAMESPACE
-#undef BOOST_NO_EXCEPTION_STD_NAMESPACE
-#undef BOOST_DEDUCED_TYPENAME
+// Now adjust for things that are different.
-#define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL
-#define BOOST_NO_TWO_PHASE_NAME_LOOKUP
-#define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS
-#define BOOST_NO_CXX11_AUTO_DECLARATIONS
-
-#elif __PGIC__ >= 10
-
-// options requested by configure --enable-test
-#define BOOST_HAS_THREADS
-#define BOOST_HAS_NRVO
-#define BOOST_HAS_LONG_LONG
-#if defined(linux) || defined(__linux) || defined(__linux__)
-# define BOOST_HAS_STDINT_H
-#endif
+// __float128 is a typedef, not a distinct type.
+#undef BOOST_HAS_FLOAT128
-// options --enable-test wants undefined
-#undef BOOST_NO_STDC_NAMESPACE
-#undef BOOST_NO_EXCEPTION_STD_NAMESPACE
-#undef BOOST_DEDUCED_TYPENAME
-
-#elif __PGIC__ >= 7
-
-#define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL
-#define BOOST_NO_TWO_PHASE_NAME_LOOKUP
-#define BOOST_NO_SWPRINTF
-#define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS
-#define BOOST_NO_CXX11_AUTO_DECLARATIONS
-
-#else
-
-# error "Pgi compiler not configured - please reconfigure"
-
-#endif
-//
-// C++0x features
-//
-// See boost\config\suffix.hpp for BOOST_NO_LONG_LONG
-//
-#define BOOST_NO_CXX11_CHAR16_T
-#define BOOST_NO_CXX11_CHAR32_T
-#define BOOST_NO_CXX11_CONSTEXPR
-#define BOOST_NO_CXX11_DECLTYPE
-#define BOOST_NO_CXX11_DECLTYPE_N3276
-#define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
-#define BOOST_NO_CXX11_DELETED_FUNCTIONS
-#define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
-#define BOOST_NO_CXX11_EXTERN_TEMPLATE
-#define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS
-#define BOOST_NO_CXX11_LAMBDAS
-#define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS
-#define BOOST_NO_CXX11_NOEXCEPT
-#define BOOST_NO_CXX11_NULLPTR
-#define BOOST_NO_CXX11_NUMERIC_LIMITS
-#define BOOST_NO_CXX11_RANGE_BASED_FOR
-#define BOOST_NO_CXX11_RAW_LITERALS
-#define BOOST_NO_CXX11_RVALUE_REFERENCES
-#define BOOST_NO_CXX11_SCOPED_ENUMS
-#define BOOST_NO_SFINAE_EXPR
-#define BOOST_NO_CXX11_SFINAE_EXPR
-#define BOOST_NO_CXX11_STATIC_ASSERT
-#define BOOST_NO_SWPRINTF
-#define BOOST_NO_CXX11_TEMPLATE_ALIASES
-#define BOOST_NO_CXX11_UNICODE_LITERALS
-#define BOOST_NO_CXX11_VARIADIC_TEMPLATES
-#define BOOST_NO_CXX11_VARIADIC_MACROS
-#define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
-
-#define BOOST_NO_CXX11_HDR_UNORDERED_SET
-#define BOOST_NO_CXX11_HDR_UNORDERED_MAP
-#define BOOST_NO_CXX11_HDR_TYPEINDEX
-#define BOOST_NO_CXX11_HDR_TYPE_TRAITS
-#define BOOST_NO_CXX11_HDR_TUPLE
-#define BOOST_NO_CXX11_HDR_THREAD
-#define BOOST_NO_CXX11_HDR_SYSTEM_ERROR
-#define BOOST_NO_CXX11_HDR_REGEX
-#define BOOST_NO_CXX11_HDR_RATIO
-#define BOOST_NO_CXX11_HDR_RANDOM
-#define BOOST_NO_CXX11_HDR_MUTEX
-#define BOOST_NO_CXX11_HDR_INITIALIZER_LIST
-#define BOOST_NO_CXX11_HDR_FUTURE
-#define BOOST_NO_CXX11_HDR_FORWARD_LIST
-#define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE
-#define BOOST_NO_CXX11_HDR_CODECVT
-#define BOOST_NO_CXX11_HDR_CHRONO
-#define BOOST_NO_CXX11_HDR_ARRAY
-#define BOOST_NO_CXX11_USER_DEFINED_LITERALS
-#define BOOST_NO_CXX11_ALIGNAS
-#define BOOST_NO_CXX11_TRAILING_RESULT_TYPES
-#define BOOST_NO_CXX11_INLINE_NAMESPACES
-#define BOOST_NO_CXX11_REF_QUALIFIERS
-#define BOOST_NO_CXX11_FINAL
-#define BOOST_NO_CXX11_THREAD_LOCAL
-
-// C++ 14:
-#if !defined(__cpp_aggregate_nsdmi) || (__cpp_aggregate_nsdmi < 201304)
-# define BOOST_NO_CXX14_AGGREGATE_NSDMI
-#endif
-#if !defined(__cpp_binary_literals) || (__cpp_binary_literals < 201304)
-# define BOOST_NO_CXX14_BINARY_LITERALS
-#endif
-#if !defined(__cpp_constexpr) || (__cpp_constexpr < 201304)
-# define BOOST_NO_CXX14_CONSTEXPR
-#endif
-#if !defined(__cpp_decltype_auto) || (__cpp_decltype_auto < 201304)
-# define BOOST_NO_CXX14_DECLTYPE_AUTO
-#endif
-#if (__cplusplus < 201304) // There's no SD6 check for this....
-# define BOOST_NO_CXX14_DIGIT_SEPARATORS
-#endif
-#if !defined(__cpp_generic_lambdas) || (__cpp_generic_lambdas < 201304)
-# define BOOST_NO_CXX14_GENERIC_LAMBDAS
-#endif
-#if !defined(__cpp_init_captures) || (__cpp_init_captures < 201304)
-# define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES
-#endif
-#if !defined(__cpp_return_type_deduction) || (__cpp_return_type_deduction < 201304)
-# define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION
-#endif
-#if !defined(__cpp_variable_templates) || (__cpp_variable_templates < 201304)
-# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
-#endif
-
-// C++17
-#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606)
-# define BOOST_NO_CXX17_STRUCTURED_BINDINGS
-#endif
-#if !defined(__cpp_inline_variables) || (__cpp_inline_variables < 201606)
-# define BOOST_NO_CXX17_INLINE_VARIABLES
-#endif
-#if !defined(__cpp_fold_expressions) || (__cpp_fold_expressions < 201603)
-# define BOOST_NO_CXX17_FOLD_EXPRESSIONS
-#endif
-//
-// version check:
-// probably nothing to do here?
-
+// __int128 is not supported.
+#undef BOOST_HAS_INT128
--- boost\config\compiler\sunpro_cc.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\compiler\sunpro_cc.hpp 2017-08-24 14:59:12.000000000 -0700
@@ -199,12 +199,12 @@
// versions check:
// we don't support sunpro prior to version 4:
#if __SUNPRO_CC < 0x400
#error "Compiler not supported or configured - please reconfigure"
#endif
//
-// last known and checked version is 0x590:
-#if (__SUNPRO_CC > 0x590)
+// last known and checked version:
+#if (__SUNPRO_CC > 0x5150)
# if defined(BOOST_ASSERT_CONFIG)
-# error "Unknown compiler version - please run the configure tests and report the results"
+# error "Boost.Config is older than your compiler - please check for an updated Boost release."
# endif
#endif
--- boost\config\compiler\vacpp.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\compiler\vacpp.hpp 2017-08-28 19:23:29.000000000 -0700
@@ -62,12 +62,17 @@
// Some versions of the compiler have issues with default arguments on partial specializations
#if __IBMCPP__ <= 1010
#define BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS
#endif
+// Type aliasing hint. Supported since XL C++ 13.1
+#if (__IBMCPP__ >= 1310)
+# define BOOST_MAY_ALIAS __attribute__((__may_alias__))
+#endif
+
//
// C++0x features
//
// See boost\config\suffix.hpp for BOOST_NO_LONG_LONG
//
#if ! __IBMCPP_AUTO_TYPEDEDUCTION
--- boost\config\compiler\visualc.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\compiler\visualc.hpp 2017-08-24 15:01:53.000000000 -0700
@@ -104,17 +104,26 @@
# define BOOST_NO_RTTI
#endif
//
// TR1 features:
//
-#if (_MSC_VER >= 1700) && defined(_HAS_CXX17) && (_HAS_CXX17 > 0)
-// # define BOOST_HAS_TR1_HASH // don't know if this is true yet.
-// # define BOOST_HAS_TR1_TYPE_TRAITS // don't know if this is true yet.
-# define BOOST_HAS_TR1_UNORDERED_MAP
-# define BOOST_HAS_TR1_UNORDERED_SET
+#if (_MSC_VER >= 1700)
+# define BOOST_HAS_TR1_HASH
+# define BOOST_HAS_TR1_TYPE_TRAITS
+# define BOOST_HAS_TR1_UNORDERED_MAP
+# define BOOST_HAS_TR1_UNORDERED_SET
+#endif
+#if (_MSC_FULL_VER >= 190024210) && \
+ ((defined(_HAS_TR1_NAMESPACE) && !_HAS_TR1_NAMESPACE) || (!defined(_HAS_TR1_NAMESPACE) && \
+ ((defined(_HAS_CXX17) && _HAS_CXX17) || (!defined(_HAS_CXX17) && \
+ defined(_MSVC_LANG) && (_MSVC_LANG > 201402)))))
+# undef BOOST_HAS_TR1_HASH
+# undef BOOST_HAS_TR1_TYPE_TRAITS
+# undef BOOST_HAS_TR1_UNORDERED_MAP
+# undef BOOST_HAS_TR1_UNORDERED_SET
#endif
//
// C++0x features
//
// See above for BOOST_NO_LONG_LONG
@@ -187,16 +196,27 @@
#if (_MSC_FULL_VER < 190024210)
# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
# define BOOST_NO_SFINAE_EXPR
# define BOOST_NO_CXX11_CONSTEXPR
#endif
-// C++14 features supported by VC++ 14.1 (Visual Studio 2017)
+// C++14 features supported by VC++ 14.10 (Visual Studio 2017)
//
#if (_MSC_VER < 1910)
# define BOOST_NO_CXX14_AGGREGATE_NSDMI
+#endif
+
+// C++17 features supported by VC++ 14.11 (Visual Studio 2017 Update 3)
+//
+#if (_MSC_VER < 1911)
+# define BOOST_NO_CXX11_SFINAE_EXPR
+# define BOOST_NO_CXX14_CONSTEXPR
+# define BOOST_NO_CXX17_STRUCTURED_BINDINGS
+#elif (defined(_HAS_CXX17) && !_HAS_CXX17) || (!defined(_HAS_CXX17) && \
+ (!defined(_MSVC_LANG) || (_MSVC_LANG <= 201402)))
+# define BOOST_NO_CXX17_STRUCTURED_BINDINGS
#endif
// MSVC including version 14 has not yet completely
// implemented value-initialization, as is reported:
// "VC++ does not value-initialize members of derived classes without
// user-declared constructor", reported in 2009 by Sylvester Hesp:
@@ -209,21 +229,15 @@
// https://connect.microsoft.com/VisualStudio/feedback/details/100744
// Reported again by John Maddock in 2015 for VC14:
// https://connect.microsoft.com/VisualStudio/feedback/details/1582233/c-subobjects-still-not-value-initialized-correctly
// See also: http://www.boost.org/libs/utility/value_init.htm#compiler_issues
// (Niels Dekker, LKEB, May 2010)
#define BOOST_NO_COMPLETE_VALUE_INITIALIZATION
-//
-// C++ 11:
-//
+// C++:
#define BOOST_NO_TWO_PHASE_NAME_LOOKUP
-#define BOOST_NO_CXX11_SFINAE_EXPR
-// C++ 14:
-# define BOOST_NO_CXX14_CONSTEXPR
// C++ 17:
-#define BOOST_NO_CXX17_STRUCTURED_BINDINGS
#define BOOST_NO_CXX17_INLINE_VARIABLES
#define BOOST_NO_CXX17_FOLD_EXPRESSIONS
//
// Things that don't work in clr mode:
//
@@ -286,13 +300,13 @@
# error "Unknown EVC++ compiler version - please run the configure tests and report the results"
# else
# pragma message("Unknown EVC++ compiler version - please run the configure tests and report the results")
# endif
# endif
# else
-# if _MSC_VER < 1310
+# if _MSC_VER < 1200
// Note: Versions up to 7.0 aren't supported.
# define BOOST_COMPILER_VERSION 5.0
# elif _MSC_VER < 1300
# define BOOST_COMPILER_VERSION 6.0
# elif _MSC_VER < 1310
# define BOOST_COMPILER_VERSION 7.0
@@ -307,25 +321,27 @@
# elif _MSC_VER < 1800
# define BOOST_COMPILER_VERSION 11.0
# elif _MSC_VER < 1900
# define BOOST_COMPILER_VERSION 12.0
# elif _MSC_VER < 1910
# define BOOST_COMPILER_VERSION 14.0
+# elif _MSC_VER < 1911
+# define BOOST_COMPILER_VERSION 14.10
# elif _MSC_VER < 1920
-# define BOOST_COMPILER_VERSION 14.1
+# define BOOST_COMPILER_VERSION 14.11
# else
# define BOOST_COMPILER_VERSION _MSC_VER
# endif
# endif
# define BOOST_COMPILER "Microsoft Visual C++ version " BOOST_STRINGIZE(BOOST_COMPILER_VERSION)
#endif
//
-// last known and checked version is 19.10.25017 (VC++ 2017):
-#if (_MSC_VER > 1910)
+// last known and checked version is 19.11.25506 (VC++ 2017.3):
+#if (_MSC_VER > 1911)
# if defined(BOOST_ASSERT_CONFIG)
-# error "Unknown compiler version - please run the configure tests and report the results"
-# else
-# pragma message("Unknown compiler version - please run the configure tests and report the results")
+# error "Boost.Config is older than your current compiler version."
+# elif !defined(BOOST_CONFIG_SUPPRESS_OUTDATED_MESSAGE)
+# pragma message("Info: Boost.Config is older than your compiler version - probably nothing bad will happen - but you may wish to look for an update Boost version. Define BOOST_CONFIG_SUPPRESS_OUTDATED_MESSAGE to suppress this message.")
# endif
#endif
--- boost\config\compiler\xlcpp.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\compiler\xlcpp.hpp 2017-08-28 19:23:30.000000000 -0700
@@ -264,13 +264,18 @@
// Unused attribute:
#if defined(__GNUC__) && (__GNUC__ >= 4)
# define BOOST_ATTRIBUTE_UNUSED __attribute__((unused))
#endif
+// Type aliasing hint.
+#if __has_attribute(__may_alias__)
+# define BOOST_MAY_ALIAS __attribute__((__may_alias__))
+#endif
+
#ifndef BOOST_COMPILER
# define BOOST_COMPILER "Clang version " __clang_version__
#endif
// Macro used to identify the Clang compiler.
#define BOOST_CLANG 1
--- boost\config\compiler\xlcpp_zos.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\compiler\xlcpp_zos.hpp 2017-08-28 19:23:30.000000000 -0700
@@ -156,13 +156,14 @@
// -------------------------------------
#if defined(__IBM_ATTRIBUTES)
# define BOOST_FORCEINLINE inline __attribute__ ((__always_inline__))
# define BOOST_NOINLINE __attribute__ ((__noinline__))
+# define BOOST_MAY_ALIAS __attribute__((__may_alias__))
// No BOOST_ALIGNMENT - explicit alignment support is broken (V2R1).
#endif
extern "builtin" long __builtin_expect(long, long);
#define BOOST_LIKELY(x) __builtin_expect((x) && true, 1)
#define BOOST_UNLIKELY(x) __builtin_expect((x) && true, 0)
--- boost\config\detail\select_compiler_config.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\detail\select_compiler_config.hpp 2017-08-28 19:23:30.000000000 -0700
@@ -49,12 +49,16 @@
# define BOOST_COMPILER_CONFIG "boost/config/compiler/digitalmars.hpp"
#elif defined __DCC__
// Wind River Diab C++
# define BOOST_COMPILER_CONFIG "boost/config/compiler/diab.hpp"
+#elif defined(__PGI)
+// Portland Group Inc.
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/pgi.hpp"
+
# elif defined(__GNUC__) && !defined(__ibmxl__)
// GNU C++:
# define BOOST_COMPILER_CONFIG "boost/config/compiler/gcc.hpp"
#elif defined __KCC
// Kai C++
@@ -105,16 +109,12 @@
# define BOOST_COMPILER_CONFIG "boost/config/compiler/xlcpp.hpp"
#elif defined(__IBMCPP__)
// IBM Visual Age or IBM XL C/C++ for Linux (Big Endian)
# define BOOST_COMPILER_CONFIG "boost/config/compiler/vacpp.hpp"
-#elif defined(__PGI)
-// Portland Group Inc.
-# define BOOST_COMPILER_CONFIG "boost/config/compiler/pgi.hpp"
-
#elif defined _MSC_VER
// Microsoft Visual C++
//
// Must remain the last #elif since some other vendors (Metrowerks, for
// example) also #define _MSC_VER
# define BOOST_COMPILER_CONFIG "boost/config/compiler/visualc.hpp"
--- boost\config\detail\suffix.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\detail\suffix.hpp 2017-08-28 19:27:01.000000000 -0700
@@ -599,12 +599,20 @@
# if !defined(BOOST_NO_RESTRICT_REFERENCES)
# define BOOST_NO_RESTRICT_REFERENCES
# endif
# endif
#endif
+// BOOST_MAY_ALIAS -----------------------------------------------//
+// The macro expands to an attribute to mark a type that is allowed to alias other types.
+// The macro is defined in the compiler-specific headers.
+#if !defined(BOOST_MAY_ALIAS)
+# define BOOST_NO_MAY_ALIAS
+# define BOOST_MAY_ALIAS
+#endif
+
// BOOST_FORCEINLINE ---------------------------------------------//
// Macro to use in place of 'inline' to force a function to be inline
#if !defined(BOOST_FORCEINLINE)
# if defined(_MSC_VER)
# define BOOST_FORCEINLINE __forceinline
# elif defined(__GNUC__) && __GNUC__ > 3
@@ -1022,17 +1030,23 @@
// BOOST_NO_CXX11_VARIADIC_TEMPLATES is set:
//
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS)
# define BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS
#endif
+#if defined(BOOST_MSVC) && BOOST_MSVC_FULL_VER >= 190023918
+# define BOOST_EMPTYBASES __declspec(empty_bases)
+#else
+# define BOOST_EMPTYBASES
+#endif
+
//
// Finish off with checks for macros that are depricated / no longer supported,
// if any of these are set then it's very likely that much of Boost will no
// longer work. So stop with a #error for now, but give the user a chance
// to continue at their own risk if they really want to:
//
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_CONFIG_ALLOW_DEPRECATED)
# error "You are using a compiler which lacks features which are now a minimum requirement in order to use Boost, define BOOST_CONFIG_ALLOW_DEPRECATED if you want to continue at your own risk!!!"
#endif
#endif
--- boost\config\stdlib\dinkumware.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\stdlib\dinkumware.hpp 2017-08-28 20:38:02.000000000 -0700
@@ -145,15 +145,15 @@
# define BOOST_NO_CXX11_ALLOCATOR
// 540 has std::align but it is not a conforming implementation
# define BOOST_NO_CXX11_STD_ALIGN
#endif
// Before 650 std::pointer_traits has a broken rebind template
-#if !defined(_CPPLIB_VER) || _CPPLIB_VER < 650
+#if !defined(_CPPLIB_VER) || (_CPPLIB_VER < 650)
# define BOOST_NO_CXX11_POINTER_TRAITS
-#elif defined(BOOST_MSVC) && BOOST_MSVC < 1910
+#elif (defined(BOOST_MSVC) || (defined(__clang__) && defined(_MSC_VER))) && (_MSC_VER < 1910)
# define BOOST_NO_CXX11_POINTER_TRAITS
#endif
#if defined(__has_include)
#if !__has_include(<shared_mutex>)
# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
@@ -167,17 +167,22 @@
// C++14 features
#if !defined(_CPPLIB_VER) || (_CPPLIB_VER < 650)
# define BOOST_NO_CXX14_STD_EXCHANGE
#endif
// C++17 features
-#if !defined(_CPPLIB_VER) || (_CPPLIB_VER < 650) || !defined(BOOST_MSVC) || (BOOST_MSVC < 1910) || !defined(_HAS_CXX17) || (_HAS_CXX17 == 0)
+#if !(defined(_CPPLIB_VER) && (_CPPLIB_VER >= 650) && \
+ defined(_MSC_VER) && (_MSC_VER >= 1910) && \
+ ((defined(__clang__) && (__cplusplus > 201402)) || \
+ (defined(BOOST_MSVC) && ((defined(_HAS_CXX17) && _HAS_CXX17) || (!defined(_HAS_CXX17) && \
+ defined(_MSVC_LANG) && (_MSVC_LANG > 201402))))))
# define BOOST_NO_CXX17_STD_APPLY
#endif
#if !defined(_CPPLIB_VER) || (_CPPLIB_VER < 650)
# define BOOST_NO_CXX17_STD_INVOKE
+# define BOOST_NO_CXX17_ITERATOR_TRAITS
#endif
#if defined(BOOST_INTEL) && (BOOST_INTEL <= 1400)
// Intel's compiler can't handle this header yet:
# define BOOST_NO_CXX11_HDR_ATOMIC
#endif
@@ -197,13 +202,16 @@
#endif
#if defined(_CPPLIB_VER) && (_CPPLIB_VER >= 650)
// If _HAS_AUTO_PTR_ETC is defined to 0, std::auto_ptr and std::random_shuffle are not available.
// See https://www.visualstudio.com/en-us/news/vs2015-vs.aspx#C++
// and http://blogs.msdn.com/b/vcblog/archive/2015/06/19/c-11-14-17-features-in-vs-2015-rtm.aspx
-# if defined(_HAS_AUTO_PTR_ETC) && (_HAS_AUTO_PTR_ETC == 0)
+# if (defined(_HAS_AUTO_PTR_ETC) && !_HAS_AUTO_PTR_ETC) || (!defined(_HAS_AUTO_PTR_ETC) && \
+ ((defined(_HAS_CXX17) && _HAS_CXX17) || (!defined(_HAS_CXX17) && \
+ ((defined(BOOST_MSVC) && defined(_MSVC_LANG) && (_MSVC_LANG > 201402)) || \
+ (defined(__clang__) && (__cplusplus > 201402))))))
# define BOOST_NO_AUTO_PTR
# define BOOST_NO_CXX98_RANDOM_SHUFFLE
# define BOOST_NO_CXX98_FUNCTION_BASE
# define BOOST_NO_CXX98_BINDERS
# endif
#endif
--- boost\config\stdlib\libcomo.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\stdlib\libcomo.hpp 2017-08-28 19:23:30.000000000 -0700
@@ -76,16 +76,17 @@
// C++14 features
# define BOOST_NO_CXX14_STD_EXCHANGE
// C++17 features
# define BOOST_NO_CXX17_STD_APPLY
# define BOOST_NO_CXX17_STD_INVOKE
+# define BOOST_NO_CXX17_ITERATOR_TRAITS
//
// Intrinsic type_traits support.
// The SGI STL has it's own __type_traits class, which
// has intrinsic compiler support with SGI's compilers.
// Whatever map SGI style type traits to boost equivalents:
//
#define BOOST_HAS_SGI_TYPE_TRAITS
#define BOOST_STDLIB "Comeau standard library " BOOST_STRINGIZE(__LIBCOMO_VERSION__)
--- boost\config\stdlib\libcpp.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\stdlib\libcpp.hpp 2017-08-28 19:23:30.000000000 -0700
@@ -100,12 +100,14 @@
# define BOOST_NO_CXX98_RANDOM_SHUFFLE
#endif
#if (_LIBCPP_VERSION > 4000) && (__cplusplus > 201402L) && !defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS)
# define BOOST_NO_CXX98_BINDERS
#endif
+#define BOOST_NO_CXX17_ITERATOR_TRAITS
+
#if (_LIBCPP_VERSION <= 1101) && !defined(BOOST_NO_CXX11_THREAD_LOCAL)
// This is a bit of a sledgehammer, because really it's just libc++abi that has no
// support for thread_local, leading to linker errors such as
// "undefined reference to `__cxa_thread_atexit'". It is fixed in the
// most recent releases of libc++abi though...
# define BOOST_NO_CXX11_THREAD_LOCAL
--- boost\config\stdlib\libstdcpp3.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\stdlib\libstdcpp3.hpp 2017-08-28 19:23:30.000000000 -0700
@@ -244,12 +244,13 @@
// C++0x features in GCC 4.6.0 and later
//
#if (BOOST_LIBSTDCXX_VERSION < 40600) || !defined(BOOST_LIBSTDCXX11)
# define BOOST_NO_CXX11_HDR_TYPEINDEX
# define BOOST_NO_CXX11_ADDRESSOF
+# define BOOST_NO_CXX17_ITERATOR_TRAITS
#endif
// C++0x features in GCC 4.7.0 and later
//
#if (BOOST_LIBSTDCXX_VERSION < 40700) || !defined(BOOST_LIBSTDCXX11)
// Note that although <chrono> existed prior to 4.7, "steady_clock" is spelled "monotonic_clock"
--- boost\config\stdlib\modena.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\stdlib\modena.hpp 2017-08-28 19:23:30.000000000 -0700
@@ -65,13 +65,14 @@
// C++14 features
# define BOOST_NO_CXX14_STD_EXCHANGE
// C++17 features
# define BOOST_NO_CXX17_STD_APPLY
# define BOOST_NO_CXX17_STD_INVOKE
+# define BOOST_NO_CXX17_ITERATOR_TRAITS
#define BOOST_STDLIB "Modena C++ standard library"
--- boost\config\stdlib\msl.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\stdlib\msl.hpp 2017-08-28 19:23:30.000000000 -0700
@@ -89,8 +89,9 @@
// C++14 features
# define BOOST_NO_CXX14_STD_EXCHANGE
// C++17 features
# define BOOST_NO_CXX17_STD_APPLY
# define BOOST_NO_CXX17_STD_INVOKE
+# define BOOST_NO_CXX17_ITERATOR_TRAITS
#define BOOST_STDLIB "Metrowerks Standard Library version " BOOST_STRINGIZE(__MSL_CPP__)
--- boost\config\stdlib\roguewave.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\stdlib\roguewave.hpp 2017-08-28 19:23:30.000000000 -0700
@@ -201,6 +201,7 @@
// C++14 features
# define BOOST_NO_CXX14_STD_EXCHANGE
// C++17 features
# define BOOST_NO_CXX17_STD_APPLY
# define BOOST_NO_CXX17_STD_INVOKE
+# define BOOST_NO_CXX17_ITERATOR_TRAITS
--- boost\config\stdlib\sgi.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\stdlib\sgi.hpp 2017-08-28 19:23:30.000000000 -0700
@@ -159,8 +159,9 @@
// C++14 features
# define BOOST_NO_CXX14_STD_EXCHANGE
// C++17 features
# define BOOST_NO_CXX17_STD_APPLY
# define BOOST_NO_CXX17_STD_INVOKE
+# define BOOST_NO_CXX17_ITERATOR_TRAITS
#define BOOST_STDLIB "SGI standard library"
--- boost\config\stdlib\stlport.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\stdlib\stlport.hpp 2017-08-28 19:23:30.000000000 -0700
@@ -249,8 +249,9 @@
// C++14 features
# define BOOST_NO_CXX14_STD_EXCHANGE
// C++17 features
# define BOOST_NO_CXX17_STD_APPLY
# define BOOST_NO_CXX17_STD_INVOKE
+# define BOOST_NO_CXX17_ITERATOR_TRAITS
#define BOOST_STDLIB "STLPort standard library version " BOOST_STRINGIZE(__SGI_STL_PORT)
--- boost\config\stdlib\vacpp.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\stdlib\vacpp.hpp 2017-08-28 19:23:30.000000000 -0700
@@ -65,8 +65,9 @@
// C++14 features
# define BOOST_NO_CXX14_STD_EXCHANGE
// C++17 features
# define BOOST_NO_CXX17_STD_APPLY
# define BOOST_NO_CXX17_STD_INVOKE
+# define BOOST_NO_CXX17_ITERATOR_TRAITS
#define BOOST_STDLIB "Visual Age default standard library"
--- boost\config\stdlib\xlcpp_zos.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\config\stdlib\xlcpp_zos.hpp 2017-08-28 19:23:30.000000000 -0700
@@ -54,6 +54,7 @@
#define BOOST_NO_CXX14_STD_EXCHANGE
#define BOOST_NO_CXX14_HDR_SHARED_MUTEX
#define BOOST_NO_CXX17_STD_INVOKE
#define BOOST_NO_CXX17_STD_APPLY
+#define BOOST_NO_CXX17_ITERATOR_TRAITS
--- boost\container\flat_map.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\container\flat_map.hpp 2017-08-21 15:37:00.000000000 -0700
@@ -196,12 +196,13 @@
//
//////////////////////////////////////////////
//! <b>Effects</b>: Default constructs an empty flat_map.
//!
//! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
flat_map() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
container_detail::is_nothrow_default_constructible<Compare>::value)
: m_flat_tree()
{}
//! <b>Effects</b>: Constructs an empty flat_map using the specified allocator.
--- boost\container\flat_set.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\container\flat_set.hpp 2017-08-21 15:37:53.000000000 -0700
@@ -124,14 +124,14 @@
//////////////////////////////////////////////
//! <b>Effects</b>: Default constructs an empty container.
//!
//! <b>Complexity</b>: Constant.
BOOST_CONTAINER_FORCEINLINE
- explicit flat_set() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
- container_detail::is_nothrow_default_constructible<Compare>::value)
+ flat_set() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
+ container_detail::is_nothrow_default_constructible<Compare>::value)
: base_t()
{}
//! <b>Effects</b>: Constructs an empty container using the specified
//! comparison object.
//!
@@ -1078,14 +1078,15 @@
typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_iterator) const_iterator;
typedef typename BOOST_CONTAINER_IMPDEF(base_t::reverse_iterator) reverse_iterator;
typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_reverse_iterator) const_reverse_iterator;
typedef typename BOOST_CONTAINER_IMPDEF(base_t::sequence_type) sequence_type;
//! @copydoc ::boost::container::flat_set::flat_set()
- BOOST_CONTAINER_FORCEINLINE explicit flat_multiset() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
- container_detail::is_nothrow_default_constructible<Compare>::value)
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multiset() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value &&
+ container_detail::is_nothrow_default_constructible<Compare>::value)
: base_t()
{}
//! @copydoc ::boost::container::flat_set::flat_set(const Compare&)
BOOST_CONTAINER_FORCEINLINE explicit flat_multiset(const Compare& comp)
: base_t(comp)
--- boost\context\detail\config.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\context\detail\config.hpp 2017-08-21 15:38:39.000000000 -0700
@@ -62,16 +62,16 @@
// 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
+# undef BOOST_CONTEXT_NO_CXX14_INTEGER_SEQUENCE
#endif
// workaround: Xcode clang feature detection
-#if ! defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence >= 201304
+#if ! defined(__cpp_lib_integer_sequence) && defined(_LIBCPP_STD_VER)
# if _LIBCPP_STD_VER > 11
# undef BOOST_CONTEXT_NO_CXX14_INTEGER_SEQUENCE
# endif
#endif
// workaroud: MSVC 14 does support constexpr
--- boost\context\continuation_fcontext.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\context\continuation_fcontext.hpp 2017-08-25 01:20:20.000000000 -0700
@@ -92,13 +92,13 @@
auto p = static_cast< std::tuple< Fn > * >( t.data);
BOOST_ASSERT( nullptr != p);
typename std::decay< Fn >::type fn = std::get< 0 >( * p);
t.data = nullptr;
Ctx c{ t.fctx };
// execute function, pass continuation via reference
- fn( std::move( c) );
+ c = fn( std::move( c) );
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
return { exchange( c.fctx_, nullptr), nullptr };
#else
return { std::exchange( c.fctx_, nullptr), nullptr };
#endif
}
--- boost\context\continuation_ucontext.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\context\continuation_ucontext.hpp 2017-08-25 01:21:28.000000000 -0700
@@ -81,24 +81,24 @@
record->run();
}
struct BOOST_CONTEXT_DECL activation_record {
thread_local static activation_record * current_rec;
- ucontext_t uctx{};
- stack_context sctx{};
- bool main_ctx{ true };
- activation_record * from{ nullptr };
- std::function< void(activation_record*&) > ontop{};
- bool terminated{ false };
- bool force_unwind{ false };
+ ucontext_t uctx{};
+ stack_context sctx{};
+ bool main_ctx{ true };
+ activation_record * from{ nullptr };
+ std::function< activation_record*(activation_record*&) > ontop{};
+ bool terminated{ false };
+ bool force_unwind{ false };
#if defined(BOOST_USE_ASAN)
- void * fake_stack{ nullptr };
- void * stack_bottom{ nullptr };
- std::size_t stack_size{ 0 };
- bool started{ false };
+ void * fake_stack{ nullptr };
+ void * stack_bottom{ nullptr };
+ std::size_t stack_size{ 0 };
+ bool started{ false };
#endif
static activation_record *& current() noexcept;
// used for toplevel-context
// (e.g. main context, thread-entry context)
@@ -165,26 +165,36 @@
// returned by continuation::current()
current() = this;
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
current()->ontop = std::bind(
[](typename std::decay< Fn >::type & fn, activation_record *& ptr){
Ctx c{ ptr };
- fn( std::move( c) );
+ c = fn( std::move( c) );
if ( ! c) {
ptr = nullptr;
}
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ return exchange( c.ptr_, nullptr);
+#else
+ return std::exchange( c.ptr_, nullptr);
+#endif
},
std::forward< Fn >( fn),
std::placeholders::_1);
#else
current()->ontop = [fn=std::forward<Fn>(fn)](activation_record *& ptr){
Ctx c{ ptr };
- fn( std::move( c) );
+ c = fn( std::move( c) );
if ( ! c) {
ptr = nullptr;
}
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ return exchange( c.ptr_, nullptr);
+#else
+ return std::exchange( c.ptr_, nullptr);
+#endif
};
#endif
#if defined(BOOST_USE_SEGMENTED_STACKS)
// adjust segmented stack properties
__splitstack_getcontext( from->sctx.segments_ctx);
__splitstack_setcontext( sctx.segments_ctx);
@@ -405,13 +415,13 @@
#else
detail::activation_record * ptr = std::exchange( ptr_, nullptr)->resume();
#endif
if ( BOOST_UNLIKELY( detail::activation_record::current()->force_unwind) ) {
throw detail::forced_unwind{ ptr};
} else if ( BOOST_UNLIKELY( nullptr != detail::activation_record::current()->ontop) ) {
- detail::activation_record::current()->ontop( ptr);
+ ptr = detail::activation_record::current()->ontop( ptr);
detail::activation_record::current()->ontop = nullptr;
}
return continuation{ ptr };
}
template< typename Fn >
@@ -423,13 +433,13 @@
detail::activation_record * ptr =
std::exchange( ptr_, nullptr)->resume_with< continuation >( std::forward< Fn >( fn) );
#endif
if ( BOOST_UNLIKELY( detail::activation_record::current()->force_unwind) ) {
throw detail::forced_unwind{ ptr};
} else if ( BOOST_UNLIKELY( nullptr != detail::activation_record::current()->ontop) ) {
- detail::activation_record::current()->ontop( ptr);
+ ptr = detail::activation_record::current()->ontop( ptr);
detail::activation_record::current()->ontop = nullptr;
}
return continuation{ ptr };
}
explicit operator bool() const noexcept {
--- boost\context\continuation_winfib.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\context\continuation_winfib.hpp 2017-08-25 01:22:26.000000000 -0700
@@ -62,19 +62,19 @@
record->run();
}
struct BOOST_CONTEXT_DECL activation_record {
thread_local static activation_record * current_rec;
- LPVOID fiber{ nullptr };
- stack_context sctx{};
- bool main_ctx{ true };
- activation_record * from{ nullptr };
- std::function< void(activation_record*&) > ontop{};
- bool terminated{ false };
- bool force_unwind{ false };
+ LPVOID fiber{ nullptr };
+ stack_context sctx{};
+ bool main_ctx{ true };
+ activation_record * from{ nullptr };
+ std::function< activation_record*(activation_record*&) > ontop{};
+ bool terminated{ false };
+ bool force_unwind{ false };
static activation_record *& current() noexcept;
// used for toplevel-context
// (e.g. main context, thread-entry context)
activation_record() noexcept {
@@ -139,26 +139,36 @@
// returned by continuation::current()
current() = this;
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
current()->ontop = std::bind(
[](typename std::decay< Fn >::type & fn, activation_record *& ptr){
Ctx c{ ptr };
- fn( std::move( c) );
+ c = fn( std::move( c) );
if ( ! c) {
ptr = nullptr;
}
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ return exchange( c.ptr_, nullptr);
+#else
+ return std::exchange( c.ptr_, nullptr);
+#endif
},
std::forward< Fn >( fn),
std::placeholders::_1);
#else
current()->ontop = [fn=std::forward<Fn>(fn)](activation_record *& ptr){
Ctx c{ ptr };
- fn( std::move( c) );
+ c = fn( std::move( c) );
if ( ! c) {
ptr = nullptr;
}
+#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
+ return exchange( c.ptr_, nullptr);
+#else
+ return std::exchange( c.ptr_, nullptr);
+#endif
};
#endif
// context switch
::SwitchToFiber( fiber);
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
return detail::exchange( current()->from, nullptr);
@@ -333,13 +343,13 @@
#else
detail::activation_record * ptr = std::exchange( ptr_, nullptr)->resume();
#endif
if ( BOOST_UNLIKELY( detail::activation_record::current()->force_unwind) ) {
throw detail::forced_unwind{ ptr};
} else if ( BOOST_UNLIKELY( nullptr != detail::activation_record::current()->ontop) ) {
- detail::activation_record::current()->ontop( ptr);
+ ptr = detail::activation_record::current()->ontop( ptr);
detail::activation_record::current()->ontop = nullptr;
}
return continuation{ ptr };
}
template< typename Fn >
@@ -351,13 +361,13 @@
detail::activation_record * ptr =
std::exchange( ptr_, nullptr)->resume_with< continuation >( std::forward< Fn >( fn) );
#endif
if ( BOOST_UNLIKELY( detail::activation_record::current()->force_unwind) ) {
throw detail::forced_unwind{ ptr};
} else if ( BOOST_UNLIKELY( nullptr != detail::activation_record::current()->ontop) ) {
- detail::activation_record::current()->ontop( ptr);
+ ptr = detail::activation_record::current()->ontop( ptr);
detail::activation_record::current()->ontop = nullptr;
}
return continuation{ ptr };
}
explicit operator bool() const noexcept {
--- boost\coroutine\detail\push_coroutine_impl.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\coroutine\detail\push_coroutine_impl.hpp 2017-08-25 01:26:08.000000000 -0700
@@ -51,12 +51,14 @@
caller_( caller),
callee_( callee)
{
if ( unwind) flags_ |= flag_force_unwind;
}
+ virtual ~push_coroutine_impl() {}
+
bool force_unwind() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_force_unwind); }
bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
@@ -141,12 +143,14 @@
caller_( caller),
callee_( callee)
{
if ( unwind) flags_ |= flag_force_unwind;
}
+ virtual ~push_coroutine_impl() {}
+
bool force_unwind() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_force_unwind); }
bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
@@ -214,12 +218,14 @@
caller_( caller),
callee_( callee)
{
if ( unwind) flags_ |= flag_force_unwind;
}
+ virtual ~push_coroutine_impl() {}
+
inline bool force_unwind() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_force_unwind); }
inline bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
--- boost\coroutine2\detail\pull_control_block_cc.ipp 2017-08-19 09:49:40.000000000 -0700
+++ boost\coroutine2\detail\pull_control_block_cc.ipp 2017-08-25 01:28:52.000000000 -0700
@@ -100,12 +100,15 @@
// set termination flags
state |= state_t::complete;
// jump back
return other->c.resume();
});
#endif
+ if ( except) {
+ std::rethrow_exception( except);
+ }
}
template< typename T >
pull_coroutine< T >::control_block::control_block( typename push_coroutine< T >::control_block * cb,
boost::context::continuation & c_) noexcept :
c{ std::move( c_) },
@@ -247,12 +250,15 @@
// set termination flags
state |= state_t::complete;
// jump back
return other->c.resume();
});
#endif
+ if ( except) {
+ std::rethrow_exception( except);
+ }
}
template< typename T >
pull_coroutine< T & >::control_block::control_block( typename push_coroutine< T & >::control_block * cb,
boost::context::continuation & c_) noexcept :
c{ std::move( c_) },
@@ -368,12 +374,15 @@
// set termination flags
state |= state_t::complete;
// jump back to ctx
return other->c.resume();
});
#endif
+ if ( except) {
+ std::rethrow_exception( except);
+ }
}
inline
pull_coroutine< void >::control_block::control_block( push_coroutine< void >::control_block * cb,
boost::context::continuation & c_) noexcept :
c{ std::move( c_) },
--- boost\date_time\gregorian\greg_year.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\date_time\gregorian\greg_year.hpp 2017-08-28 19:11:27.000000000 -0700
@@ -27,16 +27,16 @@
//! Policy class that declares error handling gregorian year type
typedef CV::simple_exception_policy<unsigned short, 1400, 10000, bad_year> greg_year_policies;
//! Generated representation for gregorian year
typedef CV::constrained_value<greg_year_policies> greg_year_rep;
- //! Represent a day of the month (range 1900 - 10000)
+ //! Represent a year (range 1400 - 10000)
/*! This small class allows for simple conversion an integer value into
a year for the gregorian calendar. This currently only allows a
- range of 1900 to 10000. Both ends of the range are a bit arbitrary
+ range of 1400 to 10000. Both ends of the range are a bit arbitrary
at the moment, but they are the limits of current testing of the
library. As such they may be increased in the future.
*/
class BOOST_SYMBOL_VISIBLE greg_year : public greg_year_rep {
public:
greg_year(unsigned short year) : greg_year_rep(year) {}
--- boost\date_time\posix_time\conversion.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\date_time\posix_time\conversion.hpp 2017-08-28 19:15:39.000000000 -0700
@@ -77,13 +77,13 @@
*
* \note FILETIME is part of the Win32 API, so it is not portable to non-windows
* platforms.
*
* \note The function is templated on the FILETIME type, so that
* it can be used with both native FILETIME and the ad-hoc
- * boost::date_time::winapi::file_time type.
+ * boost::detail::winapi::FILETIME_ type.
*/
template< typename TimeT, typename FileTimeT >
inline
TimeT from_ftime(const FileTimeT& ft)
{
return boost::date_time::time_from_ftime<TimeT>(ft);
--- boost\date_time\adjust_functors.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\date_time\adjust_functors.hpp 2017-08-28 19:11:26.000000000 -0700
@@ -1,69 +1,69 @@
#ifndef _DATE_TIME_ADJUST_FUNCTORS_HPP___
#define _DATE_TIME_ADJUST_FUNCTORS_HPP___
/* Copyright (c) 2002,2003 CrystalClear Software, Inc.
- * Use, modification and distribution is subject to the
+ * Use, modification and distribution is subject to the
* Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
* Author: Jeff Garland, Bart Garst
* $Date$
*/
#include "boost/date_time/date.hpp"
#include "boost/date_time/wrapping_int.hpp"
namespace boost {
namespace date_time {
-
+
//! Functor to iterate a fixed number of days
template<class date_type>
- class day_functor
+ class day_functor
{
public:
typedef typename date_type::duration_type duration_type;
day_functor(int f) : f_(f) {}
- duration_type get_offset(const date_type& d) const
+ duration_type get_offset(const date_type& d) const
{
// why is 'd' a parameter???
// fix compiler warnings
d.year();
return duration_type(f_);
}
- duration_type get_neg_offset(const date_type& d) const
+ duration_type get_neg_offset(const date_type& d) const
{
// fix compiler warnings
d.year();
return duration_type(-f_);
}
private:
int f_;
};
//! Provides calculation to find next nth month given a date
/*! This adjustment function provides the logic for 'month-based'
- * advancement on a ymd based calendar. The policy it uses
+ * advancement on a ymd based calendar. The policy it uses
* to handle the non existant end of month days is to back
* up to the last day of the month. Also, if the starting
* date is the last day of a month, this functor will attempt
* to adjust to the end of the month.
*/
template<class date_type>
- class month_functor
+ class month_functor
{
public:
typedef typename date_type::duration_type duration_type;
typedef typename date_type::calendar_type cal_type;
typedef typename cal_type::ymd_type ymd_type;
typedef typename cal_type::day_type day_type;
month_functor(int f) : f_(f), origDayOfMonth_(0) {}
- duration_type get_offset(const date_type& d) const
+ duration_type get_offset(const date_type& d) const
{
ymd_type ymd(d.year_month_day());
if (origDayOfMonth_ == 0) {
origDayOfMonth_ = ymd.day;
day_type endOfMonthDay(cal_type::end_of_month_day(ymd.year,ymd.month));
if (endOfMonthDay == ymd.day) {
@@ -71,13 +71,13 @@
}
}
typedef date_time::wrapping_int2<short,1,12> wrap_int2;
typedef typename wrap_int2::int_type int_type;
wrap_int2 wi(ymd.month);
//calc the year wrap around, add() returns 0 or 1 if wrapped
- int_type year = wi.add(static_cast<int_type>(f_));
+ int_type year = wi.add(f_);
year = static_cast<int_type>(year + ymd.year); //calculate resulting year
// std::cout << "trace wi: " << wi.as_int() << std::endl;
// std::cout << "trace year: " << year << std::endl;
//find the last day for the new month
day_type resultingEndOfMonthDay(cal_type::end_of_month_day(year, wi.as_int()));
//original was the end of month -- force to last day of month
@@ -88,13 +88,13 @@
if (dayOfMonth > resultingEndOfMonthDay) {
dayOfMonth = resultingEndOfMonthDay;
}
return date_type(year, wi.as_int(), dayOfMonth) - d;
}
//! Returns a negative duration_type
- duration_type get_neg_offset(const date_type& d) const
+ duration_type get_neg_offset(const date_type& d) const
{
ymd_type ymd(d.year_month_day());
if (origDayOfMonth_ == 0) {
origDayOfMonth_ = ymd.day;
day_type endOfMonthDay(cal_type::end_of_month_day(ymd.year,ymd.month));
if (endOfMonthDay == ymd.day) {
@@ -102,13 +102,13 @@
}
}
typedef date_time::wrapping_int2<short,1,12> wrap_int2;
typedef typename wrap_int2::int_type int_type;
wrap_int2 wi(ymd.month);
//calc the year wrap around, add() returns 0 or 1 if wrapped
- int_type year = wi.subtract(static_cast<int_type>(f_));
+ int_type year = wi.subtract(f_);
year = static_cast<int_type>(year + ymd.year); //calculate resulting year
//find the last day for the new month
day_type resultingEndOfMonthDay(cal_type::end_of_month_day(year, wi.as_int()));
//original was the end of month -- force to last day of month
if (origDayOfMonth_ == -1) {
return date_type(year, wi.as_int(), resultingEndOfMonthDay) - d;
@@ -124,55 +124,55 @@
mutable short origDayOfMonth_;
};
//! Functor to iterate a over weeks
template<class date_type>
- class week_functor
+ class week_functor
{
public:
typedef typename date_type::duration_type duration_type;
typedef typename date_type::calendar_type calendar_type;
week_functor(int f) : f_(f) {}
- duration_type get_offset(const date_type& d) const
+ duration_type get_offset(const date_type& d) const
{
// why is 'd' a parameter???
// fix compiler warnings
d.year();
return duration_type(f_*calendar_type::days_in_week());
}
- duration_type get_neg_offset(const date_type& d) const
+ duration_type get_neg_offset(const date_type& d) const
{
// fix compiler warnings
d.year();
return duration_type(-f_*calendar_type::days_in_week());
}
private:
int f_;
};
//! Functor to iterate by a year adjusting for leap years
template<class date_type>
- class year_functor
+ class year_functor
{
public:
//typedef typename date_type::year_type year_type;
typedef typename date_type::duration_type duration_type;
year_functor(int f) : _mf(f * 12) {}
- duration_type get_offset(const date_type& d) const
+ duration_type get_offset(const date_type& d) const
{
return _mf.get_offset(d);
}
- duration_type get_neg_offset(const date_type& d) const
+ duration_type get_neg_offset(const date_type& d) const
{
return _mf.get_neg_offset(d);
}
private:
month_functor<date_type> _mf;
};
-
+
} }//namespace date_time
#endif
--- boost\date_time\filetime_functions.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\date_time\filetime_functions.hpp 2017-08-28 19:15:39.000000000 -0700
@@ -16,139 +16,53 @@
*/
#include <boost/date_time/compiler_config.hpp>
#if defined(BOOST_HAS_FTIME) // skip this file if no FILETIME
-#if defined(BOOST_USE_WINDOWS_H)
-# include <windows.h>
-#endif
-
#include <boost/cstdint.hpp>
#include <boost/date_time/time.hpp>
#include <boost/date_time/date_defs.hpp>
namespace boost {
namespace date_time {
-namespace winapi {
-
-#if !defined(BOOST_USE_WINDOWS_H)
-
- extern "C" {
-
- struct FILETIME
- {
- boost::uint32_t dwLowDateTime;
- boost::uint32_t dwHighDateTime;
- };
- struct SYSTEMTIME
- {
- boost::uint16_t wYear;
- boost::uint16_t wMonth;
- boost::uint16_t wDayOfWeek;
- boost::uint16_t wDay;
- boost::uint16_t wHour;
- boost::uint16_t wMinute;
- boost::uint16_t wSecond;
- boost::uint16_t wMilliseconds;
- };
-
- __declspec(dllimport) void __stdcall GetSystemTimeAsFileTime(FILETIME* lpFileTime);
- __declspec(dllimport) int __stdcall FileTimeToLocalFileTime(const FILETIME* lpFileTime, FILETIME* lpLocalFileTime);
- __declspec(dllimport) void __stdcall GetSystemTime(SYSTEMTIME* lpSystemTime);
- __declspec(dllimport) int __stdcall SystemTimeToFileTime(const SYSTEMTIME* lpSystemTime, FILETIME* lpFileTime);
-
- } // extern "C"
-
-#endif // defined(BOOST_USE_WINDOWS_H)
-
- typedef FILETIME file_time;
- typedef SYSTEMTIME system_time;
-
- inline void get_system_time_as_file_time(file_time& ft)
- {
-#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205))
- // Some runtime library implementations expect local times as the norm for ctime.
- file_time ft_utc;
- GetSystemTimeAsFileTime(&ft_utc);
- FileTimeToLocalFileTime(&ft_utc, &ft);
-#elif defined(BOOST_HAS_GETSYSTEMTIMEASFILETIME)
- GetSystemTimeAsFileTime(&ft);
-#else
- system_time st;
- GetSystemTime(&st);
- SystemTimeToFileTime(&st, &ft);
-#endif
- }
-
- /*!
- * The function converts file_time into number of microseconds elapsed since 1970-Jan-01
- *
- * \note Only dates after 1970-Jan-01 are supported. Dates before will be wrapped.
- *
- * \note The function is templated on the FILETIME type, so that
- * it can be used with both native FILETIME and the ad-hoc
- * boost::date_time::winapi::file_time type.
- */
- template< typename FileTimeT >
- inline boost::uint64_t file_time_to_microseconds(FileTimeT const& ft)
- {
- /* shift is difference between 1970-Jan-01 & 1601-Jan-01
- * in 100-nanosecond intervals */
- const uint64_t shift = 116444736000000000ULL; // (27111902 << 32) + 3577643008
-
- union {
- FileTimeT as_file_time;
- uint64_t as_integer; // 100-nanos since 1601-Jan-01
- } caster;
- caster.as_file_time = ft;
-
- caster.as_integer -= shift; // filetime is now 100-nanos since 1970-Jan-01
- return (caster.as_integer / 10); // truncate to microseconds
- }
-
-} // namespace winapi
-
//! Create a time object from an initialized FILETIME struct.
/*!
* Create a time object from an initialized FILETIME struct.
* A FILETIME struct holds 100-nanosecond units (0.0000001). When
* built with microsecond resolution the file_time's sub second value
* will be truncated. Nanosecond resolution has no truncation.
*
* \note The function is templated on the FILETIME type, so that
* it can be used with both native FILETIME and the ad-hoc
- * boost::date_time::winapi::file_time type.
+ * boost::detail::winapi::FILETIME_ type.
*/
template< typename TimeT, typename FileTimeT >
inline
TimeT time_from_ftime(const FileTimeT& ft)
{
typedef typename TimeT::date_type date_type;
typedef typename TimeT::date_duration_type date_duration_type;
typedef typename TimeT::time_duration_type time_duration_type;
// https://svn.boost.org/trac/boost/ticket/2523
// Since this function can be called with arbitrary times, including ones that
// are before 1970-Jan-01, we'll have to cast the time a bit differently,
- // than it is done in the file_time_to_microseconds function. This allows to
+ // than it is done in the microsec_clock::file_time_to_microseconds function. This allows to
// avoid integer wrapping for dates before 1970-Jan-01.
- union {
- FileTimeT as_file_time;
- uint64_t as_integer; // 100-nanos since 1601-Jan-01
- } caster;
- caster.as_file_time = ft;
-
- uint64_t sec = caster.as_integer / 10000000UL;
- uint32_t sub_sec = (caster.as_integer % 10000000UL) // 100-nanoseconds since the last second
+
+ // 100-nanos since 1601-Jan-01
+ uint64_t ft_as_integer = (static_cast< uint64_t >(ft.dwHighDateTime) << 32) | static_cast< uint64_t >(ft.dwLowDateTime);
+ uint64_t sec = ft_as_integer / 10000000UL;
+ uint32_t sub_sec = static_cast< uint32_t >(ft_as_integer % 10000000UL) // 100-nanoseconds since the last second
#if !defined(BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG)
- / 10; // microseconds since the last second
+ / 10U; // microseconds since the last second
#else
- * 100; // nanoseconds since the last second
+ * 100U; // nanoseconds since the last second
#endif
// split sec into usable chunks: days, hours, minutes, & seconds
const uint32_t sec_per_day = 86400; // seconds per day
uint32_t days = static_cast< uint32_t >(sec / sec_per_day);
uint32_t tmp = static_cast< uint32_t >(sec % sec_per_day);
--- boost\date_time\microsec_time_clock.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\date_time\microsec_time_clock.hpp 2017-08-28 19:15:39.000000000 -0700
@@ -17,13 +17,15 @@
#include <boost/cstdint.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/date_time/compiler_config.hpp>
#include <boost/date_time/c_time.hpp>
#include <boost/date_time/time_clock.hpp>
-#include <boost/date_time/filetime_functions.hpp>
+#if defined(BOOST_HAS_FTIME)
+#include <boost/detail/winapi/time.hpp>
+#endif
#ifdef BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK
namespace boost {
namespace date_time {
@@ -82,16 +84,25 @@
#ifdef BOOST_HAS_GETTIMEOFDAY
timeval tv;
gettimeofday(&tv, 0); //gettimeofday does not support TZ adjust on Linux.
std::time_t t = tv.tv_sec;
boost::uint32_t sub_sec = tv.tv_usec;
#elif defined(BOOST_HAS_FTIME)
- winapi::file_time ft;
- winapi::get_system_time_as_file_time(ft);
- uint64_t micros = winapi::file_time_to_microseconds(ft); // it will not wrap, since ft is the current time
- // and cannot be before 1970-Jan-01
+ boost::detail::winapi::FILETIME_ ft;
+ boost::detail::winapi::GetSystemTimeAsFileTime(&ft);
+#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205))
+ // Some runtime library implementations expect local times as the norm for ctime functions.
+ {
+ boost::detail::winapi::FILETIME_ local_ft;
+ boost::detail::winapi::FileTimeToLocalFileTime(&ft, &local_ft);
+ ft = local_ft;
+ }
+#endif
+
+ boost::uint64_t micros = file_time_to_microseconds(ft); // it will not wrap, since ft is the current time
+ // and cannot be before 1970-Jan-01
std::time_t t = static_cast<std::time_t>(micros / 1000000UL); // seconds since epoch
// microseconds -- static casts suppress warnings
boost::uint32_t sub_sec = static_cast<boost::uint32_t>(micros % 1000000UL);
#else
#error Internal Boost.DateTime error: BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK is defined, however neither gettimeofday nor FILETIME support is detected.
#endif
@@ -112,16 +123,36 @@
static_cast< typename time_duration_type::min_type >(curr_ptr->tm_min),
static_cast< typename time_duration_type::sec_type >(curr_ptr->tm_sec),
sub_sec * adjust);
return time_type(d,td);
}
+
+#if defined(BOOST_HAS_FTIME)
+ /*!
+ * The function converts file_time into number of microseconds elapsed since 1970-Jan-01
+ *
+ * \note Only dates after 1970-Jan-01 are supported. Dates before will be wrapped.
+ */
+ static boost::uint64_t file_time_to_microseconds(boost::detail::winapi::FILETIME_ const& ft)
+ {
+ // shift is difference between 1970-Jan-01 & 1601-Jan-01
+ // in 100-nanosecond units
+ const boost::uint64_t shift = 116444736000000000ULL; // (27111902 << 32) + 3577643008
+
+ // 100-nanos since 1601-Jan-01
+ boost::uint64_t ft_as_integer = (static_cast< boost::uint64_t >(ft.dwHighDateTime) << 32) | static_cast< boost::uint64_t >(ft.dwLowDateTime);
+
+ ft_as_integer -= shift; // filetime is now 100-nanos since 1970-Jan-01
+ return (ft_as_integer / 10U); // truncate to microseconds
+ }
+#endif
};
} } //namespace date_time
#endif //BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK
#endif
--- boost\detail\winapi\basic_types.hpp 2017-08-19 09:49:50.000000000 -0700
+++ boost\detail\winapi\basic_types.hpp 2017-08-28 21:02:22.000000000 -0700
@@ -64,17 +64,13 @@
struct _SECURITY_ATTRIBUTES;
BOOST_DETAIL_WINAPI_DECLARE_HANDLE(HINSTANCE);
typedef HINSTANCE HMODULE;
}
#endif
-#if defined(__GNUC__)
-#define BOOST_DETAIL_WINAPI_MAY_ALIAS __attribute__ ((__may_alias__))
-#else
-#define BOOST_DETAIL_WINAPI_MAY_ALIAS
-#endif
+#define BOOST_DETAIL_WINAPI_MAY_ALIAS BOOST_MAY_ALIAS
// MinGW64 gcc 4.8.2 fails to compile function declarations with boost::detail::winapi::VOID_ arguments even though
// the typedef expands to void. In Windows SDK, VOID is a macro which unfolds to void. We use our own macro in such cases.
#define BOOST_DETAIL_WINAPI_VOID void
namespace boost {
--- boost\detail\bitmask.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\detail\bitmask.hpp 2017-08-28 20:31:37.000000000 -0700
@@ -3,45 +3,56 @@
// Copyright Beman Dawes 2006
// Distributed under the Boost Software License, Version 1.0
// http://www.boost.org/LICENSE_1_0.txt
// Usage: enum foo { a=1, b=2, c=4 };
-// BOOST_BITMASK( foo );
+// BOOST_BITMASK( foo )
//
// void f( foo arg );
// ...
// f( a | c );
+//
+// See [bitmask.types] in the C++ standard for the formal specification
#ifndef BOOST_BITMASK_HPP
#define BOOST_BITMASK_HPP
+#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#define BOOST_BITMASK(Bitmask) \
\
- inline Bitmask operator| (Bitmask x , Bitmask y ) \
+ inline BOOST_CONSTEXPR Bitmask operator| (Bitmask x , Bitmask y ) \
{ return static_cast<Bitmask>( static_cast<boost::int_least32_t>(x) \
| static_cast<boost::int_least32_t>(y)); } \
\
- inline Bitmask operator& (Bitmask x , Bitmask y ) \
+ inline BOOST_CONSTEXPR Bitmask operator& (Bitmask x , Bitmask y ) \
{ return static_cast<Bitmask>( static_cast<boost::int_least32_t>(x) \
& static_cast<boost::int_least32_t>(y)); } \
\
- inline Bitmask operator^ (Bitmask x , Bitmask y ) \
+ inline BOOST_CONSTEXPR Bitmask operator^ (Bitmask x , Bitmask y ) \
{ return static_cast<Bitmask>( static_cast<boost::int_least32_t>(x) \
^ static_cast<boost::int_least32_t>(y)); } \
\
- inline Bitmask operator~ (Bitmask x ) \
+ inline BOOST_CONSTEXPR Bitmask operator~ (Bitmask x ) \
{ return static_cast<Bitmask>(~static_cast<boost::int_least32_t>(x)); } \
\
- inline Bitmask & operator&=(Bitmask & x , Bitmask y) \
+ inline Bitmask & operator&=(Bitmask& x , Bitmask y) \
{ x = x & y ; return x ; } \
\
- inline Bitmask & operator|=(Bitmask & x , Bitmask y) \
+ inline Bitmask & operator|=(Bitmask& x , Bitmask y) \
{ x = x | y ; return x ; } \
\
- inline Bitmask & operator^=(Bitmask & x , Bitmask y) \
- { x = x ^ y ; return x ; }
+ inline Bitmask & operator^=(Bitmask& x , Bitmask y) \
+ { x = x ^ y ; return x ; } \
+ \
+ /* Boost extensions to [bitmask.types] */ \
+ \
+ inline BOOST_CONSTEXPR bool operator!(Bitmask x) \
+ { return !static_cast<int>(x); } \
+ \
+ inline BOOST_CONSTEXPR bool bitmask_set(Bitmask x) \
+ { return !!x; }
#endif // BOOST_BITMASK_HPP
--- boost\detail\compressed_pair.hpp 2017-08-19 09:49:50.000000000 -0700
+++ boost\detail\compressed_pair.hpp 2017-08-21 15:39:43.000000000 -0700
@@ -32,13 +32,13 @@
# pragma warning(disable:4512)
#endif
namespace boost
{
template <class T1, class T2>
-class compressed_pair;
+class BOOST_EMPTYBASES compressed_pair;
// compressed_pair
namespace details
{
@@ -67,13 +67,13 @@
{static const int value = 4;};
template <class T1, class T2>
struct compressed_pair_switch<T1, T2, true, false, false>
{static const int value = 5;};
- template <class T1, class T2, int Version> class compressed_pair_imp;
+ template <class T1, class T2, int Version> class BOOST_EMPTYBASES compressed_pair_imp;
#ifdef __GNUC__
// workaround for GCC (JM):
using std::swap;
#endif
//
@@ -90,13 +90,13 @@
swap(t1, t2);
}
// 0 derive from neither
template <class T1, class T2>
- class compressed_pair_imp<T1, T2, 0>
+ class BOOST_EMPTYBASES compressed_pair_imp<T1, T2, 0>
{
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
@@ -132,13 +132,13 @@
second_type second_;
};
// 1 derive from T1
template <class T1, class T2>
- class compressed_pair_imp<T1, T2, 1>
+ class BOOST_EMPTYBASES compressed_pair_imp<T1, T2, 1>
: protected ::boost::remove_cv<T1>::type
{
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
@@ -174,13 +174,13 @@
second_type second_;
};
// 2 derive from T2
template <class T1, class T2>
- class compressed_pair_imp<T1, T2, 2>
+ class BOOST_EMPTYBASES compressed_pair_imp<T1, T2, 2>
: protected ::boost::remove_cv<T2>::type
{
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
@@ -217,13 +217,13 @@
first_type first_;
};
// 3 derive from T1 and T2
template <class T1, class T2>
- class compressed_pair_imp<T1, T2, 3>
+ class BOOST_EMPTYBASES compressed_pair_imp<T1, T2, 3>
: protected ::boost::remove_cv<T1>::type,
protected ::boost::remove_cv<T2>::type
{
public:
typedef T1 first_type;
typedef T2 second_type;
@@ -260,13 +260,13 @@
// Originally this did not store an instance of T2 at all
// but that led to problems beause it meant &x.first() == &x.second()
// which is not true for any other kind of pair, so now we store an instance
// of T2 just in case the user is relying on first() and second() returning
// different objects (albeit both empty).
template <class T1, class T2>
- class compressed_pair_imp<T1, T2, 4>
+ class BOOST_EMPTYBASES compressed_pair_imp<T1, T2, 4>
: protected ::boost::remove_cv<T1>::type
{
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
@@ -295,13 +295,13 @@
T2 m_second;
};
// 5 T1 == T2 and are not empty: //JM
template <class T1, class T2>
- class compressed_pair_imp<T1, T2, 5>
+ class BOOST_EMPTYBASES compressed_pair_imp<T1, T2, 5>
{
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
@@ -334,13 +334,13 @@
second_type second_;
};
} // details
template <class T1, class T2>
-class compressed_pair
+class BOOST_EMPTYBASES compressed_pair
: private ::boost::details::compressed_pair_imp<T1, T2,
::boost::details::compressed_pair_switch<
T1,
T2,
::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
::boost::is_empty<T1>::value,
@@ -379,13 +379,13 @@
};
// JM
// Partial specialisation for case where T1 == T2:
//
template <class T>
-class compressed_pair<T, T>
+class BOOST_EMPTYBASES compressed_pair<T, T>
: private details::compressed_pair_imp<T, T,
::boost::details::compressed_pair_switch<
T,
T,
::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
::boost::is_empty<T>::value,
--- boost\detail\ob_compressed_pair.hpp 2017-08-19 09:49:50.000000000 -0700
+++ boost\detail\ob_compressed_pair.hpp 2017-08-21 15:40:07.000000000 -0700
@@ -45,13 +45,13 @@
// each of the compressed_pair versions that follow
// have one template single-argument constructor
// in place of two specific constructors:
//
template <class T1, class T2>
-class compressed_pair;
+class BOOST_EMPTYBASES compressed_pair;
namespace detail{
template <class A, class T1, class T2>
struct best_conversion_traits
{
@@ -138,13 +138,13 @@
swap(_second, y._second);
}
};
// T1 != T2, T2 empty
template <class T1, class T2>
-class compressed_pair_1 : T2
+class BOOST_EMPTYBASES compressed_pair_1 : T2
{
private:
T1 _first;
public:
typedef T1 first_type;
typedef T2 second_type;
@@ -180,13 +180,13 @@
swap(_first, y._first);
}
};
// T1 != T2, T1 empty
template <class T1, class T2>
-class compressed_pair_2 : T1
+class BOOST_EMPTYBASES compressed_pair_2 : T1
{
private:
T2 _second;
public:
typedef T1 first_type;
typedef T2 second_type;
@@ -229,13 +229,13 @@
swap(_second, y._second);
}
};
// T1 != T2, both empty
template <class T1, class T2>
-class compressed_pair_3 : T1, T2
+class BOOST_EMPTYBASES compressed_pair_3 : T1, T2
{
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
@@ -265,13 +265,13 @@
// no need to swap empty base classes:
}
};
// T1 == T2, and empty
template <class T1, class T2>
-class compressed_pair_4 : T1
+class BOOST_EMPTYBASES compressed_pair_4 : T1
{
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
@@ -409,13 +409,13 @@
typedef typename bound_type::type type;
};
} // namespace detail
template <class T1, class T2>
-class compressed_pair : public detail::compressed_pair_traits<T1, T2>::type
+class BOOST_EMPTYBASES compressed_pair : public detail::compressed_pair_traits<T1, T2>::type
{
private:
typedef typename detail::compressed_pair_traits<T1, T2>::type base_type;
public:
typedef T1 first_type;
typedef T2 second_type;
--- boost\fiber\context.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\fiber\context.hpp 2017-08-27 02:44:29.000000000 -0700
@@ -420,15 +420,15 @@
{
// fn and tpl must be destroyed before calling terminate()
auto fn = std::move( fn_);
auto arg = std::move( arg_);
c.resume();
#if defined(BOOST_NO_CXX17_STD_APPLY)
- boost::context::detail::apply( std::move( fn_), std::move( arg_) );
+ boost::context::detail::apply( std::move( fn), std::move( arg) );
#else
- std::apply( std::move( fn_), std::move( arg_) );
+ std::apply( std::move( fn), std::move( arg) );
#endif
}
// terminate context
return terminate();
}
--- boost\filesystem\operations.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\filesystem\operations.hpp 2017-08-21 15:40:51.000000000 -0700
@@ -886,13 +886,13 @@
// directory_iterator //
// //
//--------------------------------------------------------------------------------------//
class directory_iterator
: public boost::iterator_facade< directory_iterator,
- directory_entry,
+ const directory_entry,
boost::single_pass_traversal_tag >
{
public:
directory_iterator() BOOST_NOEXCEPT {} // creates the "end" iterator
@@ -926,13 +926,13 @@
boost::shared_ptr< detail::dir_itr_imp > m_imp;
friend class boost::iterator_core_access;
boost::iterator_facade<
directory_iterator,
- directory_entry,
+ const directory_entry,
boost::single_pass_traversal_tag >::reference dereference() const
{
BOOST_ASSERT_MSG(m_imp.get(), "attempt to dereference end iterator");
return m_imp->dir_entry;
}
@@ -1141,13 +1141,13 @@
// //
//--------------------------------------------------------------------------------------//
class recursive_directory_iterator
: public boost::iterator_facade<
recursive_directory_iterator,
- directory_entry,
+ const directory_entry,
boost::single_pass_traversal_tag >
{
public:
recursive_directory_iterator() BOOST_NOEXCEPT {} // creates the "end" iterator
@@ -1266,13 +1266,13 @@
boost::shared_ptr< detail::recur_dir_itr_imp > m_imp;
friend class boost::iterator_core_access;
boost::iterator_facade<
recursive_directory_iterator,
- directory_entry,
+ const directory_entry,
boost::single_pass_traversal_tag >::reference
dereference() const
{
BOOST_ASSERT_MSG(m_imp.get(),
"dereference of end recursive_directory_iterator");
return *m_imp->m_stack.top();
--- boost\format\detail\config_macros.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\format\detail\config_macros.hpp 2017-08-21 15:41:24.000000000 -0700
@@ -42,13 +42,13 @@
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT( 0x570 ) ) )
// some future __BORLANDC__ >0x564 versions might not need this
// 0x570 is Borland's kylix branch
#define BOOST_NO_LOCALE_ISDIGIT
#endif
-#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570) ) || BOOST_WORKAROUND( BOOST_MSVC, BOOST_TESTED_AT(1300))
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570) ) || BOOST_WORKAROUND( BOOST_MSVC, < 1900 )
#define BOOST_NO_OVERLOAD_FOR_NON_CONST
#endif
// **** Workaround for io streams, stlport and msvc.
#ifdef BOOST_IO_NEEDS_USING_DECLARATION
namespace boost {
--- boost\functional\hash\hash.hpp 2017-08-19 09:49:41.000000000 -0700
+++ boost\functional\hash\hash.hpp 2017-08-21 15:41:47.000000000 -0700
@@ -14,13 +14,12 @@
// domain. The author hereby disclaims copyright to this source code.
#if !defined(BOOST_FUNCTIONAL_HASH_HASH_HPP)
#define BOOST_FUNCTIONAL_HASH_HASH_HPP
#include <boost/functional/hash/hash_fwd.hpp>
-#include <functional>
#include <boost/functional/hash/detail/hash_float.hpp>
#include <string>
#include <boost/limits.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/utility/enable_if.hpp>
@@ -59,23 +58,18 @@
#endif
namespace boost
{
namespace hash_detail
{
-#if defined(_HAS_AUTO_PTR_ETC) && !_HAS_AUTO_PTR_ETC
template <typename T>
struct hash_base
{
typedef T argument_type;
typedef std::size_t result_type;
};
-#else
- template <typename T>
- struct hash_base : std::unary_function<T, std::size_t> {};
-#endif
struct enable_hash_value { typedef std::size_t type; };
template <typename T> struct basic_numbers {};
template <typename T> struct long_numbers;
template <typename T> struct ulong_numbers;
@@ -437,23 +431,23 @@
// BOOST_HASH_SPECIALIZE_REF - define a specialization for a type which is
// passed by const reference.
//
// These are undefined later.
#define BOOST_HASH_SPECIALIZE(type) \
- template <> struct hash<type> \
+ template <> struct BOOST_EMPTYBASES hash<type> \
: public boost::hash_detail::hash_base<type> \
{ \
std::size_t operator()(type v) const \
{ \
return boost::hash_value(v); \
} \
};
#define BOOST_HASH_SPECIALIZE_REF(type) \
- template <> struct hash<type> \
+ template <> struct BOOST_EMPTYBASES hash<type> \
: public boost::hash_detail::hash_base<type> \
{ \
std::size_t operator()(type const& v) const \
{ \
return boost::hash_value(v); \
} \
@@ -513,13 +507,13 @@
// Specializing boost::hash for pointers.
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template <class T>
- struct hash<T*>
+ struct BOOST_EMPTYBASES hash<T*>
: public boost::hash_detail::hash_base<T*>
{
std::size_t operator()(T* v) const
{
#if !BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590)
return boost::hash_value(v);
@@ -546,13 +540,13 @@
struct hash_impl;
template <>
struct hash_impl<true>
{
template <class T>
- struct inner
+ struct BOOST_EMPTYBASES inner
: public boost::hash_detail::hash_base<T>
{
std::size_t operator()(T val) const
{
#if !BOOST_WORKAROUND(__SUNPRO_CC, <= 590)
return boost::hash_value(val);
@@ -564,13 +558,13 @@
#endif
}
};
};
}
- template <class T> struct hash
+ template <class T> struct BOOST_EMPTYBASES hash
: public boost::hash_detail::hash_impl<boost::is_pointer<T>::value>
::BOOST_NESTED_TEMPLATE inner<T>
{
};
#endif
--- boost\hana\config.hpp 2017-08-19 09:49:42.000000000 -0700
+++ boost\hana\config.hpp 2017-08-22 19:22:39.000000000 -0700
@@ -127,13 +127,15 @@
// 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
+#if (defined(__cpp_constexpr) && (__cpp_constexpr >= 201603)) || \
+ (defined(_MSC_VER) && (_MSC_VER >= 1911) && \
+ defined(_MSVC_LANG) && (_MSVC_LANG > 201402))
# define BOOST_HANA_CONFIG_HAS_CONSTEXPR_LAMBDA
# define BOOST_HANA_CONSTEXPR_LAMBDA constexpr
#else
# define BOOST_HANA_CONSTEXPR_LAMBDA /* nothing */
#endif
---
+++ boost\mp11\detail\config.hpp 2017-08-28 02:56:56.000000000 -0700
@@ -0,0 +1,44 @@
+#ifndef BOOST_MP11_DETAIL_CONFIG_HPP_INCLUDED
+#define BOOST_MP11_DETAIL_CONFIG_HPP_INCLUDED
+
+// Copyright 2016 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+
+#if defined( BOOST_NO_CXX11_CONSTEXPR )
+
+# define BOOST_MP11_NO_CONSTEXPR
+
+#elif defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
+
+# define BOOST_MP11_NO_CONSTEXPR
+
+#endif
+
+#if defined(__cpp_fold_expressions) && __cpp_fold_expressions >= 201603
+
+# define BOOST_MP11_HAS_FOLD_EXPRESSIONS
+
+#elif defined(BOOST_CLANG) && defined(__has_cpp_attribute)
+# if __has_cpp_attribute(fallthrough) && __cplusplus >= 201406L // Clang 3.9+ in c++1z mode
+
+# define BOOST_MP11_HAS_FOLD_EXPRESSIONS
+
+# endif
+#endif
+
+#if defined(__has_builtin)
+# if __has_builtin(__type_pack_element)
+
+# define BOOST_MP11_HAS_TYPE_PACK_ELEMENT
+
+# endif
+#endif
+
+#endif // #ifndef BOOST_MP11_DETAIL_CONFIG_HPP_INCLUDED
---
+++ boost\mp11\detail\mp_append.hpp 2017-08-28 02:56:56.000000000 -0700
@@ -0,0 +1,149 @@
+#ifndef BOOST_MP11_DETAIL_MP_APPEND_HPP_INCLUDED
+#define BOOST_MP11_DETAIL_MP_APPEND_HPP_INCLUDED
+
+// Copyright 2015-2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/mp11/detail/mp_list.hpp>
+#include <boost/mp11/utility.hpp>
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+
+namespace boost
+{
+namespace mp11
+{
+
+// mp_append<L...>
+
+namespace detail
+{
+
+template<class... L> struct mp_append_impl;
+
+#if BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
+
+template<> struct mp_append_impl<>
+{
+ using type = mp_list<>;
+};
+
+template<template<class...> class L, class... T> struct mp_append_impl<L<T...>>
+{
+ using type = L<T...>;
+};
+
+template<template<class...> class L1, class... T1, template<class...> class L2, class... T2, class... Lr> struct mp_append_impl<L1<T1...>, L2<T2...>, Lr...>
+{
+ using type = typename mp_append_impl<L1<T1..., T2...>, Lr...>::type;
+};
+
+#else
+
+template<class L1 = mp_list<>, class L2 = mp_list<>, class L3 = mp_list<>, class L4 = mp_list<>, class L5 = mp_list<>, class L6 = mp_list<>, class L7 = mp_list<>, class L8 = mp_list<>, class L9 = mp_list<>, class L10 = mp_list<>, class L11 = mp_list<>> struct append_11_impl;
+
+template<
+ template<class...> class L1, class... T1,
+ template<class...> class L2, class... T2,
+ template<class...> class L3, class... T3,
+ template<class...> class L4, class... T4,
+ template<class...> class L5, class... T5,
+ template<class...> class L6, class... T6,
+ template<class...> class L7, class... T7,
+ template<class...> class L8, class... T8,
+ template<class...> class L9, class... T9,
+ template<class...> class L10, class... T10,
+ template<class...> class L11, class... T11>
+
+struct append_11_impl<L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>, L5<T5...>, L6<T6...>, L7<T7...>, L8<T8...>, L9<T9...>, L10<T10...>, L11<T11...>>
+{
+ using type = L1<T1..., T2..., T3..., T4..., T5..., T6..., T7..., T8..., T9..., T10..., T11...>;
+};
+
+template<
+
+ class L00 = mp_list<>, class L01 = mp_list<>, class L02 = mp_list<>, class L03 = mp_list<>, class L04 = mp_list<>, class L05 = mp_list<>, class L06 = mp_list<>, class L07 = mp_list<>, class L08 = mp_list<>, class L09 = mp_list<>, class L0A = mp_list<>,
+ class L10 = mp_list<>, class L11 = mp_list<>, class L12 = mp_list<>, class L13 = mp_list<>, class L14 = mp_list<>, class L15 = mp_list<>, class L16 = mp_list<>, class L17 = mp_list<>, class L18 = mp_list<>, class L19 = mp_list<>,
+ class L20 = mp_list<>, class L21 = mp_list<>, class L22 = mp_list<>, class L23 = mp_list<>, class L24 = mp_list<>, class L25 = mp_list<>, class L26 = mp_list<>, class L27 = mp_list<>, class L28 = mp_list<>, class L29 = mp_list<>,
+ class L30 = mp_list<>, class L31 = mp_list<>, class L32 = mp_list<>, class L33 = mp_list<>, class L34 = mp_list<>, class L35 = mp_list<>, class L36 = mp_list<>, class L37 = mp_list<>, class L38 = mp_list<>, class L39 = mp_list<>,
+ class L40 = mp_list<>, class L41 = mp_list<>, class L42 = mp_list<>, class L43 = mp_list<>, class L44 = mp_list<>, class L45 = mp_list<>, class L46 = mp_list<>, class L47 = mp_list<>, class L48 = mp_list<>, class L49 = mp_list<>,
+ class L50 = mp_list<>, class L51 = mp_list<>, class L52 = mp_list<>, class L53 = mp_list<>, class L54 = mp_list<>, class L55 = mp_list<>, class L56 = mp_list<>, class L57 = mp_list<>, class L58 = mp_list<>, class L59 = mp_list<>,
+ class L60 = mp_list<>, class L61 = mp_list<>, class L62 = mp_list<>, class L63 = mp_list<>, class L64 = mp_list<>, class L65 = mp_list<>, class L66 = mp_list<>, class L67 = mp_list<>, class L68 = mp_list<>, class L69 = mp_list<>,
+ class L70 = mp_list<>, class L71 = mp_list<>, class L72 = mp_list<>, class L73 = mp_list<>, class L74 = mp_list<>, class L75 = mp_list<>, class L76 = mp_list<>, class L77 = mp_list<>, class L78 = mp_list<>, class L79 = mp_list<>,
+ class L80 = mp_list<>, class L81 = mp_list<>, class L82 = mp_list<>, class L83 = mp_list<>, class L84 = mp_list<>, class L85 = mp_list<>, class L86 = mp_list<>, class L87 = mp_list<>, class L88 = mp_list<>, class L89 = mp_list<>,
+ class L90 = mp_list<>, class L91 = mp_list<>, class L92 = mp_list<>, class L93 = mp_list<>, class L94 = mp_list<>, class L95 = mp_list<>, class L96 = mp_list<>, class L97 = mp_list<>, class L98 = mp_list<>, class L99 = mp_list<>,
+ class LA0 = mp_list<>, class LA1 = mp_list<>, class LA2 = mp_list<>, class LA3 = mp_list<>, class LA4 = mp_list<>, class LA5 = mp_list<>, class LA6 = mp_list<>, class LA7 = mp_list<>, class LA8 = mp_list<>, class LA9 = mp_list<>
+
+> struct append_111_impl
+{
+ using type = typename append_11_impl<
+
+ typename append_11_impl<L00, L01, L02, L03, L04, L05, L06, L07, L08, L09, L0A>::type,
+ typename append_11_impl<mp_list<>, L10, L11, L12, L13, L14, L15, L16, L17, L18, L19>::type,
+ typename append_11_impl<mp_list<>, L20, L21, L22, L23, L24, L25, L26, L27, L28, L29>::type,
+ typename append_11_impl<mp_list<>, L30, L31, L32, L33, L34, L35, L36, L37, L38, L39>::type,
+ typename append_11_impl<mp_list<>, L40, L41, L42, L43, L44, L45, L46, L47, L48, L49>::type,
+ typename append_11_impl<mp_list<>, L50, L51, L52, L53, L54, L55, L56, L57, L58, L59>::type,
+ typename append_11_impl<mp_list<>, L60, L61, L62, L63, L64, L65, L66, L67, L68, L69>::type,
+ typename append_11_impl<mp_list<>, L70, L71, L72, L73, L74, L75, L76, L77, L78, L79>::type,
+ typename append_11_impl<mp_list<>, L80, L81, L82, L83, L84, L85, L86, L87, L88, L89>::type,
+ typename append_11_impl<mp_list<>, L90, L91, L92, L93, L94, L95, L96, L97, L98, L99>::type,
+ typename append_11_impl<mp_list<>, LA0, LA1, LA2, LA3, LA4, LA5, LA6, LA7, LA8, LA9>::type
+
+ >::type;
+};
+
+template<
+
+ class L00, class L01, class L02, class L03, class L04, class L05, class L06, class L07, class L08, class L09, class L0A,
+ class L10, class L11, class L12, class L13, class L14, class L15, class L16, class L17, class L18, class L19,
+ class L20, class L21, class L22, class L23, class L24, class L25, class L26, class L27, class L28, class L29,
+ class L30, class L31, class L32, class L33, class L34, class L35, class L36, class L37, class L38, class L39,
+ class L40, class L41, class L42, class L43, class L44, class L45, class L46, class L47, class L48, class L49,
+ class L50, class L51, class L52, class L53, class L54, class L55, class L56, class L57, class L58, class L59,
+ class L60, class L61, class L62, class L63, class L64, class L65, class L66, class L67, class L68, class L69,
+ class L70, class L71, class L72, class L73, class L74, class L75, class L76, class L77, class L78, class L79,
+ class L80, class L81, class L82, class L83, class L84, class L85, class L86, class L87, class L88, class L89,
+ class L90, class L91, class L92, class L93, class L94, class L95, class L96, class L97, class L98, class L99,
+ class LA0, class LA1, class LA2, class LA3, class LA4, class LA5, class LA6, class LA7, class LA8, class LA9,
+ class... Lr
+
+> struct append_inf_impl
+{
+ using prefix = typename append_111_impl<
+
+ L00, L01, L02, L03, L04, L05, L06, L07, L08, L09, L0A,
+ L10, L11, L12, L13, L14, L15, L16, L17, L18, L19,
+ L20, L21, L22, L23, L24, L25, L26, L27, L28, L29,
+ L30, L31, L32, L33, L34, L35, L36, L37, L38, L39,
+ L40, L41, L42, L43, L44, L45, L46, L47, L48, L49,
+ L50, L51, L52, L53, L54, L55, L56, L57, L58, L59,
+ L60, L61, L62, L63, L64, L65, L66, L67, L68, L69,
+ L70, L71, L72, L73, L74, L75, L76, L77, L78, L79,
+ L80, L81, L82, L83, L84, L85, L86, L87, L88, L89,
+ L90, L91, L92, L93, L94, L95, L96, L97, L98, L99,
+ LA0, LA1, LA2, LA3, LA4, LA5, LA6, LA7, LA8, LA9
+
+ >::type;
+
+ using type = typename mp_append_impl<prefix, Lr...>::type;
+};
+
+template<class... L> struct mp_append_impl: mp_if_c<(sizeof...(L) > 111), mp_quote<append_inf_impl>, mp_if_c<(sizeof...(L) > 11), mp_quote<append_111_impl>, mp_quote<append_11_impl>>>::template fn<L...>
+{
+};
+
+#endif
+
+} // namespace detail
+
+template<class... L> using mp_append = typename detail::mp_append_impl<L...>::type;
+
+} // namespace mp11
+} // namespace boost
+
+#endif // #ifndef BOOST_MP11_DETAIL_MP_APPEND_HPP_INCLUDED
---
+++ boost\mp11\detail\mp_count.hpp 2017-08-24 15:13:49.000000000 -0700
@@ -0,0 +1,115 @@
+#ifndef BOOST_MP11_DETAIL_MP_COUNT_HPP_INCLUDED
+#define BOOST_MP11_DETAIL_MP_COUNT_HPP_INCLUDED
+
+// Copyright 2015, 2016 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/detail/mp_plus.hpp>
+#include <boost/mp11/detail/config.hpp>
+#include <boost/config.hpp>
+
+namespace boost
+{
+namespace mp11
+{
+
+// mp_count<L, V>
+namespace detail
+{
+
+template<class L, class V> struct mp_count_impl;
+
+#if defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS )
+
+template<template<class...> class L, class... T, class V> struct mp_count_impl<L<T...>, V>
+{
+ using type = mp_size_t<(std::is_same<T, V>::value + ... + 0)>;
+};
+
+#elif !defined( BOOST_MP11_NO_CONSTEXPR )
+
+constexpr std::size_t cx_plus()
+{
+ return 0;
+}
+
+template<class T1, class... T> constexpr std::size_t cx_plus(T1 t1, T... t)
+{
+ return t1 + cx_plus(t...);
+}
+
+template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T>
+constexpr std::size_t cx_plus(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T... t)
+{
+ return t1 + t2 + t3 + t4 + t5 + t6 + t7 + t8 + t9 + t10 + cx_plus(t...);
+}
+
+template<template<class...> class L, class... T, class V> struct mp_count_impl<L<T...>, V>
+{
+ using type = mp_size_t<cx_plus(std::is_same<T, V>::value...)>;
+};
+
+#else
+
+template<template<class...> class L, class... T, class V> struct mp_count_impl<L<T...>, V>
+{
+ using type = mp_size_t<mp_plus<std::is_same<T, V>...>::value>;
+};
+
+#endif
+
+} // namespace detail
+
+template<class L, class V> using mp_count = typename detail::mp_count_impl<L, V>::type;
+
+// mp_count_if<L, P>
+namespace detail
+{
+
+template<class L, template<class...> class P> struct mp_count_if_impl;
+
+#if defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS )
+
+template<template<class...> class L, class... T, template<class...> class P> struct mp_count_if_impl<L<T...>, P>
+{
+ using type = mp_size_t<(mp_to_bool<P<T>>::value + ... + 0)>;
+};
+
+#elif !defined( BOOST_MP11_NO_CONSTEXPR )
+
+template<template<class...> class L, class... T, template<class...> class P> struct mp_count_if_impl<L<T...>, P>
+{
+ using type = mp_size_t<cx_plus(mp_to_bool<P<T>>::value...)>;
+};
+
+#else
+
+template<template<class...> class L, class... T, template<class...> class P> struct mp_count_if_impl<L<T...>, P>
+{
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
+
+ template<class T> struct _f { using type = mp_to_bool<P<T>>; };
+ using type = mp_size_t<mp_plus<typename _f<T>::type...>::value>;
+
+#else
+
+ using type = mp_size_t<mp_plus<mp_to_bool<P<T>>...>::value>;
+
+#endif
+};
+
+#endif
+
+} // namespace detail
+
+template<class L, template<class...> class P> using mp_count_if = typename detail::mp_count_if_impl<L, P>::type;
+
+} // namespace mp11
+} // namespace boost
+
+#endif // #ifndef BOOST_MP11_DETAIL_MP_COUNT_HPP_INCLUDED
---
+++ boost\mp11\detail\mp_list.hpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,24 @@
+#ifndef BOOST_MP11_DETAIL_MP_LIST_HPP_INCLUDED
+#define BOOST_MP11_DETAIL_MP_LIST_HPP_INCLUDED
+
+// Copyright 2015, 2016 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+namespace boost
+{
+namespace mp11
+{
+
+// mp_list<T...>
+template<class... T> struct mp_list
+{
+};
+
+} // namespace mp11
+} // namespace boost
+
+#endif // #ifndef BOOST_MP11_DETAIL_MP_LIST_HPP_INCLUDED
---
+++ boost\mp11\detail\mp_map_find.hpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,43 @@
+#ifndef BOOST_MP11_DETAIL_MP_MAP_FIND_HPP_INCLUDED
+#define BOOST_MP11_DETAIL_MP_MAP_FIND_HPP_INCLUDED
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/mp11/utility.hpp>
+
+namespace boost
+{
+namespace mp11
+{
+
+// mp_map_find
+namespace detail
+{
+
+template<class M, class K> struct mp_map_find_impl;
+
+template<template<class...> class M, class... T, class K> struct mp_map_find_impl<M<T...>, K>
+{
+ using U = mp_inherit<mp_identity<T>...>;
+
+ template<template<class...> class L, class... U> static mp_identity<L<K, U...>> f( mp_identity<L<K, U...>>* );
+ static mp_identity<void> f( ... );
+
+ using V = decltype( f((U*)0) );
+
+ using type = typename V::type;
+};
+
+} // namespace detail
+
+template<class M, class K> using mp_map_find = typename detail::mp_map_find_impl<M, K>::type;
+
+} // namespace mp11
+} // namespace boost
+
+#endif // #ifndef BOOST_MP11_DETAIL_MP_MAP_FIND_HPP_INCLUDED
---
+++ boost\mp11\detail\mp_plus.hpp 2017-08-28 02:56:56.000000000 -0700
@@ -0,0 +1,82 @@
+#ifndef BOOST_MP11_DETAIL_MP_PLUS_HPP_INCLUDED
+#define BOOST_MP11_DETAIL_MP_PLUS_HPP_INCLUDED
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/mp11/detail/config.hpp>
+#include <boost/config/workaround.hpp>
+#include <type_traits>
+
+namespace boost
+{
+namespace mp11
+{
+
+// mp_plus
+namespace detail
+{
+
+#if defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS )
+
+template<class... T> struct mp_plus_impl
+{
+ static const auto _v = (T::value + ... + 0);
+ using type = std::integral_constant<typename std::remove_const<decltype(_v)>::type, _v>;
+};
+
+#else
+
+template<class... T> struct mp_plus_impl;
+
+template<> struct mp_plus_impl<>
+{
+ using type = std::integral_constant<int, 0>;
+};
+
+#if BOOST_WORKAROUND( BOOST_GCC, < 40800 )
+
+template<class T1, class... T> struct mp_plus_impl<T1, T...>
+{
+ static const decltype(T1::value + mp_plus_impl<T...>::type::value) _v = T1::value + mp_plus_impl<T...>::type::value;
+ using type = std::integral_constant<typename std::remove_const<decltype(_v)>::type, _v>;
+};
+
+template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T> struct mp_plus_impl<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>
+{
+ static const
+ decltype(T1::value + T2::value + T3::value + T4::value + T5::value + T6::value + T7::value + T8::value + T9::value + T10::value + mp_plus_impl<T...>::type::value)
+ _v = T1::value + T2::value + T3::value + T4::value + T5::value + T6::value + T7::value + T8::value + T9::value + T10::value + mp_plus_impl<T...>::type::value;
+ using type = std::integral_constant<typename std::remove_const<decltype(_v)>::type, _v>;
+};
+
+#else
+
+template<class T1, class... T> struct mp_plus_impl<T1, T...>
+{
+ static const auto _v = T1::value + mp_plus_impl<T...>::type::value;
+ using type = std::integral_constant<typename std::remove_const<decltype(_v)>::type, _v>;
+};
+
+template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T> struct mp_plus_impl<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>
+{
+ static const auto _v = T1::value + T2::value + T3::value + T4::value + T5::value + T6::value + T7::value + T8::value + T9::value + T10::value + mp_plus_impl<T...>::type::value;
+ using type = std::integral_constant<typename std::remove_const<decltype(_v)>::type, _v>;
+};
+
+#endif
+
+#endif
+
+} // namespace detail
+
+template<class... T> using mp_plus = typename detail::mp_plus_impl<T...>::type;
+
+} // namespace mp11
+} // namespace boost
+
+#endif // #ifndef BOOST_MP11_DETAIL_MP_PLUS_HPP_INCLUDED
---
+++ boost\mp11\detail\mp_with_index.hpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,374 @@
+#ifndef BOOST_MP11_DETAIL_MP_WITH_INDEX_HPP_INCLUDED
+#define BOOST_MP11_DETAIL_MP_WITH_INDEX_HPP_INCLUDED
+
+// Copyright 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/mp11/integral.hpp>
+#include <boost/config.hpp>
+#include <type_traits>
+#include <utility>
+#include <cassert>
+
+#if !defined( BOOST_NO_CXX14_CONSTEXPR )
+# define BOOST_MP11_CONSTEXPR14 constexpr
+#else
+# define BOOST_MP11_CONSTEXPR14
+#endif
+
+namespace boost
+{
+namespace mp11
+{
+
+namespace detail
+{
+
+template<std::size_t N> struct mp_with_index_impl_
+{
+ template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
+ {
+ switch( i )
+ {
+ case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
+ case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
+ case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
+ case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
+ case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
+ case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
+ case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
+ case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
+ case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
+ case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
+ case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
+ case 11: return std::forward<F>(f)( mp_size_t<K+11>() );
+ case 12: return std::forward<F>(f)( mp_size_t<K+12>() );
+ case 13: return std::forward<F>(f)( mp_size_t<K+13>() );
+ case 14: return std::forward<F>(f)( mp_size_t<K+14>() );
+ case 15: return std::forward<F>(f)( mp_size_t<K+15>() );
+ }
+
+ return mp_with_index_impl_<N-16>::template call<K+16>( i-16, std::forward<F>(f) );
+ }
+};
+
+template<> struct mp_with_index_impl_<0>
+{
+};
+
+template<> struct mp_with_index_impl_<1>
+{
+ template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t /*i*/, F && f )
+ {
+ return std::forward<F>(f)( mp_size_t<K+0>() );
+ }
+};
+
+template<> struct mp_with_index_impl_<2>
+{
+ template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
+ {
+ switch( i )
+ {
+ case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
+ default: return std::forward<F>(f)( mp_size_t<K+1>() );
+ }
+ }
+};
+
+template<> struct mp_with_index_impl_<3>
+{
+ template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
+ {
+ switch( i )
+ {
+ case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
+ case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
+ default: return std::forward<F>(f)( mp_size_t<K+2>() );
+ }
+ }
+};
+
+template<> struct mp_with_index_impl_<4>
+{
+ template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
+ {
+ switch( i )
+ {
+ case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
+ case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
+ case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
+ default: return std::forward<F>(f)( mp_size_t<K+3>() );
+ }
+ }
+};
+
+template<> struct mp_with_index_impl_<5>
+{
+ template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
+ {
+ switch( i )
+ {
+ case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
+ case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
+ case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
+ case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
+ default: return std::forward<F>(f)( mp_size_t<K+4>() );
+ }
+ }
+};
+
+template<> struct mp_with_index_impl_<6>
+{
+ template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
+ {
+ switch( i )
+ {
+ case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
+ case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
+ case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
+ case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
+ case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
+ default: return std::forward<F>(f)( mp_size_t<K+5>() );
+ }
+ }
+};
+
+template<> struct mp_with_index_impl_<7>
+{
+ template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
+ {
+ switch( i )
+ {
+ case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
+ case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
+ case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
+ case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
+ case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
+ case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
+ default: return std::forward<F>(f)( mp_size_t<K+6>() );
+ }
+ }
+};
+
+template<> struct mp_with_index_impl_<8>
+{
+ template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
+ {
+ switch( i )
+ {
+ case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
+ case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
+ case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
+ case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
+ case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
+ case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
+ case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
+ default: return std::forward<F>(f)( mp_size_t<K+7>() );
+ }
+ }
+};
+
+template<> struct mp_with_index_impl_<9>
+{
+ template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
+ {
+ switch( i )
+ {
+ case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
+ case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
+ case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
+ case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
+ case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
+ case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
+ case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
+ case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
+ default: return std::forward<F>(f)( mp_size_t<K+8>() );
+ }
+ }
+};
+
+template<> struct mp_with_index_impl_<10>
+{
+ template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
+ {
+ switch( i )
+ {
+ case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
+ case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
+ case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
+ case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
+ case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
+ case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
+ case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
+ case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
+ case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
+ default: return std::forward<F>(f)( mp_size_t<K+9>() );
+ }
+ }
+};
+
+template<> struct mp_with_index_impl_<11>
+{
+ template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
+ {
+ switch( i )
+ {
+ case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
+ case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
+ case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
+ case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
+ case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
+ case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
+ case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
+ case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
+ case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
+ case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
+ default: return std::forward<F>(f)( mp_size_t<K+10>() );
+ }
+ }
+};
+
+template<> struct mp_with_index_impl_<12>
+{
+ template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
+ {
+ switch( i )
+ {
+ case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
+ case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
+ case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
+ case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
+ case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
+ case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
+ case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
+ case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
+ case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
+ case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
+ case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
+ default: return std::forward<F>(f)( mp_size_t<K+11>() );
+ }
+ }
+};
+
+template<> struct mp_with_index_impl_<13>
+{
+ template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
+ {
+ switch( i )
+ {
+ case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
+ case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
+ case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
+ case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
+ case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
+ case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
+ case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
+ case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
+ case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
+ case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
+ case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
+ case 11: return std::forward<F>(f)( mp_size_t<K+11>() );
+ default: return std::forward<F>(f)( mp_size_t<K+12>() );
+ }
+ }
+};
+
+template<> struct mp_with_index_impl_<14>
+{
+ template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
+ {
+ switch( i )
+ {
+ case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
+ case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
+ case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
+ case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
+ case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
+ case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
+ case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
+ case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
+ case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
+ case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
+ case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
+ case 11: return std::forward<F>(f)( mp_size_t<K+11>() );
+ case 12: return std::forward<F>(f)( mp_size_t<K+12>() );
+ default: return std::forward<F>(f)( mp_size_t<K+13>() );
+ }
+ }
+};
+
+template<> struct mp_with_index_impl_<15>
+{
+ template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
+ {
+ switch( i )
+ {
+ case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
+ case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
+ case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
+ case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
+ case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
+ case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
+ case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
+ case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
+ case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
+ case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
+ case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
+ case 11: return std::forward<F>(f)( mp_size_t<K+11>() );
+ case 12: return std::forward<F>(f)( mp_size_t<K+12>() );
+ case 13: return std::forward<F>(f)( mp_size_t<K+13>() );
+ default: return std::forward<F>(f)( mp_size_t<K+14>() );
+ }
+ }
+};
+
+template<> struct mp_with_index_impl_<16>
+{
+ template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
+ {
+ switch( i )
+ {
+ case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
+ case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
+ case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
+ case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
+ case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
+ case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
+ case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
+ case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
+ case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
+ case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
+ case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
+ case 11: return std::forward<F>(f)( mp_size_t<K+11>() );
+ case 12: return std::forward<F>(f)( mp_size_t<K+12>() );
+ case 13: return std::forward<F>(f)( mp_size_t<K+13>() );
+ case 14: return std::forward<F>(f)( mp_size_t<K+14>() );
+ default: return std::forward<F>(f)( mp_size_t<K+15>() );
+ }
+ }
+};
+
+} // namespace detail
+
+template<std::size_t N, class F> inline BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) mp_with_index( std::size_t i, F && f )
+{
+ assert( i < N );
+ return detail::mp_with_index_impl_<N>::template call<0>( i, std::forward<F>(f) );
+}
+
+template<class N, class F> inline BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) mp_with_index( std::size_t i, F && f )
+{
+ return mp_with_index<std::size_t{N::value}>( i, std::forward<F>(f) );
+}
+
+#undef BOOST_MP11_CONSTEXPR14
+
+} // namespace mp11
+} // namespace boost
+
+#endif // #ifndef BOOST_MP11_DETAIL_MP_WITH_INDEX_HPP_INCLUDED
---
+++ boost\mp11\algorithm.hpp 2017-08-28 02:56:56.000000000 -0700
@@ -0,0 +1,943 @@
+#ifndef BOOST_MP11_ALGORITHM_HPP_INCLUDED
+#define BOOST_MP11_ALGORITHM_HPP_INCLUDED
+
+// Copyright 2015-2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/set.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/utility.hpp>
+#include <boost/mp11/function.hpp>
+#include <boost/mp11/detail/mp_count.hpp>
+#include <boost/mp11/detail/mp_plus.hpp>
+#include <boost/mp11/detail/mp_map_find.hpp>
+#include <boost/mp11/detail/mp_with_index.hpp>
+#include <boost/mp11/detail/config.hpp>
+#include <boost/mp11/integer_sequence.hpp>
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+#include <type_traits>
+#include <utility>
+
+namespace boost
+{
+namespace mp11
+{
+
+// mp_assign<L1, L2>
+namespace detail
+{
+
+template<class L1, class L2> struct mp_assign_impl;
+
+template<template<class...> class L1, class... T, template<class...> class L2, class... U> struct mp_assign_impl<L1<T...>, L2<U...>>
+{
+ using type = L1<U...>;
+};
+
+} // namespace detail
+
+template<class L1, class L2> using mp_assign = typename detail::mp_assign_impl<L1, L2>::type;
+
+// mp_clear<L>
+template<class L> using mp_clear = mp_assign<L, mp_list<>>;
+
+// mp_fold<L, V, F> forward declaration
+namespace detail
+{
+
+template<class L, class V, template<class...> class F> struct mp_fold_impl;
+
+} // namespace detail
+
+template<class L, class V, template<class...> class F> using mp_fold = typename detail::mp_fold_impl<L, V, F>::type;
+
+// mp_transform<F, L...>
+namespace detail
+{
+
+template<template<class...> class F, class... L> struct mp_transform_impl
+{
+};
+
+template<template<class...> class F, template<class...> class L, class... T> struct mp_transform_impl<F, L<T...>>
+{
+#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
+
+ template<class... U> struct f { using type = F<U...>; };
+
+ using type = L<typename f<T>::type...>;
+
+#else
+
+ using type = L<F<T>...>;
+
+#endif
+};
+
+template<template<class...> class F, template<class...> class L1, class... T1, template<class...> class L2, class... T2> struct mp_transform_impl<F, L1<T1...>, L2<T2...>>
+{
+#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
+
+ template<class... U> struct f { using type = F<U...>; };
+
+ using type = L1<typename f<T1, T2>::type...>;
+
+#else
+
+ using type = L1<F<T1,T2>...>;
+
+#endif
+};
+
+template<template<class...> class F, template<class...> class L1, class... T1, template<class...> class L2, class... T2, template<class...> class L3, class... T3> struct mp_transform_impl<F, L1<T1...>, L2<T2...>, L3<T3...>>
+{
+#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
+
+ template<class... U> struct f { using type = F<U...>; };
+
+ using type = L1<typename f<T1, T2, T3>::type...>;
+
+#else
+
+ using type = L1<F<T1,T2,T3>...>;
+
+#endif
+};
+
+#if BOOST_WORKAROUND( BOOST_MSVC, == 1900 ) || BOOST_WORKAROUND( BOOST_GCC, < 40800 )
+
+template<class... L> using mp_same_size_1 = mp_same<mp_size<L>...>;
+template<class... L> struct mp_same_size_2: mp_defer<mp_same_size_1, L...> {};
+
+#endif
+
+struct list_size_mismatch
+{
+};
+
+} // namespace detail
+
+#if BOOST_WORKAROUND( BOOST_MSVC, == 1900 ) || BOOST_WORKAROUND( BOOST_GCC, < 40800 )
+
+template<template<class...> class F, class... L> using mp_transform = typename mp_if<typename detail::mp_same_size_2<L...>::type, detail::mp_transform_impl<F, L...>, detail::list_size_mismatch>::type;
+
+#else
+
+template<template<class...> class F, class... L> using mp_transform = typename mp_if<mp_same<mp_size<L>...>, detail::mp_transform_impl<F, L...>, detail::list_size_mismatch>::type;
+
+#endif
+
+template<class Q, class... L> using mp_transform_q = mp_transform<Q::template fn, L...>;
+
+namespace detail
+{
+
+template<template<class...> class F, template<class...> class L1, class... T1, template<class...> class L2, class... T2, template<class...> class L3, class... T3, template<class...> class L4, class... T4, class... L> struct mp_transform_impl<F, L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>, L...>
+{
+ using A1 = L1<mp_list<T1, T2, T3, T4>...>;
+
+ template<class V, class T> using _f = mp_transform<mp_push_back, V, T>;
+
+ using A2 = mp_fold<mp_list<L...>, A1, _f>;
+
+ template<class T> using _g = mp_apply<F, T>;
+
+ using type = mp_transform<_g, A2>;
+};
+
+} // namespace detail
+
+// mp_transform_if<P, F, L...>
+namespace detail
+{
+
+template<template<class...> class P, template<class...> class F, class... L> struct mp_transform_if_impl
+{
+ // the stupid quote-unquote dance avoids "pack expansion used as argument for non-pack parameter of alias template"
+
+ using Qp = mp_quote<P>;
+ using Qf = mp_quote<F>;
+
+#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
+
+ template<class... U> struct _f_ { using type = mp_eval_if_q<mp_not<mp_invoke<Qp, U...>>, mp_first<mp_list<U...>>, Qf, U...>; };
+ template<class... U> using _f = typename _f_<U...>::type;
+
+#else
+
+ template<class... U> using _f = mp_eval_if_q<mp_not<mp_invoke<Qp, U...>>, mp_first<mp_list<U...>>, Qf, U...>;
+
+#endif
+
+ using type = mp_transform<_f, L...>;
+};
+
+} // namespace detail
+
+template<template<class...> class P, template<class...> class F, class... L> using mp_transform_if = typename detail::mp_transform_if_impl<P, F, L...>::type;
+template<class Qp, class Qf, class... L> using mp_transform_if_q = typename detail::mp_transform_if_impl<Qp::template fn, Qf::template fn, L...>::type;
+
+// mp_fill<L, V>
+namespace detail
+{
+
+template<class L, class V> struct mp_fill_impl;
+
+template<template<class...> class L, class... T, class V> struct mp_fill_impl<L<T...>, V>
+{
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1900 )
+
+ template<class...> struct _f { using type = V; };
+ using type = L<typename _f<T>::type...>;
+
+#else
+
+ template<class...> using _f = V;
+ using type = L<_f<T>...>;
+
+#endif
+};
+
+} // namespace detail
+
+template<class L, class V> using mp_fill = typename detail::mp_fill_impl<L, V>::type;
+
+// mp_contains<L, V>
+template<class L, class V> using mp_contains = mp_to_bool<mp_count<L, V>>;
+
+// mp_repeat(_c)<L, N>
+namespace detail
+{
+
+template<class L, std::size_t N> struct mp_repeat_c_impl
+{
+ using _l1 = typename mp_repeat_c_impl<L, N/2>::type;
+ using _l2 = typename mp_repeat_c_impl<L, N%2>::type;
+
+ using type = mp_append<_l1, _l1, _l2>;
+};
+
+template<class L> struct mp_repeat_c_impl<L, 0>
+{
+ using type = mp_clear<L>;
+};
+
+template<class L> struct mp_repeat_c_impl<L, 1>
+{
+ using type = L;
+};
+
+} // namespace detail
+
+template<class L, std::size_t N> using mp_repeat_c = typename detail::mp_repeat_c_impl<L, N>::type;
+template<class L, class N> using mp_repeat = typename detail::mp_repeat_c_impl<L, std::size_t{ N::value }>::type;
+
+// mp_product<F, L...>
+namespace detail
+{
+
+template<template<class...> class F, class P, class... L> struct mp_product_impl_2;
+
+template<template<class...> class F, class P> struct mp_product_impl_2<F, P>
+{
+ using type = mp_list<mp_rename<P, F>>;
+};
+
+template<template<class...> class F, class P, template<class...> class L1, class... T1, class... L> struct mp_product_impl_2<F, P, L1<T1...>, L...>
+{
+ using type = mp_append<typename mp_product_impl_2<F, mp_push_back<P, T1>, L...>::type...>;
+};
+
+template<template<class...> class F, class... L> struct mp_product_impl;
+
+template<template<class...> class F, class L1, class... L> struct mp_product_impl<F, L1, L...>
+{
+ using type = mp_assign<L1, typename mp_product_impl_2<F, mp_list<>, L1, L...>::type>;
+};
+
+} // namespace detail
+
+template<template<class...> class F, class... L> using mp_product = typename detail::mp_product_impl<F, L...>::type;
+template<class Q, class... L> using mp_product_q = typename detail::mp_product_impl<Q::template fn, L...>::type;
+
+// mp_drop(_c)<L, N>
+namespace detail
+{
+
+template<class L, class L2> struct mp_drop_impl;
+
+template<template<class...> class L, class... T, template<class...> class L2, class... U> struct mp_drop_impl<L<T...>, L2<U...>>
+{
+ template<class... W> static mp_identity<L<W...>> f( U*..., mp_identity<W>*... );
+
+ using R = decltype( f( (mp_identity<T>*)0 ... ) );
+
+ using type = typename R::type;
+};
+
+} // namespace detail
+
+template<class L, std::size_t N> using mp_drop_c = typename detail::mp_drop_impl<L, mp_repeat_c<mp_list<void>, N>>::type;
+
+template<class L, class N> using mp_drop = typename detail::mp_drop_impl<L, mp_repeat<mp_list<void>, N>>::type;
+
+// mp_iota(_c)<N>
+namespace detail
+{
+
+template<class S> struct mp_from_sequence_impl;
+
+template<template<class T, T... I> class S, class U, U... J> struct mp_from_sequence_impl<S<U, J...>>
+{
+ using type = mp_list<std::integral_constant<U, J>...>;
+};
+
+template<class S> using mp_from_sequence = typename mp_from_sequence_impl<S>::type;
+
+} // namespace detail
+
+template<std::size_t N> using mp_iota_c = detail::mp_from_sequence<make_index_sequence<N>>;
+template<class N> using mp_iota = detail::mp_from_sequence<make_integer_sequence<typename std::remove_const<decltype(N::value)>::type, N::value>>;
+
+// mp_at(_c)<L, I>
+namespace detail
+{
+
+template<class L, std::size_t I> struct mp_at_c_impl;
+
+#if defined(BOOST_MP11_HAS_TYPE_PACK_ELEMENT)
+
+template<template<class...> class L, class... T, std::size_t I> struct mp_at_c_impl<L<T...>, I>
+{
+ using type = __type_pack_element<I, T...>;
+};
+
+#else
+
+template<class L, std::size_t I> struct mp_at_c_impl
+{
+ using _map = mp_transform<mp_list, mp_iota<mp_size<L>>, L>;
+ using type = mp_second<mp_map_find<_map, mp_size_t<I>>>;
+};
+
+#endif
+
+} // namespace detail
+
+template<class L, std::size_t I> using mp_at_c = typename mp_if_c<(I < mp_size<L>::value), detail::mp_at_c_impl<L, I>, void>::type;
+template<class L, class I> using mp_at = mp_at_c<L, std::size_t{ I::value }>;
+
+// mp_take(_c)<L, N>
+namespace detail
+{
+
+template<class L, std::size_t N, class E = void> struct mp_take_c_impl;
+
+template<template<class...> class L, class... T> struct mp_take_c_impl<L<T...>, 0>
+{
+ using type = L<>;
+};
+
+template<template<class...> class L, class T1, class... T> struct mp_take_c_impl<L<T1, T...>, 1>
+{
+ using type = L<T1>;
+};
+
+template<template<class...> class L, class T1, class T2, class... T> struct mp_take_c_impl<L<T1, T2, T...>, 2>
+{
+ using type = L<T1, T2>;
+};
+
+template<template<class...> class L, class T1, class T2, class T3, class... T> struct mp_take_c_impl<L<T1, T2, T3, T...>, 3>
+{
+ using type = L<T1, T2, T3>;
+};
+
+template<template<class...> class L, class T1, class T2, class T3, class T4, class... T> struct mp_take_c_impl<L<T1, T2, T3, T4, T...>, 4>
+{
+ using type = L<T1, T2, T3, T4>;
+};
+
+template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class... T, std::size_t N> struct mp_take_c_impl<L<T1, T2, T3, T4, T5, T...>, N, typename std::enable_if<N >= 5>::type>
+{
+ using type = mp_append<L<T1, T2, T3, T4, T5>, typename mp_take_c_impl<L<T...>, N-5>::type>;
+};
+
+} // namespace detail
+
+template<class L, std::size_t N> using mp_take_c = typename detail::mp_take_c_impl<L, N>::type;
+template<class L, class N> using mp_take = typename detail::mp_take_c_impl<L, std::size_t{ N::value }>::type;
+
+// mp_replace<L, V, W>
+namespace detail
+{
+
+template<class L, class V, class W> struct mp_replace_impl;
+
+template<template<class...> class L, class... T, class V, class W> struct mp_replace_impl<L<T...>, V, W>
+{
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
+ template<class A> struct _f { using type = mp_if<std::is_same<A, V>, W, A>; };
+ using type = L<typename _f<T>::type...>;
+#else
+ template<class A> using _f = mp_if<std::is_same<A, V>, W, A>;
+ using type = L<_f<T>...>;
+#endif
+};
+
+} // namespace detail
+
+template<class L, class V, class W> using mp_replace = typename detail::mp_replace_impl<L, V, W>::type;
+
+// mp_replace_if<L, P, W>
+namespace detail
+{
+
+template<class L, template<class...> class P, class W> struct mp_replace_if_impl;
+
+template<template<class...> class L, class... T, template<class...> class P, class W> struct mp_replace_if_impl<L<T...>, P, W>
+{
+ template<class U> using _f = mp_if<P<U>, W, U>;
+ using type = L<_f<T>...>;
+};
+
+} // namespace detail
+
+template<class L, template<class...> class P, class W> using mp_replace_if = typename detail::mp_replace_if_impl<L, P, W>::type;
+
+// mp_copy_if<L, P>
+namespace detail
+{
+
+template<class L, template<class...> class P> struct mp_copy_if_impl;
+
+template<template<class...> class L, class... T, template<class...> class P> struct mp_copy_if_impl<L<T...>, P>
+{
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
+ template<class U> struct _f { using type = mp_if<P<U>, mp_list<U>, mp_list<>>; };
+ using type = mp_append<L<>, typename _f<T>::type...>;
+#else
+ template<class U> using _f = mp_if<P<U>, mp_list<U>, mp_list<>>;
+ using type = mp_append<L<>, _f<T>...>;
+#endif
+};
+
+} // namespace detail
+
+template<class L, template<class...> class P> using mp_copy_if = typename detail::mp_copy_if_impl<L, P>::type;
+
+// mp_remove<L, V>
+namespace detail
+{
+
+template<class L, class V> struct mp_remove_impl;
+
+template<template<class...> class L, class... T, class V> struct mp_remove_impl<L<T...>, V>
+{
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
+ template<class U> struct _f { using type = mp_if<std::is_same<U, V>, mp_list<>, mp_list<U>>; };
+ using type = mp_append<L<>, typename _f<T>::type...>;
+#else
+ template<class U> using _f = mp_if<std::is_same<U, V>, mp_list<>, mp_list<U>>;
+ using type = mp_append<L<>, _f<T>...>;
+#endif
+};
+
+} // namespace detail
+
+template<class L, class V> using mp_remove = typename detail::mp_remove_impl<L, V>::type;
+
+// mp_remove_if<L, P>
+namespace detail
+{
+
+template<class L, template<class...> class P> struct mp_remove_if_impl;
+
+template<template<class...> class L, class... T, template<class...> class P> struct mp_remove_if_impl<L<T...>, P>
+{
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
+ template<class U> struct _f { using type = mp_if<P<U>, mp_list<>, mp_list<U>>; };
+ using type = mp_append<L<>, typename _f<T>::type...>;
+#else
+ template<class U> using _f = mp_if<P<U>, mp_list<>, mp_list<U>>;
+ using type = mp_append<L<>, _f<T>...>;
+#endif
+};
+
+} // namespace detail
+
+template<class L, template<class...> class P> using mp_remove_if = typename detail::mp_remove_if_impl<L, P>::type;
+
+// mp_partition<L, P>
+namespace detail
+{
+
+template<class L, template<class...> class P> struct mp_partition_impl;
+
+template<template<class...> class L, class... T, template<class...> class P> struct mp_partition_impl<L<T...>, P>
+{
+ using type = L<mp_copy_if<L<T...>, P>, mp_remove_if<L<T...>, P>>;
+};
+
+} // namespace detail
+
+template<class L, template<class...> class P> using mp_partition = typename detail::mp_partition_impl<L, P>::type;
+
+// mp_sort<L, P>
+namespace detail
+{
+
+template<class L, template<class...> class P> struct mp_sort_impl;
+
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
+
+template<template<class...> class L, class... T, template<class...> class P> struct mp_sort_impl<L<T...>, P>
+{
+ static_assert( sizeof...(T) == 0, "T... must be empty" );
+ using type = L<>;
+};
+
+#else
+
+template<template<class...> class L, template<class...> class P> struct mp_sort_impl<L<>, P>
+{
+ using type = L<>;
+};
+
+#endif
+
+template<template<class...> class L, class T1, template<class...> class P> struct mp_sort_impl<L<T1>, P>
+{
+ using type = L<T1>;
+};
+
+template<template<class...> class L, class T1, class... T, template<class...> class P> struct mp_sort_impl<L<T1, T...>, P>
+{
+ template<class U> using F = P<U, T1>;
+
+ using part = mp_partition<L<T...>, F>;
+
+ using S1 = typename mp_sort_impl<mp_first<part>, P>::type;
+ using S2 = typename mp_sort_impl<mp_second<part>, P>::type;
+
+ using type = mp_append<mp_push_back<S1, T1>, S2>;
+};
+
+} // namespace detail
+
+template<class L, template<class...> class P> using mp_sort = typename detail::mp_sort_impl<L, P>::type;
+
+// mp_find<L, V>
+namespace detail
+{
+
+template<class L, class V> struct mp_find_impl;
+
+#if defined( BOOST_CLANG ) && defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS )
+
+struct mp_index_holder
+{
+ std::size_t i_;
+ bool f_;
+};
+
+constexpr inline mp_index_holder operator+( mp_index_holder const & v, bool f )
+{
+ if( v.f_ )
+ {
+ return v;
+ }
+ else if( f )
+ {
+ return { v.i_, true };
+ }
+ else
+ {
+ return { v.i_ + 1, false };
+ }
+}
+
+template<template<class...> class L, class... T, class V> struct mp_find_impl<L<T...>, V>
+{
+ static constexpr mp_index_holder _v{ 0, false };
+ using type = mp_size_t< (_v + ... + std::is_same<T, V>::value).i_ >;
+};
+
+#elif !defined( BOOST_MP11_NO_CONSTEXPR )
+
+template<template<class...> class L, class V> struct mp_find_impl<L<>, V>
+{
+ using type = mp_size_t<0>;
+};
+
+#if !defined( BOOST_NO_CXX14_CONSTEXPR )
+
+constexpr std::size_t cx_find_index( bool const * first, bool const * last )
+{
+ std::size_t m = 0;
+
+ while( first != last && !*first )
+ {
+ ++m;
+ ++first;
+ }
+
+ return m;
+}
+
+#else
+
+constexpr std::size_t cx_find_index( bool const * first, bool const * last )
+{
+ return first == last || *first? 0: 1 + cx_find_index( first + 1, last );
+}
+
+#endif
+
+template<template<class...> class L, class... T, class V> struct mp_find_impl<L<T...>, V>
+{
+ static constexpr bool _v[] = { std::is_same<T, V>::value... };
+ using type = mp_size_t< cx_find_index( _v, _v + sizeof...(T) ) >;
+};
+
+#else
+
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
+
+template<template<class...> class L, class... T, class V> struct mp_find_impl<L<T...>, V>
+{
+ static_assert( sizeof...(T) == 0, "T... must be empty" );
+ using type = mp_size_t<0>;
+};
+
+#else
+
+template<template<class...> class L, class V> struct mp_find_impl<L<>, V>
+{
+ using type = mp_size_t<0>;
+};
+
+#endif
+
+template<template<class...> class L, class... T, class V> struct mp_find_impl<L<V, T...>, V>
+{
+ using type = mp_size_t<0>;
+};
+
+template<template<class...> class L, class T1, class... T, class V> struct mp_find_impl<L<T1, T...>, V>
+{
+ using _r = typename mp_find_impl<mp_list<T...>, V>::type;
+ using type = mp_size_t<1 + _r::value>;
+};
+
+#endif
+
+} // namespace detail
+
+template<class L, class V> using mp_find = typename detail::mp_find_impl<L, V>::type;
+
+// mp_find_if<L, P>
+namespace detail
+{
+
+template<class L, template<class...> class P> struct mp_find_if_impl;
+
+#if defined( BOOST_CLANG ) && defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS )
+
+template<template<class...> class L, class... T, template<class...> class P> struct mp_find_if_impl<L<T...>, P>
+{
+ static constexpr mp_index_holder _v{ 0, false };
+ using type = mp_size_t< (_v + ... + P<T>::value).i_ >;
+};
+
+#elif !defined( BOOST_MP11_NO_CONSTEXPR )
+
+template<template<class...> class L, template<class...> class P> struct mp_find_if_impl<L<>, P>
+{
+ using type = mp_size_t<0>;
+};
+
+template<template<class...> class L, class... T, template<class...> class P> struct mp_find_if_impl<L<T...>, P>
+{
+ static constexpr bool _v[] = { P<T>::value... };
+ using type = mp_size_t< cx_find_index( _v, _v + sizeof...(T) ) >;
+};
+
+#else
+
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
+
+template<template<class...> class L, class... T, template<class...> class P> struct mp_find_if_impl<L<T...>, P>
+{
+ static_assert( sizeof...(T) == 0, "T... must be empty" );
+ using type = mp_size_t<0>;
+};
+
+#else
+
+template<template<class...> class L, template<class...> class P> struct mp_find_if_impl<L<>, P>
+{
+ using type = mp_size_t<0>;
+};
+
+#endif
+
+template<class L, template<class...> class P> struct mp_find_if_impl_2
+{
+ using _r = typename mp_find_if_impl<L, P>::type;
+ using type = mp_size_t<1 + _r::value>;
+};
+
+template<template<class...> class L, class T1, class... T, template<class...> class P> struct mp_find_if_impl<L<T1, T...>, P>
+{
+ using type = typename mp_if<P<T1>, mp_identity<mp_size_t<0>>, mp_find_if_impl_2<mp_list<T...>, P>>::type;
+};
+
+#endif
+
+} // namespace detail
+
+template<class L, template<class...> class P> using mp_find_if = typename detail::mp_find_if_impl<L, P>::type;
+
+// mp_reverse<L>
+namespace detail
+{
+
+template<class L> struct mp_reverse_impl;
+
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
+
+template<template<class...> class L, class... T> struct mp_reverse_impl<L<T...>>
+{
+ static_assert( sizeof...(T) == 0, "T... must be empty" );
+ using type = L<>;
+};
+
+#else
+
+template<template<class...> class L> struct mp_reverse_impl<L<>>
+{
+ using type = L<>;
+};
+
+#endif
+
+template<template<class...> class L, class T1> struct mp_reverse_impl<L<T1>>
+{
+ using type = L<T1>;
+};
+
+template<template<class...> class L, class T1, class T2> struct mp_reverse_impl<L<T1, T2>>
+{
+ using type = L<T2, T1>;
+};
+
+template<template<class...> class L, class T1, class T2, class T3> struct mp_reverse_impl<L<T1, T2, T3>>
+{
+ using type = L<T3, T2, T1>;
+};
+
+template<template<class...> class L, class T1, class T2, class T3, class T4> struct mp_reverse_impl<L<T1, T2, T3, T4>>
+{
+ using type = L<T4, T3, T2, T1>;
+};
+
+template<template<class...> class L, class T1, class T2, class T3, class T4, class T5> struct mp_reverse_impl<L<T1, T2, T3, T4, T5>>
+{
+ using type = L<T5, T4, T3, T2, T1>;
+};
+
+template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6> struct mp_reverse_impl<L<T1, T2, T3, T4, T5, T6>>
+{
+ using type = L<T6, T5, T4, T3, T2, T1>;
+};
+
+template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7> struct mp_reverse_impl<L<T1, T2, T3, T4, T5, T6, T7>>
+{
+ using type = L<T7, T6, T5, T4, T3, T2, T1>;
+};
+
+template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8> struct mp_reverse_impl<L<T1, T2, T3, T4, T5, T6, T7, T8>>
+{
+ using type = L<T8, T7, T6, T5, T4, T3, T2, T1>;
+};
+
+template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9> struct mp_reverse_impl<L<T1, T2, T3, T4, T5, T6, T7, T8, T9>>
+{
+ using type = L<T9, T8, T7, T6, T5, T4, T3, T2, T1>;
+};
+
+template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T> struct mp_reverse_impl<L<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>>
+{
+ using type = mp_push_back<typename mp_reverse_impl<L<T...>>::type, T10, T9, T8, T7, T6, T5, T4, T3, T2, T1>;
+};
+
+} // namespace detail
+
+template<class L> using mp_reverse = typename detail::mp_reverse_impl<L>::type;
+
+// mp_fold<L, V, F>
+namespace detail
+{
+
+template<class L, class V, template<class...> class F> struct mp_fold_impl;
+
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
+
+template<template<class...> class L, class... T, class V, template<class...> class F> struct mp_fold_impl<L<T...>, V, F>
+{
+ static_assert( sizeof...(T) == 0, "T... must be empty" );
+ using type = V;
+};
+
+#else
+
+template<template<class...> class L, class V, template<class...> class F> struct mp_fold_impl<L<>, V, F>
+{
+ using type = V;
+};
+
+#endif
+
+template<template<class...> class L, class T1, class... T, class V, template<class...> class F> struct mp_fold_impl<L<T1, T...>, V, F>
+{
+ using type = typename mp_fold_impl<L<T...>, F<V, T1>, F>::type;
+};
+
+template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T, class V, template<class...> class F> struct mp_fold_impl<L<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>, V, F>
+{
+ using type = typename mp_fold_impl<L<T...>, F<F<F<F<F<F<F<F<F<F<V, T1>, T2>, T3>, T4>, T5>, T6>, T7>, T8>, T9>, T10>, F>::type;
+};
+
+} // namespace detail
+
+// mp_reverse_fold<L, V, F>
+namespace detail
+{
+
+template<class L, class V, template<class...> class F> struct mp_reverse_fold_impl;
+
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
+
+template<template<class...> class L, class... T, class V, template<class...> class F> struct mp_reverse_fold_impl<L<T...>, V, F>
+{
+ static_assert( sizeof...(T) == 0, "T... must be empty" );
+ using type = V;
+};
+
+#else
+
+template<template<class...> class L, class V, template<class...> class F> struct mp_reverse_fold_impl<L<>, V, F>
+{
+ using type = V;
+};
+
+#endif
+
+template<template<class...> class L, class T1, class... T, class V, template<class...> class F> struct mp_reverse_fold_impl<L<T1, T...>, V, F>
+{
+ using rest = typename mp_reverse_fold_impl<L<T...>, V, F>::type;
+ using type = F<T1, rest>;
+};
+
+template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T, class V, template<class...> class F> struct mp_reverse_fold_impl<L<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>, V, F>
+{
+ using rest = typename mp_reverse_fold_impl<L<T...>, V, F>::type;
+ using type = F<T1, F<T2, F<T3, F<T4, F<T5, F<T6, F<T7, F<T8, F<T9, F<T10, rest>>>>>>>>>>;
+};
+
+} // namespace detail
+
+template<class L, class V, template<class...> class F> using mp_reverse_fold = typename detail::mp_reverse_fold_impl<L, V, F>::type;
+
+// mp_unique<L>
+namespace detail
+{
+
+template<class L> struct mp_unique_impl;
+
+template<template<class...> class L, class... T> struct mp_unique_impl<L<T...>>
+{
+ using type = mp_set_push_back<L<>, T...>;
+};
+
+} // namespace detail
+
+template<class L> using mp_unique = typename detail::mp_unique_impl<L>::type;
+
+// mp_all_of<L, P>
+template<class L, template<class...> class P> using mp_all_of = mp_bool< mp_count_if<L, P>::value == mp_size<L>::value >;
+
+// mp_none_of<L, P>
+template<class L, template<class...> class P> using mp_none_of = mp_bool< mp_count_if<L, P>::value == 0 >;
+
+// mp_any_of<L, P>
+template<class L, template<class...> class P> using mp_any_of = mp_bool< mp_count_if<L, P>::value != 0 >;
+
+// mp_replace_at_c<L, I, W>
+namespace detail
+{
+
+template<class L, class I, class W> struct mp_replace_at_impl
+{
+ static_assert( I::value >= 0, "mp_replace_at<L, I, W>: I must not be negative" );
+
+ template<class T1, class T2> using _p = std::is_same<T2, mp_size_t<I::value>>;
+ template<class T1, class T2> using _f = W;
+
+ using type = mp_transform_if<_p, _f, L, mp_iota<mp_size<L>>>;
+};
+
+} // namespace detail
+
+template<class L, class I, class W> using mp_replace_at = typename detail::mp_replace_at_impl<L, I, W>::type;
+template<class L, std::size_t I, class W> using mp_replace_at_c = typename detail::mp_replace_at_impl<L, mp_size_t<I>, W>::type;
+
+//mp_for_each<L>(f)
+namespace detail
+{
+
+template<class... T, class F> BOOST_CONSTEXPR F mp_for_each_impl( mp_list<T...>, F && f )
+{
+ using A = int[sizeof...(T)];
+ return (void)A{ ((void)f(T()), 0)... }, std::forward<F>(f);
+}
+
+#if BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
+
+template<class F> BOOST_CONSTEXPR F mp_for_each_impl( mp_list<>, F && f )
+{
+ return std::forward<F>(f);
+}
+
+#endif
+
+} // namespace detail
+
+template<class L, class F> BOOST_CONSTEXPR F mp_for_each( F && f )
+{
+ return detail::mp_for_each_impl( mp_rename<L, mp_list>(), std::forward<F>(f) );
+}
+
+// mp_insert<L, I, T...>
+template<class L, class I, class... T> using mp_insert = mp_append<mp_take<L, I>, mp_push_front<mp_drop<L, I>, T...>>;
+
+// mp_insert_c<L, I, T...>
+template<class L, std::size_t I, class... T> using mp_insert_c = mp_append<mp_take_c<L, I>, mp_push_front<mp_drop_c<L, I>, T...>>;
+
+// mp_erase<L, I, J>
+template<class L, class I, class J> using mp_erase = mp_append<mp_take<L, I>, mp_drop<L, J>>;
+
+// mp_erase_c<L, I, J>
+template<class L, std::size_t I, std::size_t J> using mp_erase_c = mp_append<mp_take_c<L, I>, mp_drop_c<L, J>>;
+
+} // namespace mp11
+} // namespace boost
+
+#endif // #ifndef BOOST_MP11_ALGORITHM_HPP_INCLUDED
---
+++ boost\mp11\bind.hpp 2017-08-24 15:13:49.000000000 -0700
@@ -0,0 +1,105 @@
+#ifndef BOOST_MP11_BIND_HPP_INCLUDED
+#define BOOST_MP11_BIND_HPP_INCLUDED
+
+// Copyright 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/mp11/algorithm.hpp>
+#include <cstddef>
+
+namespace boost
+{
+namespace mp11
+{
+
+// mp_arg
+template<std::size_t I> struct mp_arg
+{
+ template<class... T> using fn = mp_at_c<mp_list<T...>, I>;
+};
+
+using _1 = mp_arg<0>;
+using _2 = mp_arg<1>;
+using _3 = mp_arg<2>;
+using _4 = mp_arg<3>;
+using _5 = mp_arg<4>;
+using _6 = mp_arg<5>;
+using _7 = mp_arg<6>;
+using _8 = mp_arg<7>;
+using _9 = mp_arg<8>;
+
+// mp_bind
+template<template<class...> class F, class... T> struct mp_bind;
+
+namespace detail
+{
+
+template<class V, class... T> struct eval_bound_arg
+{
+ using type = V;
+};
+
+template<std::size_t I, class... T> struct eval_bound_arg<mp_arg<I>, T...>
+{
+ using type = typename mp_arg<I>::template fn<T...>;
+};
+
+template<template<class...> class F, class... U, class... T> struct eval_bound_arg<mp_bind<F, U...>, T...>
+{
+ using type = typename mp_bind<F, U...>::template fn<T...>;
+};
+
+} // namespace detail
+
+template<template<class...> class F, class... T> struct mp_bind
+{
+ template<class... U> using fn = F<typename detail::eval_bound_arg<T, U...>::type...>;
+};
+
+template<class Q, class... T> using mp_bind_q = mp_bind<Q::template fn, T...>;
+
+// mp_bind_front
+template<template<class...> class F, class... T> struct mp_bind_front
+{
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1920 && BOOST_MSVC >= 1900 )
+#else
+private:
+#endif
+
+ template<class... U> struct _fn { using type = F<T..., U...>; };
+
+public:
+
+ // the indirection through _fn works around the language inability
+ // to expand U... into a fixed parameter list of an alias template
+
+ template<class... U> using fn = typename _fn<U...>::type;
+};
+
+template<class Q, class... T> using mp_bind_front_q = mp_bind_front<Q::template fn, T...>;
+
+// mp_bind_back
+template<template<class...> class F, class... T> struct mp_bind_back
+{
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1920 && BOOST_MSVC >= 1900 )
+#else
+private:
+#endif
+
+ template<class... U> struct _fn { using type = F<U..., T...>; };
+
+public:
+
+ template<class... U> using fn = typename _fn<U...>::type;
+};
+
+template<class Q, class... T> using mp_bind_back_q = mp_bind_back<Q::template fn, T...>;
+
+} // namespace mp11
+} // namespace boost
+
+#endif // #ifndef BOOST_MP11_BIND_HPP_INCLUDED
---
+++ boost\mp11\function.hpp 2017-08-26 01:24:32.000000000 -0700
@@ -0,0 +1,168 @@
+#ifndef BOOST_MP11_FUNCTION_HPP_INCLUDED
+#define BOOST_MP11_FUNCTION_HPP_INCLUDED
+
+// Copyright 2015-2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/utility.hpp>
+#include <boost/mp11/detail/mp_list.hpp>
+#include <boost/mp11/detail/mp_count.hpp>
+#include <boost/mp11/detail/mp_plus.hpp>
+#include <type_traits>
+
+namespace boost
+{
+namespace mp11
+{
+
+// mp_void<T...>
+namespace detail
+{
+
+template<class... T> struct mp_void_impl
+{
+ using type = void;
+};
+
+} // namespace detail
+
+template<class... T> using mp_void = typename detail::mp_void_impl<T...>::type;
+
+// mp_and<T...>
+#if BOOST_WORKAROUND( BOOST_MSVC, < 1910 )
+
+namespace detail
+{
+
+template<class... T> struct mp_and_impl;
+
+} // namespace detail
+
+template<class... T> using mp_and = mp_to_bool< typename detail::mp_and_impl<T...>::type >;
+
+namespace detail
+{
+
+template<> struct mp_and_impl<>
+{
+ using type = mp_true;
+};
+
+template<class T> struct mp_and_impl<T>
+{
+ using type = T;
+};
+
+template<class T1, class... T> struct mp_and_impl<T1, T...>
+{
+ using type = mp_eval_if< mp_not<T1>, T1, mp_and, T... >;
+};
+
+} // namespace detail
+
+#else
+
+namespace detail
+{
+
+template<class L, class E = void> struct mp_and_impl
+{
+ using type = mp_false;
+};
+
+template<class... T> struct mp_and_impl< mp_list<T...>, mp_void<mp_if<T, void>...> >
+{
+ using type = mp_true;
+};
+
+} // namespace detail
+
+template<class... T> using mp_and = typename detail::mp_and_impl<mp_list<T...>>::type;
+
+#endif
+
+// mp_all<T...>
+#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 ) || BOOST_WORKAROUND( BOOST_GCC, < 70300 )
+
+template<class... T> using mp_all = mp_bool< mp_count_if< mp_list<T...>, mp_not >::value == 0 >;
+
+#elif defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS )
+
+template<class... T> using mp_all = mp_bool<(static_cast<bool>(T::value) && ...)>;
+
+#else
+
+template<class... T> using mp_all = mp_and<mp_to_bool<T>...>;
+
+#endif
+
+// mp_or<T...>
+namespace detail
+{
+
+template<class... T> struct mp_or_impl;
+
+} // namespace detail
+
+template<class... T> using mp_or = mp_to_bool< typename detail::mp_or_impl<T...>::type >;
+
+namespace detail
+{
+
+template<> struct mp_or_impl<>
+{
+ using type = mp_false;
+};
+
+template<class T> struct mp_or_impl<T>
+{
+ using type = T;
+};
+
+template<class T1, class... T> struct mp_or_impl<T1, T...>
+{
+ using type = mp_eval_if< T1, T1, mp_or, T... >;
+};
+
+} // namespace detail
+
+// mp_any<T...>
+#if defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS ) && !BOOST_WORKAROUND( BOOST_GCC, < 70300 )
+
+template<class... T> using mp_any = mp_bool<(static_cast<bool>(T::value) || ...)>;
+
+#else
+
+template<class... T> using mp_any = mp_bool< mp_count_if< mp_list<T...>, mp_to_bool >::value != 0 >;
+
+#endif
+
+// mp_same<T...>
+namespace detail
+{
+
+template<class... T> struct mp_same_impl;
+
+template<> struct mp_same_impl<>
+{
+ using type = mp_true;
+};
+
+template<class T1, class... T> struct mp_same_impl<T1, T...>
+{
+ using type = mp_all<std::is_same<T1, T>...>;
+};
+
+} // namespace detail
+
+template<class... T> using mp_same = typename detail::mp_same_impl<T...>::type;
+
+} // namespace mp11
+} // namespace boost
+
+#endif // #ifndef BOOST_MP11_FUNCTION_HPP_INCLUDED
---
+++ boost\mp11\integer_sequence.hpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,97 @@
+#ifndef BOOST_MP11_INTEGER_SEQUENCE_HPP_INCLUDED
+#define BOOST_MP11_INTEGER_SEQUENCE_HPP_INCLUDED
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <cstddef>
+
+namespace boost
+{
+namespace mp11
+{
+
+// integer_sequence
+template<class T, T... I> struct integer_sequence
+{
+};
+
+// detail::make_integer_sequence_impl
+namespace detail
+{
+
+// iseq_if_c
+template<bool C, class T, class E> struct iseq_if_c_impl;
+
+template<class T, class E> struct iseq_if_c_impl<true, T, E>
+{
+ using type = T;
+};
+
+template<class T, class E> struct iseq_if_c_impl<false, T, E>
+{
+ using type = E;
+};
+
+template<bool C, class T, class E> using iseq_if_c = typename iseq_if_c_impl<C, T, E>::type;
+
+// iseq_identity
+template<class T> struct iseq_identity
+{
+ using type = T;
+};
+
+template<class S1, class S2> struct append_integer_sequence;
+
+template<class T, T... I, T... J> struct append_integer_sequence<integer_sequence<T, I...>, integer_sequence<T, J...>>
+{
+ using type = integer_sequence< T, I..., ( J + sizeof...(I) )... >;
+};
+
+template<class T, T N> struct make_integer_sequence_impl;
+
+template<class T, T N> struct make_integer_sequence_impl_
+{
+private:
+
+ static_assert( N >= 0, "make_integer_sequence<T, N>: N must not be negative" );
+
+ static T const M = N / 2;
+ static T const R = N % 2;
+
+ using S1 = typename make_integer_sequence_impl<T, M>::type;
+ using S2 = typename append_integer_sequence<S1, S1>::type;
+ using S3 = typename make_integer_sequence_impl<T, R>::type;
+ using S4 = typename append_integer_sequence<S2, S3>::type;
+
+public:
+
+ using type = S4;
+};
+
+template<class T, T N> struct make_integer_sequence_impl: iseq_if_c<N == 0, iseq_identity<integer_sequence<T>>, iseq_if_c<N == 1, iseq_identity<integer_sequence<T, 0>>, make_integer_sequence_impl_<T, N>>>
+{
+};
+
+} // namespace detail
+
+// make_integer_sequence
+template<class T, T N> using make_integer_sequence = typename detail::make_integer_sequence_impl<T, N>::type;
+
+// index_sequence
+template<std::size_t... I> using index_sequence = integer_sequence<std::size_t, I...>;
+
+// make_index_sequence
+template<std::size_t N> using make_index_sequence = make_integer_sequence<std::size_t, N>;
+
+// index_sequence_for
+template<class... T> using index_sequence_for = make_integer_sequence<std::size_t, sizeof...(T)>;
+
+} // namespace mp11
+} // namespace boost
+
+#endif // #ifndef BOOST_MP11_INTEGER_SEQUENCE_HPP_INCLUDED
---
+++ boost\mp11\integral.hpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,40 @@
+#ifndef BOOST_MP11_INTEGRAL_HPP_INCLUDED
+#define BOOST_MP11_INTEGRAL_HPP_INCLUDED
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <type_traits>
+#include <cstddef>
+
+namespace boost
+{
+namespace mp11
+{
+
+// mp_bool
+template<bool B> using mp_bool = std::integral_constant<bool, B>;
+
+using mp_true = mp_bool<true>;
+using mp_false = mp_bool<false>;
+
+// mp_to_bool
+template<class T> using mp_to_bool = mp_bool<static_cast<bool>( T::value )>;
+
+// mp_not<T>
+template<class T> using mp_not = mp_bool< !T::value >;
+
+// mp_int
+template<int I> using mp_int = std::integral_constant<int, I>;
+
+// mp_size_t
+template<std::size_t N> using mp_size_t = std::integral_constant<std::size_t, N>;
+
+} // namespace mp11
+} // namespace boost
+
+#endif // #ifndef BOOST_MP11_INTEGRAL_HPP_INCLUDED
---
+++ boost\mp11\list.hpp 2017-08-28 02:56:56.000000000 -0700
@@ -0,0 +1,246 @@
+#ifndef BOOST_MP11_LIST_HPP_INCLUDED
+#define BOOST_MP11_LIST_HPP_INCLUDED
+
+// Copyright 2015-2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/detail/mp_list.hpp>
+#include <boost/mp11/detail/mp_append.hpp>
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+
+namespace boost
+{
+namespace mp11
+{
+
+// mp_size<L>
+namespace detail
+{
+
+template<class L> struct mp_size_impl
+{
+// An error "no type named 'type'" here means that the argument to mp_size is not a list
+};
+
+template<template<class...> class L, class... T> struct mp_size_impl<L<T...>>
+{
+ using type = mp_size_t<sizeof...(T)>;
+};
+
+} // namespace detail
+
+template<class L> using mp_size = typename detail::mp_size_impl<L>::type;
+
+// mp_empty<L>
+template<class L> using mp_empty = mp_bool< mp_size<L>::value == 0 >;
+
+// mp_front<L>
+namespace detail
+{
+
+template<class L> struct mp_front_impl
+{
+// An error "no type named 'type'" here means that the argument to mp_front
+// is either not a list, or is an empty list
+};
+
+template<template<class...> class L, class T1, class... T> struct mp_front_impl<L<T1, T...>>
+{
+ using type = T1;
+};
+
+} // namespace detail
+
+template<class L> using mp_front = typename detail::mp_front_impl<L>::type;
+
+// mp_pop_front<L>
+namespace detail
+{
+
+template<class L> struct mp_pop_front_impl
+{
+// An error "no type named 'type'" here means that the argument to mp_pop_front
+// is either not a list, or is an empty list
+};
+
+template<template<class...> class L, class T1, class... T> struct mp_pop_front_impl<L<T1, T...>>
+{
+ using type = L<T...>;
+};
+
+} // namespace detail
+
+template<class L> using mp_pop_front = typename detail::mp_pop_front_impl<L>::type;
+
+// mp_first<L>
+template<class L> using mp_first = mp_front<L>;
+
+// mp_rest<L>
+template<class L> using mp_rest = mp_pop_front<L>;
+
+// mp_second<L>
+namespace detail
+{
+
+template<class L> struct mp_second_impl
+{
+// An error "no type named 'type'" here means that the argument to mp_second
+// is either not a list, or has fewer than two elements
+};
+
+template<template<class...> class L, class T1, class T2, class... T> struct mp_second_impl<L<T1, T2, T...>>
+{
+ using type = T2;
+};
+
+} // namespace detail
+
+template<class L> using mp_second = typename detail::mp_second_impl<L>::type;
+
+// mp_third<L>
+namespace detail
+{
+
+template<class L> struct mp_third_impl
+{
+// An error "no type named 'type'" here means that the argument to mp_third
+// is either not a list, or has fewer than three elements
+};
+
+template<template<class...> class L, class T1, class T2, class T3, class... T> struct mp_third_impl<L<T1, T2, T3, T...>>
+{
+ using type = T3;
+};
+
+} // namespace detail
+
+template<class L> using mp_third = typename detail::mp_third_impl<L>::type;
+
+// mp_push_front<L, T...>
+namespace detail
+{
+
+template<class L, class... T> struct mp_push_front_impl
+{
+// An error "no type named 'type'" here means that the first argument to mp_push_front is not a list
+};
+
+template<template<class...> class L, class... U, class... T> struct mp_push_front_impl<L<U...>, T...>
+{
+ using type = L<T..., U...>;
+};
+
+} // namespace detail
+
+template<class L, class... T> using mp_push_front = typename detail::mp_push_front_impl<L, T...>::type;
+
+// mp_push_back<L, T...>
+namespace detail
+{
+
+template<class L, class... T> struct mp_push_back_impl
+{
+// An error "no type named 'type'" here means that the first argument to mp_push_back is not a list
+};
+
+template<template<class...> class L, class... U, class... T> struct mp_push_back_impl<L<U...>, T...>
+{
+ using type = L<U..., T...>;
+};
+
+} // namespace detail
+
+template<class L, class... T> using mp_push_back = typename detail::mp_push_back_impl<L, T...>::type;
+
+// mp_rename<L, B>
+namespace detail
+{
+
+template<class A, template<class...> class B> struct mp_rename_impl
+{
+// An error "no type named 'type'" here means that the first argument to mp_rename is not a list
+};
+
+template<template<class...> class A, class... T, template<class...> class B> struct mp_rename_impl<A<T...>, B>
+{
+ using type = B<T...>;
+};
+
+} // namespace detail
+
+template<class A, template<class...> class B> using mp_rename = typename detail::mp_rename_impl<A, B>::type;
+
+template<template<class...> class F, class L> using mp_apply = typename detail::mp_rename_impl<L, F>::type;
+
+template<class Q, class L> using mp_apply_q = typename detail::mp_rename_impl<L, Q::template fn>::type;
+
+// mp_replace_front<L, T>
+namespace detail
+{
+
+template<class L, class T> struct mp_replace_front_impl
+{
+// An error "no type named 'type'" here means that the first argument to mp_replace_front
+// is either not a list, or is an empty list
+};
+
+template<template<class...> class L, class U1, class... U, class T> struct mp_replace_front_impl<L<U1, U...>, T>
+{
+ using type = L<T, U...>;
+};
+
+} // namespace detail
+
+template<class L, class T> using mp_replace_front = typename detail::mp_replace_front_impl<L, T>::type;
+
+// mp_replace_first<L, T>
+template<class L, class T> using mp_replace_first = typename detail::mp_replace_front_impl<L, T>::type;
+
+// mp_replace_second<L, T>
+namespace detail
+{
+
+template<class L, class T> struct mp_replace_second_impl
+{
+// An error "no type named 'type'" here means that the first argument to mp_replace_second
+// is either not a list, or has fewer than two elements
+};
+
+template<template<class...> class L, class U1, class U2, class... U, class T> struct mp_replace_second_impl<L<U1, U2, U...>, T>
+{
+ using type = L<U1, T, U...>;
+};
+
+} // namespace detail
+
+template<class L, class T> using mp_replace_second = typename detail::mp_replace_second_impl<L, T>::type;
+
+// mp_replace_third<L, T>
+namespace detail
+{
+
+template<class L, class T> struct mp_replace_third_impl
+{
+// An error "no type named 'type'" here means that the first argument to mp_replace_third
+// is either not a list, or has fewer than three elements
+};
+
+template<template<class...> class L, class U1, class U2, class U3, class... U, class T> struct mp_replace_third_impl<L<U1, U2, U3, U...>, T>
+{
+ using type = L<U1, U2, T, U...>;
+};
+
+} // namespace detail
+
+template<class L, class T> using mp_replace_third = typename detail::mp_replace_third_impl<L, T>::type;
+
+} // namespace mp11
+} // namespace boost
+
+#endif // #ifndef BOOST_MP11_LIST_HPP_INCLUDED
---
+++ boost\mp11\map.hpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,118 @@
+#ifndef BOOST_MP11_MAP_HPP_INCLUDED
+#define BOOST_MP11_MAP_HPP_INCLUDED
+
+// Copyright 2015-2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/mp11/detail/mp_map_find.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/utility.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/function.hpp>
+#include <boost/mp11/set.hpp>
+#include <type_traits>
+
+namespace boost
+{
+namespace mp11
+{
+
+// mp_map_contains<M, K>
+template<class M, class K> using mp_map_contains = mp_not<std::is_same<mp_map_find<M, K>, void>>;
+
+// mp_map_insert<M, T>
+template<class M, class T> using mp_map_insert = mp_if< mp_map_contains<M, mp_first<T>>, M, mp_push_back<M, T> >;
+
+// mp_map_replace<M, T>
+namespace detail
+{
+
+template<class M, class T> struct mp_map_replace_impl;
+
+template<template<class...> class M, class... U, class T> struct mp_map_replace_impl<M<U...>, T>
+{
+ using K = mp_first<T>;
+
+ // mp_replace_if is inlined here using a struct _f because of msvc-14.0
+
+ template<class V> struct _f { using type = mp_if< std::is_same<mp_first<V>, K>, T, V >; };
+
+ using type = mp_if< mp_map_contains<M<U...>, K>, M<typename _f<U>::type...>, M<U..., T> >;
+};
+
+} // namespace detail
+
+template<class M, class T> using mp_map_replace = typename detail::mp_map_replace_impl<M, T>::type;
+
+// mp_map_update<M, T, F>
+namespace detail
+{
+
+template<class M, class T, template<class...> class F> struct mp_map_update_impl
+{
+ template<class U> using _f = std::is_same<mp_first<T>, mp_first<U>>;
+
+ // _f3<L<X, Y...>> -> L<X, F<X, Y...>>
+ template<class L> using _f3 = mp_assign<L, mp_list<mp_first<L>, mp_rename<L, F>>>;
+
+ using type = mp_if< mp_map_contains<M, mp_first<T>>, mp_transform_if<_f, _f3, M>, mp_push_back<M, T> >;
+};
+
+} // namespace detail
+
+template<class M, class T, template<class...> class F> using mp_map_update = typename detail::mp_map_update_impl<M, T, F>::type;
+
+// mp_map_erase<M, K>
+namespace detail
+{
+
+template<class M, class K> struct mp_map_erase_impl
+{
+ template<class T> using _f = std::is_same<mp_first<T>, K>;
+ using type = mp_remove_if<M, _f>;
+};
+
+} // namespace detail
+
+template<class M, class K> using mp_map_erase = typename detail::mp_map_erase_impl<M, K>::type;
+
+// mp_map_keys<M>
+template<class M> using mp_map_keys = mp_transform<mp_first, M>;
+
+// mp_is_map<M>
+namespace detail
+{
+
+template<class L> struct mp_is_map_element: mp_false
+{
+};
+
+template<template<class...> class L, class T1, class... T> struct mp_is_map_element<L<T1, T...>>: mp_true
+{
+};
+
+template<class M> using mp_keys_are_set = mp_is_set<mp_map_keys<M>>;
+
+template<class M> struct mp_is_map_impl
+{
+ using type = mp_false;
+};
+
+template<template<class...> class M, class... T> struct mp_is_map_impl<M<T...>>
+{
+ using type = mp_eval_if<mp_not<mp_all<mp_is_map_element<T>...>>, mp_false, mp_keys_are_set, M<T...>>;
+};
+
+} // namespace detail
+
+template<class M> using mp_is_map = typename detail::mp_is_map_impl<M>::type;
+
+} // namespace mp11
+} // namespace boost
+
+#endif // #ifndef BOOST_MP11_MAP_HPP_INCLUDED
---
+++ boost\mp11\mpl.hpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,175 @@
+#ifndef BOOST_MP11_MPL_HPP_INCLUDED
+#define BOOST_MP11_MPL_HPP_INCLUDED
+
+// Copyright 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <tuple>
+
+namespace boost
+{
+namespace mpl
+{
+
+struct forward_iterator_tag;
+
+namespace aux
+{
+
+struct mp11_tag {};
+
+template<class L> struct mp11_iterator
+{
+ using category = forward_iterator_tag;
+
+ using type = mp11::mp_first<L>;
+ using next = mp11_iterator<mp11::mp_rest<L>>;
+};
+
+} // namespace aux
+
+// at
+
+template< typename Tag > struct at_impl;
+
+template<> struct at_impl<aux::mp11_tag>
+{
+ template<class L, class I> struct apply
+ {
+ using type = mp11::mp_at<L, I>;
+ };
+};
+
+// back
+
+template< typename Tag > struct back_impl;
+
+template<> struct back_impl<aux::mp11_tag>
+{
+ template<class L> struct apply
+ {
+ using N = mp11::mp_size<L>;
+ using type = mp11::mp_at_c<L, N::value - 1>;
+ };
+};
+
+// begin
+
+template< typename Tag > struct begin_impl;
+
+template<> struct begin_impl<aux::mp11_tag>
+{
+ template<class L> struct apply
+ {
+ using type = aux::mp11_iterator<L>;
+ };
+};
+
+// clear
+
+template< typename Tag > struct clear_impl;
+
+template<> struct clear_impl<aux::mp11_tag>
+{
+ template<class L> struct apply
+ {
+ using type = mp11::mp_clear<L>;
+ };
+};
+
+// end
+
+template< typename Tag > struct end_impl;
+
+template<> struct end_impl<aux::mp11_tag>
+{
+ template<class L> struct apply
+ {
+ using type = aux::mp11_iterator<mp11::mp_clear<L>>;
+ };
+};
+
+// front
+
+template< typename Tag > struct front_impl;
+
+template<> struct front_impl<aux::mp11_tag>
+{
+ template<class L> struct apply
+ {
+ using type = mp11::mp_front<L>;
+ };
+};
+
+// pop_front
+
+template< typename Tag > struct pop_front_impl;
+
+template<> struct pop_front_impl<aux::mp11_tag>
+{
+ template<class L> struct apply
+ {
+ using type = mp11::mp_pop_front<L>;
+ };
+};
+
+// push_back
+
+template< typename Tag > struct push_back_impl;
+
+template<> struct push_back_impl<aux::mp11_tag>
+{
+ template<class L, class T> struct apply
+ {
+ using type = mp11::mp_push_back<L, T>;
+ };
+};
+
+// push_front
+
+template< typename Tag > struct push_front_impl;
+
+template<> struct push_front_impl<aux::mp11_tag>
+{
+ template<class L, class T> struct apply
+ {
+ using type = mp11::mp_push_front<L, T>;
+ };
+};
+
+// sequence_tag
+
+template< typename Sequence > struct sequence_tag;
+
+template<class... T> struct sequence_tag<mp11::mp_list<T...>>
+{
+ using type = aux::mp11_tag;
+};
+
+template<class... T> struct sequence_tag<std::tuple<T...>>
+{
+ using type = aux::mp11_tag;
+};
+
+// size
+
+template< typename Tag > struct size_impl;
+
+template<> struct size_impl<aux::mp11_tag>
+{
+ template<class L> struct apply
+ {
+ using type = mp11::mp_size<L>;
+ };
+};
+
+} // namespace mpl
+} // namespace boost
+
+#endif // #ifndef BOOST_MP11_MPL_HPP_INCLUDED
---
+++ boost\mp11\set.hpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,103 @@
+#ifndef BOOST_MP11_SET_HPP_INCLUDED
+#define BOOST_MP11_SET_HPP_INCLUDED
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/mp11/utility.hpp>
+#include <boost/mp11/detail/mp_list.hpp>
+#include <type_traits>
+
+namespace boost
+{
+namespace mp11
+{
+
+// mp_set_contains<S, V>
+namespace detail
+{
+
+template<class S, class V> struct mp_set_contains_impl;
+
+template<template<class...> class L, class... T, class V> struct mp_set_contains_impl<L<T...>, V>
+{
+ using type = mp_to_bool<std::is_base_of<mp_identity<V>, mp_inherit<mp_identity<T>...>>>;
+};
+
+} // namespace detail
+
+template<class S, class V> using mp_set_contains = typename detail::mp_set_contains_impl<S, V>::type;
+
+// mp_set_push_back<S, T...>
+namespace detail
+{
+
+template<class S, class... T> struct mp_set_push_back_impl;
+
+template<template<class...> class L, class... U> struct mp_set_push_back_impl<L<U...>>
+{
+ using type = L<U...>;
+};
+
+template<template<class...> class L, class... U, class T1, class... T> struct mp_set_push_back_impl<L<U...>, T1, T...>
+{
+ using S = mp_if<mp_set_contains<L<U...>, T1>, L<U...>, L<U..., T1>>;
+ using type = typename mp_set_push_back_impl<S, T...>::type;
+};
+
+} // namespace detail
+
+template<class S, class... T> using mp_set_push_back = typename detail::mp_set_push_back_impl<S, T...>::type;
+
+// mp_set_push_front<S, T...>
+namespace detail
+{
+
+template<class S, class... T> struct mp_set_push_front_impl;
+
+template<template<class...> class L, class... U> struct mp_set_push_front_impl<L<U...>>
+{
+ using type = L<U...>;
+};
+
+template<template<class...> class L, class... U, class T1> struct mp_set_push_front_impl<L<U...>, T1>
+{
+ using type = mp_if<mp_set_contains<L<U...>, T1>, L<U...>, L<T1, U...>>;
+};
+
+template<template<class...> class L, class... U, class T1, class... T> struct mp_set_push_front_impl<L<U...>, T1, T...>
+{
+ using S = typename mp_set_push_front_impl<L<U...>, T...>::type;
+ using type = typename mp_set_push_front_impl<S, T1>::type;
+};
+
+} // namespace detail
+
+template<class S, class... T> using mp_set_push_front = typename detail::mp_set_push_front_impl<S, T...>::type;
+
+// mp_is_set<S>
+namespace detail
+{
+
+template<class S> struct mp_is_set_impl
+{
+ using type = mp_false;
+};
+
+template<template<class...> class L, class... T> struct mp_is_set_impl<L<T...>>
+{
+ using type = mp_to_bool<std::is_same<mp_list<T...>, mp_set_push_back<mp_list<>, T...>>>;
+};
+
+} // namespace detail
+
+template<class S> using mp_is_set = typename detail::mp_is_set_impl<S>::type;
+
+} // namespace mp11
+} // namespace boost
+
+#endif // #ifndef BOOST_MP11_SET_HPP_INCLUDED
---
+++ boost\mp11\tuple.hpp 2017-08-28 02:56:56.000000000 -0700
@@ -0,0 +1,92 @@
+#ifndef BOOST_MP11_TUPLE_HPP_INCLUDED
+#define BOOST_MP11_TUPLE_HPP_INCLUDED
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/mp11/integer_sequence.hpp>
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+#include <tuple>
+#include <utility>
+#include <type_traits>
+#include <cstddef>
+
+namespace boost
+{
+namespace mp11
+{
+
+// tuple_apply
+namespace detail
+{
+
+template<class F, class Tp, std::size_t... J> BOOST_CONSTEXPR auto tuple_apply_impl( F && f, Tp && tp, integer_sequence<std::size_t, J...> )
+ -> decltype( std::forward<F>(f)( std::get<J>(std::forward<Tp>(tp))... ) )
+{
+ return std::forward<F>(f)( std::get<J>(std::forward<Tp>(tp))... );
+}
+
+} // namespace detail
+
+template<class F, class Tp,
+ class Seq = make_index_sequence<std::tuple_size<typename std::remove_reference<Tp>::type>::value>>
+BOOST_CONSTEXPR auto tuple_apply( F && f, Tp && tp )
+ -> decltype( detail::tuple_apply_impl( std::forward<F>(f), std::forward<Tp>(tp), Seq() ) )
+{
+ return detail::tuple_apply_impl( std::forward<F>(f), std::forward<Tp>(tp), Seq() );
+}
+
+// construct_from_tuple
+namespace detail
+{
+
+template<class T, class Tp, std::size_t... J> BOOST_CONSTEXPR T construct_from_tuple_impl( Tp && tp, integer_sequence<std::size_t, J...> )
+{
+ return T( std::get<J>(std::forward<Tp>(tp))... );
+}
+
+} // namespace detail
+
+template<class T, class Tp,
+ class Seq = make_index_sequence<std::tuple_size<typename std::remove_reference<Tp>::type>::value>>
+BOOST_CONSTEXPR T construct_from_tuple( Tp && tp )
+{
+ return detail::construct_from_tuple_impl<T>( std::forward<Tp>(tp), Seq() );
+}
+
+// tuple_for_each
+namespace detail
+{
+
+template<class Tp, std::size_t... J, class F> BOOST_CONSTEXPR F tuple_for_each_impl( Tp && tp, integer_sequence<std::size_t, J...>, F && f )
+{
+ using A = int[sizeof...(J)];
+ return (void)A{ ((void)f(std::get<J>(std::forward<Tp>(tp))), 0)... }, std::forward<F>(f);
+}
+
+#if BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
+
+template<class Tp, class F> BOOST_CONSTEXPR F tuple_for_each_impl( Tp && tp, integer_sequence<std::size_t>, F && f )
+{
+ return std::forward<F>(f);
+}
+
+#endif
+
+} // namespace detail
+
+template<class Tp, class F> BOOST_CONSTEXPR F tuple_for_each( Tp && tp, F && f )
+{
+ using seq = make_index_sequence<std::tuple_size<typename std::remove_reference<Tp>::type>::value>;
+ return detail::tuple_for_each_impl( std::forward<Tp>(tp), seq(), std::forward<F>(f) );
+}
+
+} // namespace mp11
+} // namespace boost
+
+#endif // #ifndef BOOST_TUPLE_HPP_INCLUDED
---
+++ boost\mp11\utility.hpp 2017-08-28 02:56:56.000000000 -0700
@@ -0,0 +1,150 @@
+#ifndef BOOST_MP11_UTILITY_HPP_INCLUDED
+#define BOOST_MP11_UTILITY_HPP_INCLUDED
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/mp11/integral.hpp>
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+
+namespace boost
+{
+namespace mp11
+{
+
+// mp_identity
+template<class T> struct mp_identity
+{
+ using type = T;
+};
+
+// mp_identity_t
+template<class T> using mp_identity_t = typename mp_identity<T>::type;
+
+// mp_inherit
+template<class... T> struct mp_inherit: T... {};
+
+// mp_if, mp_if_c
+namespace detail
+{
+
+template<bool C, class T, class... E> struct mp_if_c_impl
+{
+};
+
+template<class T, class... E> struct mp_if_c_impl<true, T, E...>
+{
+ using type = T;
+};
+
+template<class T, class E> struct mp_if_c_impl<false, T, E>
+{
+ using type = E;
+};
+
+} // namespace detail
+
+template<bool C, class T, class... E> using mp_if_c = typename detail::mp_if_c_impl<C, T, E...>::type;
+template<class C, class T, class... E> using mp_if = typename detail::mp_if_c_impl<static_cast<bool>(C::value), T, E...>::type;
+
+// mp_valid
+// implementation by Bruno Dutra (by the name is_evaluable)
+namespace detail
+{
+
+template<template<class...> class F, class... T> struct mp_valid_impl
+{
+ template<template<class...> class G, class = G<T...>> static mp_true check(int);
+ template<template<class...> class> static mp_false check(...);
+
+ using type = decltype(check<F>(0));
+};
+
+} // namespace detail
+
+template<template<class...> class F, class... T> using mp_valid = typename detail::mp_valid_impl<F, T...>::type;
+
+// mp_defer
+namespace detail
+{
+
+template<template<class...> class F, class... T> struct mp_defer_impl
+{
+ using type = F<T...>;
+};
+
+struct mp_no_type
+{
+};
+
+} // namespace detail
+
+template<template<class...> class F, class... T> using mp_defer = mp_if<mp_valid<F, T...>, detail::mp_defer_impl<F, T...>, detail::mp_no_type>;
+
+// mp_eval_if, mp_eval_if_c
+namespace detail
+{
+
+template<bool C, class T, template<class...> class F, class... U> struct mp_eval_if_c_impl;
+
+template<class T, template<class...> class F, class... U> struct mp_eval_if_c_impl<true, T, F, U...>
+{
+ using type = T;
+};
+
+template<class T, template<class...> class F, class... U> struct mp_eval_if_c_impl<false, T, F, U...>: mp_defer<F, U...>
+{
+};
+
+} // namespace detail
+
+template<bool C, class T, template<class...> class F, class... U> using mp_eval_if_c = typename detail::mp_eval_if_c_impl<C, T, F, U...>::type;
+template<class C, class T, template<class...> class F, class... U> using mp_eval_if = typename detail::mp_eval_if_c_impl<static_cast<bool>(C::value), T, F, U...>::type;
+template<class C, class T, class Q, class... U> using mp_eval_if_q = typename detail::mp_eval_if_c_impl<static_cast<bool>(C::value), T, Q::template fn, U...>::type;
+
+// mp_quote
+template<template<class...> class F> struct mp_quote
+{
+ // the indirection through mp_defer works around the language inability
+ // to expand T... into a fixed parameter list of an alias template
+
+ template<class... T> using fn = typename mp_defer<F, T...>::type;
+};
+
+// mp_quote_trait
+template<template<class...> class F> struct mp_quote_trait
+{
+ template<class... T> using fn = typename F<T...>::type;
+};
+
+// mp_invoke
+#if BOOST_WORKAROUND( BOOST_MSVC, < 1900 )
+
+namespace detail
+{
+
+template<class Q, class... T> struct mp_invoke_impl: mp_defer<Q::template fn, T...> {};
+
+} // namespace detail
+
+template<class Q, class... T> using mp_invoke = typename detail::mp_invoke_impl<Q, T...>::type;
+
+#elif BOOST_WORKAROUND( BOOST_GCC, < 50000 )
+
+template<class Q, class... T> using mp_invoke = typename mp_defer<Q::template fn, T...>::type;
+
+#else
+
+template<class Q, class... T> using mp_invoke = typename Q::template fn<T...>;
+
+#endif
+
+} // namespace mp11
+} // namespace boost
+
+#endif // #ifndef BOOST_MP11_UTILITY_HPP_INCLUDED
--- boost\multiprecision\cpp_int\add.hpp 2017-08-19 09:49:44.000000000 -0700
+++ boost\multiprecision\cpp_int\add.hpp 2017-08-21 15:43:40.000000000 -0700
@@ -61,13 +61,13 @@
// Now where only a has digits:
while(pr != pr_end)
{
if(!carry)
{
if(pa != pr)
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) && !defined(NDEBUG)
std::copy(pa, pa + (pr_end - pr), stdext::checked_array_iterator<limb_type*>(pr, result.size()));
#else
std::copy(pa, pa + (pr_end - pr), pr);
#endif
break;
}
@@ -198,13 +198,13 @@
pr[i] = static_cast<limb_type>(borrow);
borrow = (borrow >> CppInt1::limb_bits) & 1u;
++i;
}
// Any remaining digits are the same as those in pa:
if((x != i) && (pa != pr))
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) && !defined(NDEBUG)
std::copy(pa + i, pa + x, stdext::checked_array_iterator<limb_type*>(pr + i, result.size() - i));
#else
std::copy(pa + i, pa + x, pr + i);
#endif
BOOST_ASSERT(0 == borrow);
@@ -230,13 +230,13 @@
typename CppInt2::const_limb_pointer pa = a.limbs();
if(*pa >= b)
{
*pr = *pa - b;
if(&result != &a)
{
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) && !defined(NDEBUG)
std::copy(pa + 1, pa + a.size(), stdext::checked_array_iterator<limb_type*>(pr + 1, result.size() - 1));
#else
std::copy(pa + 1, pa + a.size(), pr + 1);
#endif
result.sign(a.sign());
}
@@ -260,13 +260,13 @@
++i;
}
pr[i] = pa[i] - 1;
if(&result != &a)
{
++i;
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) && !defined(NDEBUG)
std::copy(pa + i, pa + a.size(), stdext::checked_array_iterator<limb_type*>(pr + i, result.size() - i));
#else
std::copy(pa + i, pa + a.size(), pr + i);
#endif
}
result.normalize();
--- boost\multiprecision\cpp_int\comparison.hpp 2017-08-19 09:49:44.000000000 -0700
+++ boost\multiprecision\cpp_int\comparison.hpp 2017-08-21 15:43:52.000000000 -0700
@@ -24,13 +24,13 @@
BOOST_MP_FORCEINLINE typename enable_if_c<
!is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
bool
>::type
eval_eq(const cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& a, const cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& b) BOOST_NOEXCEPT
{
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) && !defined(NDEBUG)
return (a.sign() == b.sign())
&& (a.size() == b.size())
&& std::equal(a.limbs(), a.limbs() + a.size(),
stdext::checked_array_iterator<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>::const_limb_pointer>(b.limbs(), b.size()));
#else
return (a.sign() == b.sign())
@@ -43,13 +43,13 @@
!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,
bool
>::type
eval_eq(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b) BOOST_NOEXCEPT
{
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) && !defined(NDEBUG)
return (a.sign() == b.sign())
&& (a.size() == b.size())
&& std::equal(a.limbs(), a.limbs() + a.size(), stdext::checked_array_iterator<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::const_limb_pointer>(b.limbs(), b.size()));
#else
return (a.sign() == b.sign())
&& (a.size() == b.size())
--- boost\numeric\conversion\detail\converter.hpp 2017-08-19 09:49:44.000000000 -0700
+++ boost\numeric\conversion\detail\converter.hpp 2017-08-26 22:06:39.000000000 -0700
@@ -7,17 +7,17 @@
//
// Contact the author at: fernando_cacciola@hotmail.com
//
#ifndef BOOST_NUMERIC_CONVERSION_DETAIL_CONVERTER_FLC_12NOV2002_HPP
#define BOOST_NUMERIC_CONVERSION_DETAIL_CONVERTER_FLC_12NOV2002_HPP
-#include <functional>
-
#include "boost/numeric/conversion/detail/meta.hpp"
#include "boost/numeric/conversion/detail/conversion_traits.hpp"
#include "boost/numeric/conversion/bounds.hpp"
+
+#include "boost/limits.hpp"
#include "boost/type_traits/is_same.hpp"
#include "boost/mpl/integral_c.hpp"
namespace boost { namespace numeric { namespace convdetail
@@ -447,19 +447,16 @@
//--------------------------------------------------------------------------
//
// Trivial Converter : used when (cv-unqualified) T == (cv-unqualified) S
//
template<class Traits>
- struct trivial_converter_impl : public std::unary_function< BOOST_DEDUCED_TYPENAME Traits::argument_type
- ,BOOST_DEDUCED_TYPENAME Traits::result_type
- >
- ,public dummy_range_checker<Traits>
+ struct trivial_converter_impl : public dummy_range_checker<Traits>
{
typedef Traits traits ;
-
+
typedef typename Traits::source_type source_type ;
typedef typename Traits::argument_type argument_type ;
typedef typename Traits::result_type result_type ;
static result_type low_level_convert ( argument_type s ) { return s ; }
static source_type nearbyint ( argument_type s ) { return s ; }
@@ -468,16 +465,13 @@
//
// Rounding Converter : used for float to integral conversions.
//
template<class Traits,class RangeChecker,class RawConverter,class Float2IntRounder>
- struct rounding_converter : public std::unary_function< BOOST_DEDUCED_TYPENAME Traits::argument_type
- ,BOOST_DEDUCED_TYPENAME Traits::result_type
- >
- ,public RangeChecker
+ struct rounding_converter : public RangeChecker
,public Float2IntRounder
,public RawConverter
{
typedef RangeChecker RangeCheckerBase ;
typedef Float2IntRounder Float2IntRounderBase ;
typedef RawConverter RawConverterBase ;
@@ -498,16 +492,13 @@
//
// Non-Rounding Converter : used for all other conversions.
//
template<class Traits,class RangeChecker,class RawConverter>
- struct non_rounding_converter : public std::unary_function< BOOST_DEDUCED_TYPENAME Traits::argument_type
- ,BOOST_DEDUCED_TYPENAME Traits::result_type
- >
- ,public RangeChecker
+ struct non_rounding_converter : public RangeChecker
,public RawConverter
{
typedef RangeChecker RangeCheckerBase ;
typedef RawConverter RawConverterBase ;
typedef Traits traits ;
--- boost\poly_collection\detail\is_constructible.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\poly_collection\detail\is_constructible.hpp 2017-08-21 15:44:47.000000000 -0700
@@ -13,14 +13,16 @@
#pragma once
#endif
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
-#if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1900))
-/* https://connect.microsoft.com/VisualStudio/Feedback/Details/2118677 */
+#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, < 190023918 )
+/* https://connect.microsoft.com/VisualStudio/Feedback/Details/2118677
+ - fixed in VS2015U2 according to
+ https://blogs.msdn.microsoft.com/vcblog/2016/03/31/visual-c-2015-update-2-bug-fixes/ */
#include <boost/type_traits/is_constructible.hpp>
namespace boost{
namespace poly_collection{
--- boost\pool\object_pool.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\pool\object_pool.hpp 2017-08-21 15:45:08.000000000 -0700
@@ -18,13 +18,13 @@
#include <boost/pool/poolfwd.hpp>
// boost::pool
#include <boost/pool/pool.hpp>
// The following code will be put into Boost.Config in a later revision
-#if defined(BOOST_MSVC) || defined(__KCC)
+#if (defined(BOOST_MSVC) && BOOST_MSVC < 1900) || defined(__KCC)
# define BOOST_NO_TEMPLATE_CV_REF_OVERLOADS
#endif
// The following code might be put into some Boost.Config header in a later revision
#ifdef __BORLANDC__
# pragma option push -w-inl
--- boost\process\detail\posix\async_handler.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\posix\async_handler.hpp 2017-08-26 23:03:08.000000000 -0700
--- boost\process\detail\posix\async_in.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\posix\async_in.hpp 2017-08-26 23:03:08.000000000 -0700
--- boost\process\detail\posix\async_out.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\posix\async_out.hpp 2017-08-26 23:03:08.000000000 -0700
--- boost\process\detail\posix\basic_pipe.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\posix\basic_pipe.hpp 2017-08-26 23:03:08.000000000 -0700
@@ -26,13 +26,13 @@
class basic_pipe
{
int _source = -1;
int _sink = -1;
public:
explicit basic_pipe(int source, int sink) : _source(source), _sink(sink) {}
- explicit basic_pipe(int source, int sink, const std::string & name) : _source(source), _sink(sink) {}
+ explicit basic_pipe(int source, int sink, const std::string&) : _source(source), _sink(sink) {}
typedef CharT char_type ;
typedef Traits traits_type;
typedef typename Traits::int_type int_type ;
typedef typename Traits::pos_type pos_type ;
typedef typename Traits::off_type off_type ;
typedef int native_handle_type;
--- boost\process\detail\posix\child_handle.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\posix\child_handle.hpp 2017-08-26 23:03:08.000000000 -0700
@@ -41,13 +41,13 @@
int id() const
{
return pid;
}
bool in_group() const {return true;}
- bool in_group(std::error_code &ec) const noexcept {return true;}
+ bool in_group(std::error_code&) const noexcept {return true;}
typedef int process_handle_t;
process_handle_t process_handle() const { return pid; }
bool valid() const
{
--- boost\process\detail\posix\environment.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\posix\environment.hpp 2017-08-26 23:03:08.000000000 -0700
--- boost\process\detail\posix\executor.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\posix\executor.hpp 2017-08-26 23:03:08.000000000 -0700
@@ -177,13 +177,13 @@
template<typename Sequence>
class executor
{
template<typename HasHandler, typename UseVFork>
- void internal_error_handle(const std::error_code &ec, const char* msg, HasHandler, boost::mpl::true_, UseVFork) {}
+ void internal_error_handle(const std::error_code&, const char*, HasHandler, boost::mpl::true_, UseVFork) {}
int _pipe_sink = -1;
void write_error(const std::error_code & ec, const char * msg)
{
//I am the child
--- boost\process\detail\posix\file_descriptor.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\posix\file_descriptor.hpp 2017-08-26 23:03:08.000000000 -0700
--- boost\process\detail\posix\file_in.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\posix\file_in.hpp 2017-08-26 23:03:08.000000000 -0700
--- boost\process\detail\posix\file_out.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\posix\file_out.hpp 2017-08-26 23:03:08.000000000 -0700
--- boost\process\detail\posix\group_ref.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\posix\group_ref.hpp 2017-08-26 23:03:08.000000000 -0700
@@ -25,13 +25,13 @@
explicit group_ref(group_handle & g) :
grp(g)
{}
template <class Executor>
- void on_exec_setup(Executor& exec) const
+ void on_exec_setup(Executor&) const
{
if (grp.grp == -1)
::setpgid(0, 0);
else
::setpgid(0, grp.grp);
}
--- boost\process\detail\posix\handler.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\posix\handler.hpp 2017-08-26 23:03:08.000000000 -0700
--- boost\process\detail\posix\io_service_ref.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\posix\io_service_ref.hpp 2017-08-26 23:03:08.000000000 -0700
@@ -6,20 +6,21 @@
#ifndef BOOST_PROCESS_POSIX_IO_SERVICE_REF_HPP_
#define BOOST_PROCESS_POSIX_IO_SERVICE_REF_HPP_
#include <boost/process/detail/posix/handler.hpp>
#include <boost/process/detail/posix/async_handler.hpp>
#include <boost/asio/io_service.hpp>
-#include <boost/asio/signal_set.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/algorithm/transformation/filter_if.hpp>
#include <boost/fusion/algorithm/transformation/transform.hpp>
#include <boost/fusion/view/transform_view.hpp>
#include <boost/fusion/container/vector/convert.hpp>
+
+#include <boost/process/detail/posix/sigchld_service.hpp>
#include <functional>
#include <type_traits>
#include <memory>
#include <vector>
#include <sys/wait.h>
@@ -70,17 +71,15 @@
{
io_service_ref(boost::asio::io_service & ios) : ios(ios)
{
}
boost::asio::io_service &get() {return ios;};
-
- boost::asio::signal_set *signal_p = nullptr;
-
+
template <class Executor>
- void on_setup(Executor& exec)
+ void on_success(Executor& exec)
{
//must be on the heap so I can move it into the lambda.
auto asyncs = boost::fusion::filter_if<
is_async_handler<
typename std::remove_reference< boost::mpl::_ > ::type
>>(exec.seq);
@@ -90,66 +89,26 @@
return;
std::vector<std::function<void(int, const std::error_code & ec)>> funcs;
funcs.reserve(boost::fusion::size(asyncs));
boost::fusion::for_each(asyncs, async_handler_collector<Executor>(exec, funcs));
- wait_handler wh(std::move(funcs), ios, exec.exit_status);
-
- signal_p = wh.signal_.get();
- signal_p->async_wait(std::move(wh));
-
- }
-
- template <class Executor>
- void on_error(Executor & exec, const std::error_code & ec) const
- {
- if (signal_p != nullptr)
- {
- boost::system::error_code ec;
- signal_p->cancel(ec);
- }
- }
-
- struct wait_handler
- {
- std::shared_ptr<boost::asio::signal_set> signal_;
- std::vector<std::function<void(int, const std::error_code & ec)>> funcs;
- std::shared_ptr<std::atomic<int>> exit_status;
-
- wait_handler(const wait_handler & ) = default;
- wait_handler(wait_handler && ) = default;
- wait_handler(
- std::vector<std::function<void(int, const std::error_code & ec)>> && funcs,
- boost::asio::io_service & ios,
- const std::shared_ptr<std::atomic<int>> &exit_status)
- : signal_(new boost::asio::signal_set(ios, SIGCHLD)),
- funcs(std::move(funcs)),
- exit_status(exit_status)
- {
+ auto & es = exec.exit_status;
- }
- void operator()(const boost::system::error_code & ec_in, int /*signal*/)
- {
- if (ec_in.value() == boost::asio::error::operation_aborted)
- return;
-
-
- int status;
- ::wait(&status);
-
- std::error_code ec(ec_in.value(), std::system_category());
- int val = WEXITSTATUS(status);
- exit_status->store(status);
-
- for (auto & func : funcs)
- func(val, ec);
- }
+ auto wh = [funcs, es](int val, const std::error_code & ec)
+ {
+ es->store(val);
+ for (auto & func : funcs)
+ func(WEXITSTATUS(val), ec);
+ };
+
+ sigchld_service.async_wait(exec.pid, std::move(wh));
+ }
- };
private:
boost::asio::io_service &ios;
+ boost::process::detail::posix::sigchld_service &sigchld_service = boost::asio::use_service<boost::process::detail::posix::sigchld_service>(ios);
};
}}}}
#endif /* BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_ */
--- boost\process\detail\posix\null_in.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\posix\null_in.hpp 2017-08-26 23:03:08.000000000 -0700
--- boost\process\detail\posix\null_out.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\posix\null_out.hpp 2017-08-26 23:03:08.000000000 -0700
--- boost\process\detail\posix\on_exit.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\posix\on_exit.hpp 2017-08-26 23:03:08.000000000 -0700
@@ -20,16 +20,16 @@
on_exit_(const std::function<void(int, const std::error_code&)> & handler) : handler(handler)
{
}
template<typename Executor>
- std::function<void(int, const std::error_code&)> on_exit_handler(Executor & exec)
+ std::function<void(int, const std::error_code&)> on_exit_handler(Executor&)
{
return handler;
};
};
}}}}
#endif /* BOOST_PROCESS_POSIX_ON_EXIT_HPP_ */
--- boost\process\detail\posix\pipe_in.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\posix\pipe_in.hpp 2017-08-26 23:03:08.000000000 -0700
--- boost\process\detail\posix\pipe_out.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\posix\pipe_out.hpp 2017-08-26 23:03:08.000000000 -0700
---
+++ boost\process\detail\posix\sigchld_service.hpp 2017-08-26 23:03:08.000000000 -0700
@@ -0,0 +1,113 @@
+// Copyright (c) 2017 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_PROCESS_DETAIL_POSIX_SIGCHLD_SERVICE_HPP_
+#define BOOST_PROCESS_DETAIL_POSIX_SIGCHLD_SERVICE_HPP_
+
+#include <boost/asio/signal_set.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/optional.hpp>
+#include <signal.h>
+#include <functional>
+#include <sys/wait.h>
+
+namespace boost { namespace process { namespace detail { namespace posix {
+
+class sigchld_service : public boost::asio::detail::service_base<sigchld_service>
+{
+ boost::asio::io_service::strand _strand{get_io_service()};
+ boost::asio::signal_set _signal_set{get_io_service(), SIGCHLD};
+
+ std::vector<std::pair<::pid_t, std::function<void(int, std::error_code)>>> _receivers;
+ inline void _handle_signal(const boost::system::error_code & ec);
+public:
+ sigchld_service(boost::asio::io_service & io_service)
+ : boost::asio::detail::service_base<sigchld_service>(io_service)
+ {
+ }
+
+ template <typename SignalHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(SignalHandler,
+ void (int, std::error_code))
+ async_wait(::pid_t pid, SignalHandler && handler)
+ {
+ boost::asio::detail::async_result_init<
+ SignalHandler, void(boost::system::error_code)> init{std::forward<SignalHandler>(handler)};
+ auto & h = init.handler;
+ _strand.post(
+ [this, pid, h]
+ {
+ if (_receivers.empty())
+ _signal_set.async_wait(
+ [this](const boost::system::error_code & ec, int)
+ {
+ _strand.post([this,ec]{this->_handle_signal(ec);});
+ });
+ _receivers.emplace_back(pid, h);
+ });
+
+ return init.result.get();
+ }
+ void shutdown_service() override
+ {
+ _receivers.clear();
+ }
+
+ void cancel()
+ {
+ _signal_set.cancel();
+ }
+ void cancel(boost::system::error_code & ec)
+ {
+ _signal_set.cancel(ec);
+ }
+};
+
+
+void sigchld_service::_handle_signal(const boost::system::error_code & ec)
+{
+ std::error_code ec_{ec.value(), std::system_category()};
+
+ if (ec_)
+ {
+ for (auto & r : _receivers)
+ r.second(-1, ec_);
+ return;
+ }
+ int status;
+ int pid = ::waitpid(0, &status, WNOHANG);
+
+ auto itr = std::find_if(_receivers.cbegin(), _receivers.cend(),
+ [&pid](const std::pair<::pid_t, std::function<void(int, std::error_code)>> & p)
+ {
+ return p.first == pid;
+ });
+ if (itr != _receivers.cend())
+ {
+ _strand.get_io_service().wrap(itr->second)(status, ec_);
+ _receivers.erase(itr);
+ }
+ if (!_receivers.empty())
+ {
+ _signal_set.async_wait(
+ [this](const boost::system::error_code & ec, int)
+ {
+ _strand.post([ec]{});
+ this->_handle_signal(ec);
+ });
+ }
+}
+
+
+}
+}
+}
+}
+
+
+
+
+#endif
--- boost\process\detail\posix\wait_for_exit.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\posix\wait_for_exit.hpp 2017-08-26 23:03:09.000000000 -0700
@@ -12,39 +12,41 @@
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/posix/child_handle.hpp>
#include <system_error>
#include <sys/types.h>
#include <sys/wait.h>
-
+#include <unistd.h>
namespace boost { namespace process { namespace detail { namespace posix {
inline void wait(const child_handle &p, int & exit_code)
{
pid_t ret;
int status;
do
{
ret = ::waitpid(p.pid, &status, 0);
- } while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status)));
+ } while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status) && !WIFSIGNALED(status)));
if (ret == -1)
boost::process::detail::throw_last_error("waitpid(2) failed");
+ if (WIFSIGNALED(status))
+ throw process_error(std::error_code(), "process terminated due to receipt of a signal");
exit_code = status;
}
inline void wait(const child_handle &p, int & exit_code, std::error_code &ec) noexcept
{
pid_t ret;
int status;
do
{
ret = ::waitpid(p.pid, &status, 0);
}
- while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status)));
+ while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status) && !WIFSIGNALED(status)));
if (ret == -1)
ec = boost::process::detail::get_last_error();
else
{
ec.clear();
@@ -64,32 +66,33 @@
pid_t ret;
int status;
auto start = std::chrono::system_clock::now();
auto time_out = start + rel_time;
- bool time_out_occured = false;
+ bool timed_out;
do
{
- ret = ::waitpid(p.pid, &status, WUNTRACED | WNOHANG);
- if (std::chrono::system_clock::now() >= time_out)
+ ret = ::waitpid(p.pid, &status, WNOHANG);
+ if (ret == 0)
{
- time_out_occured = true;
- break;
+ timed_out = std::chrono::system_clock::now() >= time_out;
+ if (timed_out)
+ return false;
}
}
- while (((ret == -1) && errno == EINTR) ||
- ((ret != -1) && !WIFEXITED(status)));
+ while ((ret == 0) ||
+ ((ret == -1) && errno == EINTR) ||
+ ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status)));
-
if (ret == -1)
boost::process::detail::throw_last_error("waitpid(2) failed");
-
+
exit_code = status;
- return !time_out_occured;
+ return true;
}
template< class Rep, class Period >
inline bool wait_for(
const child_handle &p,
@@ -100,106 +103,122 @@
pid_t ret;
int status;
auto start = std::chrono::system_clock::now();
auto time_out = start + rel_time;
-
- bool time_out_occured = false;
+ bool timed_out;
+
do
{
- ret = ::waitpid(p.pid, &status, WUNTRACED | WNOHANG);
- if (std::chrono::system_clock::now() >= time_out)
+ ret = ::waitpid(p.pid, &status, WNOHANG);
+ if (ret == 0)
{
- time_out_occured = true;
- break;
+ timed_out = std::chrono::system_clock::now() >= time_out;
+ if (timed_out)
+ return false;
}
}
- while (((ret == -1) && errno == EINTR) ||
- ((ret != -1) && !WIFEXITED(status)));
+ while ((ret == 0) ||
+ (((ret == -1) && errno == EINTR) ||
+ ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status))));
+ if (timed_out && (ret == -1))
+ return false;
+
if (ret == -1)
ec = boost::process::detail::get_last_error();
else
{
ec.clear();
exit_code = status;
}
- return !time_out_occured;
+ return true;
}
-template< class Rep, class Period >
+template< class Clock, class Duration >
inline bool wait_until(
const child_handle &p,
int & exit_code,
- const std::chrono::duration<Rep, Period>& time_out)
+ const std::chrono::time_point<Clock, Duration>& time_out)
{
pid_t ret;
int status;
- bool time_out_occured = false;
+ bool timed_out;
do
{
- ret = ::waitpid(p.pid, &status, WUNTRACED | WNOHANG);
- if (std::chrono::system_clock::now() >= time_out)
+ ret = ::waitpid(p.pid, &status, WNOHANG);
+ if (ret == 0)
{
- time_out_occured = true;
- break;
+ timed_out = std::chrono::system_clock::now() >= time_out;
+ if (timed_out)
+ return false;
}
- }
- while (((ret == -1) && errno == EINTR) ||
- ((ret != -1) && !WIFEXITED(status)));
+ }
+ while ((ret == 0) ||
+ (((ret == -1) && errno == EINTR) ||
+ ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status))));
+ if (timed_out && !WIFEXITED(status))
+ return false;
+
if (ret == -1)
boost::process::detail::throw_last_error("waitpid(2) failed");
-
exit_code = status;
- return !time_out_occured;
+ return true;
}
-template< class Rep, class Period >
+template< class Clock, class Duration >
inline bool wait_until(
const child_handle &p,
int & exit_code,
- const std::chrono::duration<Rep, Period>& time_out,
+ const std::chrono::time_point<Clock, Duration>& time_out,
std::error_code & ec) noexcept
{
pid_t ret;
int status;
- bool time_out_occured = false;
+ bool timed_out;
+
do
{
- ret = ::waitpid(p.pid, &status, WUNTRACED | WNOHANG);
- if (std::chrono::system_clock::now() >= time_out)
+ ret = ::waitpid(p.pid, &status, WNOHANG);
+ if (ret == 0)
{
- time_out_occured = true;
- break;
+ timed_out = std::chrono::system_clock::now() >= time_out;
+ if (timed_out)
+ return false;
}
}
- while (((ret == -1) && errno == EINTR) ||
- ((ret != -1) && !WIFEXITED(status)));
+ while ((ret == 0) ||
+ (((ret == -1) && errno == EINTR) ||
+ ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status))));
+
+ if (timed_out && !WIFEXITED(status))
+ return false;
+
if (ret == -1)
ec = boost::process::detail::get_last_error();
else
{
ec.clear();
exit_code = status;
}
- return !time_out_occured;
+ return true;
}
}}}}
#endif
--- boost\process\detail\posix\wait_group.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\posix\wait_group.hpp 2017-08-26 23:03:09.000000000 -0700
@@ -22,30 +22,34 @@
{
pid_t ret;
int status;
do
{
ret = ::waitpid(-p.grp, &status, 0);
- } while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status)));
+ } while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status) && !WIFSIGNALED(status)));
if (ret == -1)
boost::process::detail::throw_last_error("waitpid(2) failed");
+ if (WIFSIGNALED(status))
+ throw process_error(std::error_code(), "process group terminated due to receipt of a signal");
}
inline void wait(const group_handle &p, std::error_code &ec) noexcept
{
pid_t ret;
int status;
do
{
ret = ::waitpid(-p.grp, &status, 0);
}
- while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status)));
+ while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status) && !WIFSIGNALED(status)));
if (ret == -1)
ec = boost::process::detail::get_last_error();
+ else if (WIFSIGNALED(status))
+ ec = std::make_error_code(std::errc::no_such_process);
else
ec.clear();
}
template< class Rep, class Period >
@@ -67,19 +71,20 @@
if (std::chrono::system_clock::now() >= time_out)
{
time_out_occured = true;
break;
}
}
- while (((ret == -1) && errno == EINTR) ||
- ((ret != -1) && !WIFEXITED(status)));
+ while (((ret == -1) && errno == EINTR) ||
+ ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status)));
if (ret == -1)
boost::process::detail::throw_last_error("waitpid(2) failed");
-
+ if (WIFSIGNALED(status))
+ throw process_error(std::error_code(), "process group terminated due to receipt of a signal");
return !time_out_occured;
}
template< class Rep, class Period >
@@ -102,18 +107,20 @@
if (std::chrono::system_clock::now() >= time_out)
{
time_out_occured = true;
break;
}
}
- while (((ret == -1) && errno == EINTR) ||
- ((ret != -1) && !WIFEXITED(status)));
+ while (((ret == -1) && errno == EINTR) ||
+ ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status)));
if (ret == -1)
ec = boost::process::detail::get_last_error();
+ else if (WIFSIGNALED(status))
+ ec = std::make_error_code(std::errc::no_such_process);
else
ec.clear();
return !time_out_occured;
}
@@ -125,30 +132,30 @@
const std::chrono::duration<Rep, Period>& time_out)
{
pid_t ret;
int status;
- auto start = std::chrono::system_clock::now();
-
bool time_out_occured = false;
do
{
ret = ::waitpid(-p.grp, &status, WUNTRACED | WNOHANG);
if (std::chrono::system_clock::now() >= time_out)
{
time_out_occured = true;
break;
}
}
- while (((ret == -1) && errno == EINTR) ||
- ((ret != -1) && !WIFEXITED(status)));
+ while (((ret == -1) && errno == EINTR) ||
+ ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status)));
if (ret == -1)
boost::process::detail::throw_last_error("waitpid(2) failed");
+ if (WIFSIGNALED(status))
+ throw process_error(std::error_code(), "process group terminated due to receipt of a signal");
return !time_out_occured;
}
@@ -171,21 +178,23 @@
if (std::chrono::system_clock::now() >= time_out)
{
time_out_occured = true;
break;
}
}
- while (((ret == -1) && errno == EINTR) ||
- ((ret != -1) && !WIFEXITED(status)));
+ while (((ret == -1) && errno == EINTR) ||
+ ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status)));
if (ret == -1)
ec = boost::process::detail::get_last_error();
+ else if (WIFSIGNALED(status))
+ ec = std::make_error_code(std::errc::no_such_process);
else
ec.clear();
return !time_out_occured;
}
}}}}
#endif
--- boost\process\detail\traits\async.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\traits\async.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\traits\cmd_or_exe.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\traits\cmd_or_exe.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\traits\decl.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\traits\decl.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\traits\env.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\traits\env.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\traits\error.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\traits\error.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\windows\async_handler.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\async_handler.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\windows\async_in.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\async_in.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\windows\async_out.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\async_out.hpp 2017-08-26 23:03:09.000000000 -0700
@@ -135,14 +135,17 @@
promise->set_exception(std::make_exception_ptr(process_error(e)));
}
else
{
std::istream is (buffer.get());
Type arg;
- arg.resize(buffer->size());
- is.read(&*arg.begin(), buffer->size());
+ if (buffer->size() > 0)
+ {
+ arg.resize(buffer->size());
+ is.read(&*arg.begin(), buffer->size());
+ }
promise->set_value(std::move(arg));
}
});
--- boost\process\detail\windows\async_pipe.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\async_pipe.hpp 2017-08-26 23:03:09.000000000 -0700
@@ -75,16 +75,14 @@
inline async_pipe& operator=(const async_pipe& rhs);
inline async_pipe& operator=(async_pipe&& rhs);
~async_pipe()
{
- if (_sink .native() != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
- ::boost::detail::winapi::CloseHandle(_sink.native());
- if (_source.native() != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
- ::boost::detail::winapi::CloseHandle(_source.native());
+ boost::system::error_code ec;
+ close(ec);
}
template<class CharT, class Traits = std::char_traits<CharT>>
inline explicit operator basic_pipe<CharT, Traits>() const;
void cancel()
--- boost\process\detail\windows\basic_cmd.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\basic_cmd.hpp 2017-08-26 23:03:09.000000000 -0700
@@ -64,17 +64,31 @@
return st;
}
inline std::wstring build_args(const std::wstring & exe, std::vector<std::wstring> && data)
{
std::wstring st = exe;
+
+ //put in quotes if it has spaces
+ {
+ boost::replace_all(st, L"\"", L"\\\"");
+
+ auto it = std::find(st.begin(), st.end(), L' ');
+
+ if (it != st.end())//contains spaces.
+ {
+ st.insert(st.begin(), L'"');
+ st += L'"';
+ }
+ }
+
for (auto & arg : data)
{
boost::replace_all(arg, L"\"", L"\\\"");
- auto it = std::find(arg.begin(), arg.end(), ' ');//contains space?
+ auto it = std::find(arg.begin(), arg.end(), L' ');//contains space?
if (it != arg.end())//ok, contains spaces.
{
//the first one is put directly onto the output,
//because then I don't have to copy the whole string
arg.insert(arg.begin(), L'"');
arg += L'"'; //thats the post one.
--- boost\process\detail\windows\cmd.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\cmd.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\windows\environment.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\environment.hpp 2017-08-26 23:03:09.000000000 -0700
@@ -297,16 +297,14 @@
if (itr == _data.end())
return;//nothing to return if it's empty anyway...
auto end = itr;
- while (*end != '\0')
- end++;
+ while (*++end != '\0');
- end ++; //to point behind the last null-char
_data.erase(itr, end);//and remove it
reload();
}
--- boost\process\detail\windows\file_descriptor.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\file_descriptor.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\windows\file_in.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\file_in.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\windows\file_out.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\file_out.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\windows\handler.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\handler.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\windows\io_service_ref.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\io_service_ref.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\windows\locale.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\locale.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\windows\null_in.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\null_in.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\windows\null_out.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\null_out.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\windows\on_exit.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\on_exit.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\windows\pipe_in.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\pipe_in.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\windows\pipe_out.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\pipe_out.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\windows\search_path.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\search_path.hpp 2017-08-26 23:03:09.000000000 -0700
@@ -17,38 +17,63 @@
#include <string>
#include <stdexcept>
#include <array>
#include <atomic>
#include <cstdlib>
#include <boost/detail/winapi/shell.hpp>
-
+#include <boost/process/environment.hpp>
-
namespace boost { namespace process { namespace detail { namespace windows {
inline boost::filesystem::path search_path(
const boost::filesystem::path &filename,
const std::vector<boost::filesystem::path> &path)
{
+ const ::boost::process::wnative_environment ne{};
+ typedef typename ::boost::process::wnative_environment::const_entry_type value_type;
+ const auto id = L"PATHEXT";
+
+ auto itr = std::find_if(ne.cbegin(), ne.cend(),
+ [&](const value_type & e)
+ {return id == ::boost::to_upper_copy(e.get_name(), ::boost::process::detail::process_locale());});
+
+ auto extensions_in = itr->to_vector();
+
+ std::vector<std::wstring> extensions((extensions_in.size() * 2) + 1);
+
+ auto it_ex = extensions.begin();
+ it_ex++;
+ it_ex = std::transform(extensions_in.begin(), extensions_in.end(), it_ex,
+ [](const std::wstring & ws){return boost::to_lower_copy(ws, ::boost::process::detail::process_locale());});
+
+ std::transform(extensions_in.begin(), extensions_in.end(), it_ex,
+ [](const std::wstring & ws){return boost::to_upper_copy(ws, ::boost::process::detail::process_locale());});
+
+
+ std::copy(std::make_move_iterator(extensions_in.begin()), std::make_move_iterator(extensions_in.end()), extensions.begin() + 1);
+
+
+ for (auto & ext : extensions)
+ boost::to_lower(ext);
+
for (const boost::filesystem::path & pp : path)
{
- auto full = pp / filename;
- std::array<std::string, 4> extensions {{ "", ".exe", ".com", ".bat" }};
+ auto p = pp / filename;
for (boost::filesystem::path ext : extensions)
{
- auto p = full;
- p += ext;
+ boost::filesystem::path pp = p;
+ pp += ext;
boost::system::error_code ec;
- bool file = boost::filesystem::is_regular_file(p, ec);
+ bool file = boost::filesystem::is_regular_file(pp, ec);
if (!ec && file &&
- ::boost::detail::winapi::sh_get_file_info(p.string().c_str(), 0, 0, 0, ::boost::detail::winapi::SHGFI_EXETYPE_))
+ ::boost::detail::winapi::sh_get_file_info(pp.native().c_str(), 0, 0, 0, ::boost::detail::winapi::SHGFI_EXETYPE_))
{
- return p;
+ return pp;
}
}
}
return "";
}
}}}}
#endif
--- boost\process\detail\windows\show_window.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\show_window.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\windows\start_dir.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\start_dir.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\detail\windows\wait_for_exit.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\windows\wait_for_exit.hpp 2017-08-26 23:03:09.000000000 -0700
@@ -162,32 +162,36 @@
std::error_code &ec) noexcept
{
std::chrono::milliseconds ms =
std::chrono::duration_cast<std::chrono::milliseconds>(
timeout_time - std::chrono::system_clock::now());
- ::boost::detail::winapi::DWORD_ _exit_code = 1;
-
- if (::boost::detail::winapi::WaitForSingleObject(p.process_handle(),
- static_cast<::boost::detail::winapi::DWORD_>(ms.count()))
- == ::boost::detail::winapi::wait_failed)
+ ::boost::detail::winapi::DWORD_ wait_code;
+ wait_code = ::boost::detail::winapi::WaitForSingleObject(p.process_handle(),
+ static_cast<::boost::detail::winapi::DWORD_>(ms.count()));
+
+ if (wait_code == ::boost::detail::winapi::wait_failed)
ec = std::error_code(
::boost::detail::winapi::GetLastError(),
std::system_category());
- else if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
+ else if (wait_code == ::boost::detail::winapi::wait_timeout)
+ return false;
+
+ ::boost::detail::winapi::DWORD_ _exit_code;
+ if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
ec = std::error_code(
::boost::detail::winapi::GetLastError(),
std::system_category());
else
ec.clear();
- exit_code = static_cast<int>(exit_code);
+ exit_code = static_cast<int>(_exit_code);
::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
return true;
;
}
}}}}
#endif
--- boost\process\detail\basic_cmd.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\basic_cmd.hpp 2017-08-26 23:03:08.000000000 -0700
--- boost\process\detail\config.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\config.hpp 2017-08-26 23:03:08.000000000 -0700
@@ -69,12 +69,17 @@
inline void throw_last_error(const std::string & msg)
{
throw process_error(get_last_error(), msg);
}
+inline void throw_last_error(const char * msg)
+{
+ throw process_error(get_last_error(), msg);
+}
+
inline void throw_last_error()
{
throw process_error(get_last_error());
}
--- boost\process\detail\handler.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\handler.hpp 2017-08-26 23:03:08.000000000 -0700
--- boost\process\detail\traits.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\detail\traits.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\async.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\async.hpp 2017-08-26 23:03:08.000000000 -0700
@@ -114,17 +114,17 @@
std::future<int> exit_code;
chlid c2("ls", on_exit=exit_code);
\endcode
\note The handler is not invoked when the launch fails.
-\warning When used \ref ignore_error it might gte invoked on error.
-
+\warning When used \ref ignore_error it might get invoked on error.
+\warning All `on_exit` use one signal(SIGCHLD) on posix, which is only guaranteed to work when all use the same `io_service`.
*/
constexpr static ::boost::process::detail::on_exit_ on_exit{};
#endif
}}
#endif /* INCLUDE_BOOST_PROCESS_DETAIL_ASYNC_HPP_ */
--- boost\process\child.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\child.hpp 2017-08-26 23:03:08.000000000 -0700
@@ -32,12 +32,15 @@
template<typename ...Args>
child::child(Args&&...args)
: child(::boost::process::detail::execute_impl(std::forward<Args>(args)...)) {}
+///Typedef for the type of an pid_t
+typedef ::boost::process::detail::api::pid_t pid_t;
+
#if defined(BOOST_PROCESS_DOXYGEN)
/** The main class to hold a child process. It is simliar to [std::thread](http://en.cppreference.com/w/cpp/thread/thread),
* in that it has a join and detach function.
*
* @attention The destructor will call terminate on the process if not joined or detached without any warning.
*
--- boost\process\cmd.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\cmd.hpp 2017-08-26 23:03:08.000000000 -0700
--- boost\process\env.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\env.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\exe.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\exe.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\io.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\io.hpp 2017-08-26 23:03:09.000000000 -0700
@@ -95,13 +95,13 @@
std::future<std::string> output;
system("ls", std_out > output, ios);
auto res = fut.get();
\endcode
-\note `boost/process/asnyc.hpp` must also be included for this to work.
+\note `boost/process/async.hpp` must also be included for this to work.
\par Closing
Stream can be closed, so nothing can be read or written.
\code{.cpp}
--- boost\process\locale.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\locale.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\start_dir.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\start_dir.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\process\windows.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\process\windows.hpp 2017-08-26 23:03:09.000000000 -0700
--- boost\proto\detail\decltype.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\proto\detail\decltype.hpp 2017-08-21 15:45:35.000000000 -0700
@@ -40,13 +40,13 @@
# pragma warning(push)
# pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined
#endif
// We're STILL using Boost.Typeof on MSVC even for msvc-11.0 because of this bug:
// https://connect.microsoft.com/VisualStudio/feedback/details/765392/decltype-of-a-pointer-to-member-operator-gets-ref-qualification-wrong
-#if !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
+#if !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1900 )
# define BOOST_PROTO_DECLTYPE_(EXPR, TYPE) typedef decltype((EXPR)) TYPE;
#else
# define BOOST_PROTO_DECLTYPE_NESTED_TYPEDEF_TPL_(NESTED, EXPR) \
BOOST_TYPEOF_NESTED_TYPEDEF_TPL(BOOST_PP_CAT(nested_and_hidden_, NESTED), EXPR) \
static int const BOOST_PP_CAT(sz, NESTED) = sizeof(boost::proto::detail::check_reference(EXPR));\
struct NESTED \
--- boost\proto\expr.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\proto\expr.hpp 2017-08-21 15:46:02.000000000 -0700
@@ -89,13 +89,13 @@
}
return that;
}
// Work-around for:
// https://connect.microsoft.com/VisualStudio/feedback/details/765449/codegen-stack-corruption-using-runtime-checks-when-aggregate-initializing-struct
- #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
+ #if BOOST_WORKAROUND(BOOST_MSVC, < 1800 )
template<typename T, typename Expr, typename C, typename U>
BOOST_FORCEINLINE
Expr make_terminal(T &t, Expr *, proto::term<U C::*> *)
{
Expr that;
that.child0 = t;
--- boost\proto\generate.hpp 2017-08-19 09:49:45.000000000 -0700
+++ boost\proto\generate.hpp 2017-08-21 15:46:20.000000000 -0700
@@ -227,13 +227,13 @@
Extends<Expr> that = {e};
return that;
}
// Work-around for:
// https://connect.microsoft.com/VisualStudio/feedback/details/765449/codegen-stack-corruption-using-runtime-checks-when-aggregate-initializing-struct
- #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
+ #if BOOST_WORKAROUND(BOOST_MSVC, < 1800 )
template<typename Class, typename Member>
BOOST_FORCEINLINE
Extends<expr<tag::terminal, proto::term<Member Class::*> > > operator ()(expr<tag::terminal, proto::term<Member Class::*> > const &e) const
{
Extends<expr<tag::terminal, proto::term<Member Class::*> > > that;
proto::value(that.proto_expr_) = proto::value(e);
---
+++ boost\range\adaptor\moved.hpp 2015-07-20 08:27:56.000000000 -0700
@@ -0,0 +1,94 @@
+// Boost.Range library
+//
+// Copyright Thorsten Ottosen, Neil Groves 2006 - 2008.
+// Copyright Adam Wulkiewicz 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_RANGE_ADAPTOR_MOVED_HPP
+#define BOOST_RANGE_ADAPTOR_MOVED_HPP
+
+#include <boost/range/adaptor/argument_fwd.hpp>
+#include <boost/range/iterator_range.hpp>
+
+#include <boost/move/iterator.hpp>
+
+namespace boost {
+
+namespace range_detail {
+
+template< class R >
+struct moved_range :
+ boost::iterator_range<
+ boost::move_iterator<
+ BOOST_DEDUCED_TYPENAME range_iterator<R>::type
+ >
+ >
+{
+private:
+ typedef boost::iterator_range<
+ boost::move_iterator<
+ BOOST_DEDUCED_TYPENAME range_iterator<R>::type
+ >
+ > base;
+public:
+ moved_range( R & r )
+ : base( boost::make_move_iterator(boost::begin(r)),
+ boost::make_move_iterator(boost::end(r)) )
+ { }
+};
+
+struct move_forwarder {};
+
+template< class InputRange >
+inline moved_range<InputRange>
+operator|( InputRange & r, move_forwarder )
+{
+ return moved_range<InputRange>( r );
+}
+
+template< class InputRange >
+inline moved_range<InputRange const>
+operator|( InputRange const& r, move_forwarder )
+{
+ return moved_range<InputRange const>( r );
+}
+
+} // namespace range_detail
+
+// Unusual use of 'using' is intended to bring filter_range into the boost namespace
+// while leaving the mechanics of the '|' operator in range_detail and maintain
+// argument dependent lookup.
+// filter_range logically needs to be in the boost namespace to allow user of
+// the library to define the return type for filter()
+using range_detail::moved_range;
+
+namespace adaptors {
+
+namespace
+{
+ const range_detail::move_forwarder moved =
+ range_detail::move_forwarder();
+}
+
+template<class InputRange>
+inline moved_range<InputRange>
+move(InputRange & rng)
+{
+ return moved_range<InputRange>(rng);
+}
+
+template<class InputRange>
+inline moved_range<InputRange const>
+move(InputRange const& rng)
+{
+ return moved_range<InputRange const>(rng);
+}
+
+} // namespace adaptors
+
+} // namespace boost
+
+#endif // BOOST_RANGE_ADAPTOR_MOVED_HPP
---
+++ boost\range\algorithm\move.hpp 2015-07-20 08:28:35.000000000 -0700
@@ -0,0 +1,57 @@
+// Boost.Range library
+//
+// Copyright Neil Groves 2009.
+// Copyright Adam Wulkiewicz 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_RANGE_ALGORITHM_MOVE_HPP
+#define BOOST_RANGE_ALGORITHM_MOVE_HPP
+
+#include <boost/concept_check.hpp>
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/concepts.hpp>
+//#include <boost/range/iterator_range.hpp>
+
+#include <boost/move/algorithm.hpp>
+
+namespace boost {
+
+namespace range {
+
+/// \brief template function move
+///
+/// range-based version of the move std algorithm
+///
+/// \pre SinglePassRange is a model of the SinglePassRangeConcept
+/// \pre OutputIterator is a model of the OutputIteratorConcept
+template< class SinglePassRange, class OutputIterator >
+inline OutputIterator move(SinglePassRange & rng, OutputIterator out)
+{
+ BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<SinglePassRange> ));
+ return ::boost::move(::boost::begin(rng), ::boost::end(rng), out);
+}
+
+/// \brief template function move
+///
+/// range-based version of the move std algorithm
+///
+/// \pre SinglePassRange is a model of the SinglePassRangeConcept
+/// \pre OutputIterator is a model of the OutputIteratorConcept
+template< class SinglePassRange, class OutputIterator >
+inline OutputIterator move(SinglePassRange const& rng, OutputIterator out)
+{
+ BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<SinglePassRange const> ));
+ return ::boost::move(::boost::begin(rng), ::boost::end(rng), out);
+}
+
+} // namespace range
+
+using range::move;
+
+} // namespace boost
+
+#endif // BOOST_RANGE_ALGORITHM_MOVE_HPP
---
+++ boost\range\algorithm\move_backward.hpp 2015-07-20 08:28:30.000000000 -0700
@@ -0,0 +1,62 @@
+// Boost.Range library
+//
+// Copyright Neil Groves 2009.
+// Copyright Adam Wulkiewicz 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_RANGE_ALGORITHM_MOVE_BACKWARD_HPP
+#define BOOST_RANGE_ALGORITHM_MOVE_BACKWARD_HPP
+
+#include <boost/concept_check.hpp>
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/concepts.hpp>
+
+#include <boost/move/algorithm.hpp>
+
+namespace boost {
+
+namespace range {
+
+/// \brief template function copy_backward
+///
+/// range-based version of the move_backwards std algorithm
+///
+/// \pre BidirectionalRange is a model of the BidirectionalRangeConcept
+/// \pre BidirectionalTraversalWriteableIterator is a model of the BidirectionalIteratorConcept
+/// \pre BidirectionalTraversalWriteableIterator is a model of the WriteableIteratorConcept
+template< class BidirectionalRange, class BidirectionalTraversalWriteableIterator >
+inline BidirectionalTraversalWriteableIterator
+move_backward(BidirectionalRange & rng,
+ BidirectionalTraversalWriteableIterator out)
+{
+ BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept<BidirectionalRange> ));
+ return ::boost::move_backward(::boost::begin(rng), ::boost::end(rng), out);
+}
+
+/// \brief template function copy_backward
+///
+/// range-based version of the move_backwards std algorithm
+///
+/// \pre BidirectionalRange is a model of the BidirectionalRangeConcept
+/// \pre BidirectionalTraversalWriteableIterator is a model of the BidirectionalIteratorConcept
+/// \pre BidirectionalTraversalWriteableIterator is a model of the WriteableIteratorConcept
+template< class BidirectionalRange, class BidirectionalTraversalWriteableIterator >
+inline BidirectionalTraversalWriteableIterator
+move_backward(BidirectionalRange const& rng,
+ BidirectionalTraversalWriteableIterator out)
+{
+ BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept<BidirectionalRange const> ));
+ return ::boost::move_backward(::boost::begin(rng), ::boost::end(rng), out);
+}
+
+} // namespace range
+
+using range::move_backward;
+
+} // namespace boost
+
+#endif // BOOST_RANGE_ALGORITHM_MOVE_BACKWARD_HPP
--- boost\range\algorithm_ext\insert.hpp 2017-08-19 09:49:48.000000000 -0700
+++ boost\range\algorithm_ext\insert.hpp 2017-08-21 15:47:30.000000000 -0700
@@ -36,13 +36,14 @@
template< class Container, class Range >
inline Container& insert( Container& on, const Range& from )
{
BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept<Container> ));
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<Range> ));
on.insert(boost::begin(from), boost::end(from));
+ return on;
}
} // namespace range
using range::insert;
} // namespace boost
#endif // include guard
--- boost\range\adaptors.hpp 2017-08-19 09:49:48.000000000 -0700
+++ boost\range\adaptors.hpp 2017-08-21 15:47:48.000000000 -0700
@@ -16,16 +16,18 @@
#include <boost/range/adaptor/copied.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/adaptor/formatted.hpp>
#include <boost/range/adaptor/indexed.hpp>
#include <boost/range/adaptor/indirected.hpp>
#include <boost/range/adaptor/map.hpp>
+#include <boost/range/adaptor/moved.hpp>
#include <boost/range/adaptor/replaced.hpp>
#include <boost/range/adaptor/replaced_if.hpp>
#include <boost/range/adaptor/reversed.hpp>
#include <boost/range/adaptor/sliced.hpp>
#include <boost/range/adaptor/strided.hpp>
#include <boost/range/adaptor/tokenized.hpp>
#include <boost/range/adaptor/transformed.hpp>
+#include <boost/range/adaptor/type_erased.hpp>
#include <boost/range/adaptor/uniqued.hpp>
#endif
--- boost\range\algorithm.hpp 2017-08-19 09:49:48.000000000 -0700
+++ boost\range\algorithm.hpp 2017-08-21 15:48:01.000000000 -0700
@@ -54,12 +54,14 @@
#include <boost/range/algorithm/copy_backward.hpp>
#include <boost/range/algorithm/fill.hpp>
#include <boost/range/algorithm/fill_n.hpp>
#include <boost/range/algorithm/generate.hpp>
#include <boost/range/algorithm/inplace_merge.hpp>
#include <boost/range/algorithm/merge.hpp>
+#include <boost/range/algorithm/move.hpp>
+#include <boost/range/algorithm/move_backward.hpp>
#include <boost/range/algorithm/nth_element.hpp>
#include <boost/range/algorithm/partial_sort.hpp>
#include <boost/range/algorithm/partial_sort_copy.hpp>
#include <boost/range/algorithm/partition.hpp>
#include <boost/range/algorithm/random_shuffle.hpp>
#include <boost/range/algorithm/remove.hpp>
@@ -74,12 +76,13 @@
#include <boost/range/algorithm/reverse_copy.hpp>
#include <boost/range/algorithm/rotate.hpp>
#include <boost/range/algorithm/rotate_copy.hpp>
#include <boost/range/algorithm/sort.hpp>
#include <boost/range/algorithm/stable_partition.hpp>
#include <boost/range/algorithm/stable_sort.hpp>
+#include <boost/range/algorithm/swap_ranges.hpp>
#include <boost/range/algorithm/transform.hpp>
#include <boost/range/algorithm/unique.hpp>
#include <boost/range/algorithm/unique_copy.hpp>
// Binary search
#include <boost/range/algorithm/binary_search.hpp>
--- boost\smart_ptr\detail\local_counted_base.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\smart_ptr\detail\local_counted_base.hpp 2017-08-28 18:55:50.000000000 -0700
@@ -57,18 +57,20 @@
virtual void local_cb_destroy() BOOST_SP_NOEXCEPT = 0;
virtual boost::detail::shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT = 0;
void add_ref() BOOST_SP_NOEXCEPT
{
+#if !defined(__NVCC__)
#if defined( __has_builtin )
# if __has_builtin( __builtin_assume )
__builtin_assume( local_use_count_ >= 1 );
-# endif
+# endif
+#endif
#endif
local_use_count_ = static_cast<count_type>( local_use_count_ + 1 );
}
void release() BOOST_SP_NOEXCEPT
--- boost\spirit\home\x3\binary\binary.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\spirit\home\x3\binary\binary.hpp 2017-08-24 15:07:24.000000000 -0700
@@ -34,13 +34,13 @@
binary_lit_parser(V n_)
: n(n_) {}
template <typename Iterator, typename Context, typename Attribute>
bool parse(Iterator& first, Iterator const& last
- , Context& context, unused_type, Attribute& attr_param) const
+ , Context const& context, unused_type, Attribute& attr_param) const
{
x3::skip_over(first, last, context);
auto bytes = reinterpret_cast<const unsigned char*>(&n);
Iterator it = first;
@@ -66,13 +66,13 @@
typedef T attribute_type;
static bool const has_attribute =
!is_same<unused_type, attribute_type>::value;
template <typename Iterator, typename Context, typename Attribute>
bool parse(Iterator& first, Iterator const& last
- , Context& context, unused_type, Attribute& attr_param) const
+ , Context const& context, unused_type, Attribute& attr_param) const
{
x3::skip_over(first, last, context);
attribute_type attr_;
auto bytes = reinterpret_cast<unsigned char*>(&attr_);
--- boost\spirit\home\x3\char\char_set.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\spirit\home\x3\char\char_set.hpp 2017-08-24 15:07:47.000000000 -0700
@@ -34,13 +34,13 @@
char_range(char_type from_, char_type to_)
: from(from_), to(to_) {}
template <typename Char, typename Context>
- bool test(Char ch_, Context& context) const
+ bool test(Char ch_, Context const& context) const
{
char_type ch = char_type(ch_); // optimize for token based parsing
return ((sizeof(Char) <= sizeof(char_type)) || encoding::ischar(ch_))
&& (get_case_compare<encoding>(context)(ch, from) >= 0 )
&& (get_case_compare<encoding>(context)(ch , to) <= 0 );
--- boost\spirit\home\x3\directive\confix.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\spirit\home\x3\directive\confix.hpp 2017-08-24 15:08:10.000000000 -0700
@@ -32,13 +32,13 @@
}
template<typename Iterator, typename Context
, typename RContext, typename Attribute>
bool parse(
Iterator& first, Iterator const& last
- , Context& context, RContext& rcontext, Attribute& attr) const
+ , Context const& context, RContext& rcontext, Attribute& attr) const
{
Iterator save = first;
if (!(prefix.parse(first, last, context, rcontext, unused) &&
this->subject.parse(first, last, context, rcontext, attr) &&
postfix.parse(first, last, context, rcontext, unused)))
--- boost\spirit\home\x3\directive\with.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\spirit\home\x3\directive\with.hpp 2017-08-24 15:08:50.000000000 -0700
@@ -18,24 +18,24 @@
template <typename Subject, typename Derived, typename T>
struct with_value_holder
: unary_parser<Subject, Derived>
{
typedef unary_parser<Subject, Derived> base_type;
mutable T val;
- with_value_holder(Subject const& subject, T const& val)
+ with_value_holder(Subject const& subject, T&& val)
: base_type(subject)
- , val(val) {}
+ , val(std::forward<T>(val)) {}
};
template <typename Subject, typename Derived, typename T>
- struct with_value_holder<Subject, Derived, T const>
+ struct with_value_holder<Subject, Derived, T&>
: unary_parser<Subject, Derived>
{
typedef unary_parser<Subject, Derived> base_type;
- T val;
- with_value_holder(Subject const& subject, T const& val)
+ T& val;
+ with_value_holder(Subject const& subject, T& val)
: base_type(subject)
, val(val) {}
};
template <typename Subject, typename ID, typename T>
struct with_directive
@@ -44,14 +44,14 @@
typedef with_value_holder<Subject, with_directive<Subject, ID, T>, T> base_type;
static bool const is_pass_through_unary = true;
static bool const handles_container = Subject::handles_container;
typedef Subject subject_type;
- with_directive(Subject const& subject, T const& val)
- : base_type(subject, val) {}
+ with_directive(Subject const& subject, T&& val)
+ : base_type(subject, std::forward<T>(val)) {}
template <typename Iterator, typename Context
, typename RContext, typename Attribute>
bool parse(Iterator& first, Iterator const& last
, Context const& context, RContext& rcontext, Attribute& attr) const
{
@@ -60,48 +60,27 @@
, make_context<ID>(this->val, context)
, rcontext
, attr);
}
};
- template <typename ID, typename T, typename NextContext = unused_type>
- struct with_context
- {
- typedef context<ID, T, NextContext> type;
- };
-
template <typename ID, typename T>
- struct with_context<ID, T, unused_type>
- {
- typedef context<ID, T> type;
- };
-
- template <typename ID, typename T>
struct with_gen
{
- T& val;
+ T&& val;
- with_gen(T& val)
- : val(val) {}
-
template <typename Subject>
with_directive<typename extension::as_parser<Subject>::value_type, ID, T>
operator[](Subject const& subject) const
{
- return { as_parser(subject), val };
+ return { as_parser(subject), std::forward<T>(val) };
}
};
template <typename ID, typename T>
- inline with_gen<ID, T> with(T& val)
+ inline with_gen<ID, T> with(T&& val)
{
- return { val };
+ return { std::forward<T>(val) };
}
-
- template <typename ID, typename T>
- inline with_gen<ID, T const> with(T const& val)
- {
- return { val };
- }
}}}
#endif
--- boost\spirit\home\x3\numeric\bool.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\spirit\home\x3\numeric\bool.hpp 2017-08-24 15:09:19.000000000 -0700
@@ -67,22 +67,22 @@
template <typename Value>
literal_bool_parser(Value const& n, BoolPolicies const& policies)
: policies(policies), n_(n) {}
template <typename Iterator, typename Context>
bool parse_main(Iterator& first, Iterator const& last
- , Context& context, T& attr) const
+ , Context const& context, T& attr) const
{
x3::skip_over(first, last, context);
return (n_ && policies.parse_true(first, last, attr, get_case_compare<encoding>(context)))
|| (!n_ && policies.parse_false(first, last, attr, get_case_compare<encoding>(context)));
}
template <typename Iterator, typename Context>
bool parse(Iterator& first, Iterator const& last
- , Context& context, unused_type, T& attr) const
+ , Context const& context, unused_type, T& attr) const
{
return parse_main(first, last, context, attr);
}
template <typename Iterator, typename Context, typename Attribute>
bool parse(Iterator& first, Iterator const& last
--- boost\spirit\home\x3\numeric\real.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\spirit\home\x3\numeric\real.hpp 2017-08-24 15:09:42.000000000 -0700
@@ -25,21 +25,21 @@
real_parser(RealPolicies const& policies)
: policies(policies) {}
template <typename Iterator, typename Context>
bool parse(Iterator& first, Iterator const& last
- , Context& context, unused_type, T& attr_) const
+ , Context const& context, unused_type, T& attr_) const
{
x3::skip_over(first, last, context);
return extract_real<T, RealPolicies>::parse(first, last, attr_, policies);
}
template <typename Iterator, typename Context, typename Attribute>
bool parse(Iterator& first, Iterator const& last
- , Context& context, unused_type, Attribute& attr_param) const
+ , Context const& context, unused_type, Attribute& attr_param) const
{
// this case is called when Attribute is not T
T attr_;
if (parse(first, last, context, unused, attr_))
{
traits::move_to(attr_, attr_param);
--- boost\spirit\home\x3\support\ast\variant.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\spirit\home\x3\support\ast\variant.hpp 2017-08-24 18:03:24.000000000 -0700
@@ -4,15 +4,16 @@
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/
#if !defined(BOOST_SPIRIT_X3_VARIANT_AUGUST_6_2011_0859AM)
#define BOOST_SPIRIT_X3_VARIANT_AUGUST_6_2011_0859AM
+#include <boost/config.hpp>
#include <boost/variant.hpp>
#include <boost/mpl/list.hpp>
-#include <boost/type_traits/is_base_of.hpp>
+#include <utility>
#include <type_traits>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace x3
{
template <typename T>
@@ -26,13 +27,13 @@
forward_ast() : p_(new T) {}
forward_ast(forward_ast const& operand)
: p_(new T(operand.get())) {}
- forward_ast(forward_ast&& operand)
+ forward_ast(forward_ast&& operand) BOOST_NOEXCEPT
: p_(operand.p_)
{
operand.p_ = 0;
}
forward_ast(T const& operand)
@@ -43,55 +44,55 @@
~forward_ast()
{
boost::checked_delete(p_);
}
- forward_ast& operator=(forward_ast const& rhs)
+ forward_ast& operator=(forward_ast const& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_copy_assignable<T>{})
{
assign(rhs.get());
return *this;
}
void swap(forward_ast& operand) BOOST_NOEXCEPT
{
T* temp = operand.p_;
operand.p_ = p_;
p_ = temp;
}
- forward_ast& operator=(T const& rhs)
+ forward_ast& operator=(T const& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_copy_assignable<T>{})
{
assign(rhs);
return *this;
}
forward_ast& operator=(forward_ast&& rhs) BOOST_NOEXCEPT
{
swap(rhs);
return *this;
}
- forward_ast& operator=(T&& rhs)
+ forward_ast& operator=(T&& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_move_assignable<T>{})
{
get() = std::move(rhs);
return *this;
}
- T& get() { return *get_pointer(); }
- const T& get() const { return *get_pointer(); }
+ T& get() BOOST_NOEXCEPT { return *get_pointer(); }
+ const T& get() const BOOST_NOEXCEPT { return *get_pointer(); }
- T* get_pointer() { return p_; }
- const T* get_pointer() const { return p_; }
+ T* get_pointer() BOOST_NOEXCEPT { return p_; }
+ const T* get_pointer() const BOOST_NOEXCEPT { return p_; }
- operator T const&() const { return this->get(); }
- operator T&() { return this->get(); }
+ operator T const&() const BOOST_NOEXCEPT { return this->get(); }
+ operator T&() BOOST_NOEXCEPT { return this->get(); }
private:
- void assign(const T& rhs)
+ void assign(const T& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_copy_assignable<T>{})
{
this->get() = rhs;
}
T* p_;
};
@@ -132,52 +133,52 @@
= std::enable_if_t<!(std::is_base_of<base_type
,std::remove_reference_t<T>
>
::value)
>;
- variant() : var() {}
+ variant() BOOST_NOEXCEPT_IF(std::is_nothrow_default_constructible<variant_type>{}) : var() {}
template <typename T, class = non_self_t<T>>
- explicit variant(T const& rhs)
+ explicit variant(T const& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_constructible<variant_type, T const&>{}))
: var(rhs) {}
template <typename T, class = non_self_t<T>>
- explicit variant(T&& rhs)
+ explicit variant(T&& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_constructible<variant_type, T&&>{}))
: var(std::forward<T>(rhs)) {}
- variant(variant const& rhs)
+ variant(variant const& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_copy_constructible<variant_type>{})
: var(rhs.var) {}
- variant(variant& rhs)
+ variant(variant& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_constructible<variant_type, variant_type&>{}))
: var(rhs.var) {}
- variant(variant&& rhs)
- : var(std::forward<variant_type>(rhs.var)) {}
+ variant(variant&& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_move_constructible<variant_type>{})
+ : var(std::move(rhs.var)) {}
- variant& operator=(variant const& rhs)
+ variant& operator=(variant const& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_copy_assignable<variant_type>{})
{
var = rhs.get();
return *this;
}
- variant& operator=(variant&& rhs)
+ variant& operator=(variant&& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_move_assignable<variant_type>{})
{
- var = std::forward<variant_type>(rhs.get());
+ var = std::move(rhs.get());
return *this;
}
template <typename T, class = non_self_t<T>>
- variant& operator=(T const& rhs)
+ variant& operator=(T const& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_assignable<variant_type, T const&>{}))
{
var = rhs;
return *this;
}
template <typename T, class = non_self_t<T>>
- variant& operator=(T&& rhs)
+ variant& operator=(T&& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_assignable<variant_type, T&&>{}))
{
var = std::forward<T>(rhs);
return *this;
}
template <typename F>
@@ -201,18 +202,18 @@
template <typename F>
typename F::result_type apply_visitor(F& v) const
{
return var.apply_visitor(v);
}
- variant_type const& get() const
+ variant_type const& get() const BOOST_NOEXCEPT
{
return var;
}
- variant_type& get()
+ variant_type& get() BOOST_NOEXCEPT
{
return var;
}
void swap(variant& rhs) BOOST_NOEXCEPT
{
@@ -224,34 +225,34 @@
}}}
namespace boost
{
template <typename T, typename ...Types>
inline T const&
- get(boost::spirit::x3::variant<Types...> const& x)
+ get(boost::spirit::x3::variant<Types...> const& x) BOOST_NOEXCEPT
{
return boost::get<T>(x.get());
}
template <typename T, typename ...Types>
inline T&
- get(boost::spirit::x3::variant<Types...>& x)
+ get(boost::spirit::x3::variant<Types...>& x) BOOST_NOEXCEPT
{
return boost::get<T>(x.get());
}
template <typename T, typename ...Types>
inline T const*
- get(boost::spirit::x3::variant<Types...> const* x)
+ get(boost::spirit::x3::variant<Types...> const* x) BOOST_NOEXCEPT
{
return boost::get<T>(&x->get());
}
template <typename T, typename ...Types>
inline T*
- get(boost::spirit::x3::variant<Types...>* x)
+ get(boost::spirit::x3::variant<Types...>* x) BOOST_NOEXCEPT
{
return boost::get<T>(&x->get());
}
}
#endif
--- boost\system\detail\error_code.ipp 2017-08-19 09:49:49.000000000 -0700
+++ boost\system\detail\error_code.ipp 2017-08-21 15:49:09.000000000 -0700
@@ -29,12 +29,18 @@
# endif
# ifndef ERROR_INCORRECT_SIZE
# define ERROR_INCORRECT_SIZE ERROR_BAD_ARGUMENTS
# endif
# endif
+# ifdef BOOST_ERROR_CODE_HEADER_ONLY
+# define BOOST_ERROR_CODE_HEADER_ONLY_INLINE inline
+# else
+# define BOOST_ERROR_CODE_HEADER_ONLY_INLINE
+# endif
+
//--------------------------------------------------------------------------------------//
namespace boost
{
namespace system
{
@@ -59,18 +65,18 @@
std::string message( int ev ) const;
error_condition default_error_condition( int ev ) const BOOST_SYSTEM_NOEXCEPT;
};
// generic_error_category implementation ---------------------------------//
- const char * generic_error_category::name() const BOOST_SYSTEM_NOEXCEPT
+ BOOST_ERROR_CODE_HEADER_ONLY_INLINE const char * generic_error_category::name() const BOOST_SYSTEM_NOEXCEPT
{
return "generic";
}
- std::string generic_error_category::message( int ev ) const
+ BOOST_ERROR_CODE_HEADER_ONLY_INLINE std::string generic_error_category::message( int ev ) const
{
using namespace boost::system::errc;
#if defined(__PGI)
using boost::system::errc::invalid_argument;
#endif
@@ -158,18 +164,18 @@
return msg;
# endif // else POSIX version of strerror_r
# endif // else use strerror_r
}
// system_error_category implementation --------------------------------------------//
- const char * system_error_category::name() const BOOST_SYSTEM_NOEXCEPT
+ BOOST_ERROR_CODE_HEADER_ONLY_INLINE const char * system_error_category::name() const BOOST_SYSTEM_NOEXCEPT
{
return "system";
}
- error_condition system_error_category::default_error_condition( int ev ) const
+ BOOST_ERROR_CODE_HEADER_ONLY_INLINE error_condition system_error_category::default_error_condition( int ev ) const
BOOST_SYSTEM_NOEXCEPT
{
using namespace boost::system::errc;
#if defined(__PGI)
using boost::system::errc::invalid_argument;
#endif
@@ -368,19 +374,19 @@
default: return error_condition( ev, system_category() );
}
}
# if !defined( BOOST_WINDOWS_API )
- std::string system_error_category::message( int ev ) const
+ BOOST_ERROR_CODE_HEADER_ONLY_INLINE std::string system_error_category::message( int ev ) const
{
return generic_category().message( ev );
}
# else
- std::string system_error_category::message( int ev ) const
+ BOOST_ERROR_CODE_HEADER_ONLY_INLINE std::string system_error_category::message( int ev ) const
{
#if defined(UNDER_CE) || BOOST_PLAT_WINDOWS_RUNTIME || defined(BOOST_NO_ANSI_APIS)
std::wstring buf(128, wchar_t());
for (;;)
{
boost::detail::winapi::DWORD_ retval = boost::detail::winapi::FormatMessageW(
@@ -478,6 +484,8 @@
static const generic_error_category generic_category_const;
return generic_category_const;
}
} // namespace system
} // namespace boost
+
+# undef BOOST_ERROR_CODE_HEADER_ONLY_INLINE
--- boost\system\error_code.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\system\error_code.hpp 2017-08-21 15:49:24.000000000 -0700
@@ -615,25 +615,25 @@
inline error_condition make_error_condition( errc_t e ) BOOST_SYSTEM_NOEXCEPT
{ return error_condition( e, generic_category() ); }
}
// error_category default implementation -----------------------------------------//
- error_condition error_category::default_error_condition( int ev ) const
+ inline error_condition error_category::default_error_condition( int ev ) const
BOOST_SYSTEM_NOEXCEPT
{
return error_condition( ev, *this );
}
- bool error_category::equivalent( int code,
+ inline bool error_category::equivalent( int code,
const error_condition & condition ) const BOOST_SYSTEM_NOEXCEPT
{
return default_error_condition( code ) == condition;
}
- bool error_category::equivalent( const error_code & code,
+ inline bool error_category::equivalent( const error_code & code,
int condition ) const BOOST_SYSTEM_NOEXCEPT
{
return *this == code.category() && code.value() == condition;
}
#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR
--- boost\thread\detail\config.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\thread\detail\config.hpp 2017-08-26 22:32:24.000000000 -0700
@@ -9,27 +9,25 @@
#define BOOST_THREAD_CONFIG_WEK01032003_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/thread/detail/platform.hpp>
-#define BOOST_THREAD_USEFIXES_TIMESPEC
//#define BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
//#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
// ATTRIBUTE_MAY_ALIAS
-#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+//#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+#if !defined(BOOST_NO_MAY_ALIAS)
- // GCC since 3.3 has may_alias attribute that helps to alleviate optimizer issues with
- // regard to violation of the strict aliasing rules.
+ // GCC since 3.3 and some other compilers have may_alias attribute that helps
+ // to alleviate optimizer issues with regard to violation of the strict aliasing rules.
#define BOOST_THREAD_DETAIL_USE_ATTRIBUTE_MAY_ALIAS
- #define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS __attribute__((__may_alias__))
-#else
- #define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS
#endif
+#define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS BOOST_MAY_ALIAS
#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
#define BOOST_THREAD_ASSERT_PRECONDITION(EXPR, EX) \
if (EXPR) {} else boost::throw_exception(EX)
#define BOOST_THREAD_VERIFY_PRECONDITION(EXPR, EX) \
--- boost\thread\detail\thread.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\thread\detail\thread.hpp 2017-08-26 22:32:24.000000000 -0700
@@ -154,13 +154,13 @@
}
};
#endif
}
namespace thread_detail {
#ifdef BOOST_THREAD_USES_CHRONO
-#if defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) && defined(BOOST_THREAD_USEFIXES_TIMESPEC)
+#if defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC)
typedef chrono::steady_clock internal_clock_t;
#else
typedef chrono::system_clock internal_clock_t;
#endif
#endif
}
@@ -296,13 +296,13 @@
start_thread(attrs);
}
#else
template <class F>
explicit thread(F f
, typename disable_if_c<
- boost::thread_detail::is_rv<F>::value // todo ass a thread_detail::is_rv
+ boost::thread_detail::is_rv<F>::value // todo as a thread_detail::is_rv
//boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value
//|| is_same<typename decay<F>::type, thread>::value
, dummy* >::type=0
):
thread_info(make_thread_info(f))
{
--- boost\thread\executors\detail\priority_executor_base.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\thread\executors\detail\priority_executor_base.hpp 2017-08-28 20:49:56.000000000 -0700
@@ -54,16 +54,22 @@
void loop()
{
try
{
for(;;)
{
- work task;
- queue_op_status st = _workq.wait_pull(task);
- if (st == queue_op_status::closed) return;
- task();
+ try {
+ work task;
+ queue_op_status st = _workq.wait_pull(task);
+ if (st == queue_op_status::closed) return;
+ task();
+ }
+ catch (boost::thread_interrupted&)
+ {
+ return;
+ }
}
}
catch (...)
{
std::terminate();
return;
--- boost\thread\executors\basic_thread_pool.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\thread\executors\basic_thread_pool.hpp 2017-08-28 20:49:56.000000000 -0700
@@ -83,17 +83,24 @@
{
try
{
for(;;)
{
work task;
- queue_op_status st = work_queue.wait_pull(task);
- if (st == queue_op_status::closed) {
- return;
- }
- task();
+ try
+ {
+ queue_op_status st = work_queue.wait_pull(task);
+ if (st == queue_op_status::closed) {
+ return;
+ }
+ task();
+ }
+ catch (boost::thread_interrupted&)
+ {
+ return;
+ }
}
}
catch (...)
{
std::terminate();
return;
@@ -231,12 +238,13 @@
* \b Effects: join all the threads.
*/
void join()
{
for (unsigned i = 0; i < threads.size(); ++i)
{
+ threads[i].interrupt();
threads[i].join();
}
}
/**
* \b Effects: close the \c basic_thread_pool for submissions.
--- boost\thread\executors\scheduled_thread_pool.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\thread\executors\scheduled_thread_pool.hpp 2017-08-28 20:49:56.000000000 -0700
@@ -29,12 +29,13 @@
}
}
~scheduled_thread_pool()
{
this->close();
+ _workers.interrupt_all();
_workers.join_all();
}
private:
typedef detail::scheduled_executor_base<> super;
}; //end class
--- boost\thread\executors\scheduler.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\thread\executors\scheduler.hpp 2017-08-28 20:49:56.000000000 -0700
@@ -228,12 +228,13 @@
: super(),
thr(&super::loop, this) {}
~scheduler()
{
this->close();
+ thr.interrupt();
thr.join();
}
template <class Ex>
scheduler_executor_wrapper<scheduler, Ex> on(Ex& ex)
{
return scheduler_executor_wrapper<scheduler, Ex>(*this, ex);
--- boost\thread\executors\scheduling_adaptor.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\thread\executors\scheduling_adaptor.hpp 2017-08-28 20:49:56.000000000 -0700
@@ -28,12 +28,13 @@
_exec(ex),
_scheduler(&super::loop, this) {}
~scheduling_adpator()
{
this->close();
+ _scheduler.interrupt();
_scheduler.join();
}
Executor& underlying_executor()
{
return _exec;
--- boost\thread\pthread\condition_variable_fwd.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\thread\pthread\condition_variable_fwd.hpp 2017-08-26 22:32:24.000000000 -0700
@@ -50,15 +50,15 @@
}
}
class condition_variable
{
private:
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
pthread_mutex_t internal_mutex;
-#endif
+//#endif
pthread_cond_t cond;
public:
//private: // used by boost::thread::try_join_until
inline bool do_wait_until(
@@ -66,58 +66,56 @@
struct timespec const &timeout);
bool do_wait_for(
unique_lock<mutex>& lock,
struct timespec const &timeout)
{
-#if ! defined BOOST_THREAD_USEFIXES_TIMESPEC
- return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now()));
-#elif ! defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
- //using namespace chrono;
- //nanoseconds ns = chrono::system_clock::now().time_since_epoch();
-
- struct timespec ts = boost::detail::timespec_now_realtime();
- //ts.tv_sec = static_cast<long>(chrono::duration_cast<chrono::seconds>(ns).count());
- //ts.tv_nsec = static_cast<long>((ns - chrono::duration_cast<chrono::seconds>(ns)).count());
- return do_wait_until(lock, boost::detail::timespec_plus(timeout, ts));
+#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
+ return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now_monotonic()));
#else
// old behavior was fine for monotonic
return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now_realtime()));
#endif
}
public:
BOOST_THREAD_NO_COPYABLE(condition_variable)
condition_variable()
{
int res;
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ // Even if it is not used, the internal_mutex exists (see
+ // above) and must be initialized (etc) in case some
+ // compilation units provide interruptions and others
+ // don't.
res=pthread_mutex_init(&internal_mutex,NULL);
if(res)
{
boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init"));
}
-#endif
+//#endif
res = detail::monotonic_pthread_cond_init(cond);
if (res)
{
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ // ditto
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
-#endif
+//#endif
boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in detail::monotonic_pthread_cond_init"));
}
}
~condition_variable()
{
int ret;
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ // ditto
do {
ret = pthread_mutex_destroy(&internal_mutex);
} while (ret == EINTR);
BOOST_ASSERT(!ret);
-#endif
+//#endif
do {
ret = pthread_cond_destroy(&cond);
} while (ret == EINTR);
BOOST_ASSERT(!ret);
}
--- boost\thread\pthread\shared_mutex.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\thread\pthread\shared_mutex.hpp 2017-08-26 22:32:24.000000000 -0700
@@ -17,13 +17,12 @@
#endif
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
-#include <boost/assert.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class shared_mutex
--- boost\thread\pthread\thread_data.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\thread\pthread\thread_data.hpp 2017-08-26 22:32:24.000000000 -0700
@@ -47,13 +47,17 @@
int res = pthread_attr_destroy(&val_);
BOOST_VERIFY(!res && "pthread_attr_destroy failed");
}
// stack
void set_stack_size(std::size_t size) BOOST_NOEXCEPT {
if (size==0) return;
+#ifdef BOOST_THREAD_USES_GETPAGESIZE
std::size_t page_size = getpagesize();
+#else
+ std::size_t page_size = ::sysconf( _SC_PAGESIZE);
+#endif
#ifdef PTHREAD_STACK_MIN
if (size<PTHREAD_STACK_MIN) size=PTHREAD_STACK_MIN;
#endif
size = ((size+page_size-1)/page_size)*page_size;
int res = pthread_attr_setstacksize(&val_, size);
BOOST_VERIFY(!res && "pthread_attr_setstacksize failed");
@@ -237,16 +241,18 @@
namespace this_thread
{
namespace hidden
{
void BOOST_THREAD_DECL sleep_for(const timespec& ts);
- void BOOST_THREAD_DECL sleep_until(const timespec& ts);
+ void BOOST_THREAD_DECL sleep_until_realtime(const timespec& ts);
}
#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Rep, class Period>
+ void sleep_for(const chrono::duration<Rep, Period>& d);
#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY
inline
void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
{
return boost::this_thread::hidden::sleep_for(boost::detail::to_timespec(ns));
@@ -256,16 +262,18 @@
namespace no_interruption_point
{
namespace hidden
{
void BOOST_THREAD_DECL sleep_for(const timespec& ts);
- void BOOST_THREAD_DECL sleep_until(const timespec& ts);
+ void BOOST_THREAD_DECL sleep_until_realtime(const timespec& ts);
}
#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Rep, class Period>
+ void sleep_for(const chrono::duration<Rep, Period>& d);
#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY
inline
void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
{
return boost::this_thread::no_interruption_point::hidden::sleep_for(boost::detail::to_timespec(ns));
@@ -281,13 +289,13 @@
#ifdef __DECXXX
/// Workaround of DECCXX issue of incorrect template substitution
template<>
#endif
inline void sleep(system_time const& abs_time)
{
- return boost::this_thread::hidden::sleep_until(boost::detail::to_timespec(abs_time));
+ return boost::this_thread::hidden::sleep_until_realtime(boost::detail::to_timespec(abs_time));
}
template<typename TimeDuration>
inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
{
this_thread::sleep(get_system_time()+rel_time);
--- boost\thread\pthread\thread_heap_alloc.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\thread\pthread\thread_heap_alloc.hpp 2017-08-26 22:32:24.000000000 -0700
@@ -13,14 +13,19 @@
{
template<typename T>
inline T* heap_new()
{
return new T();
}
-
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) && ! defined (BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template<typename T,typename... Args>
+ inline T* heap_new(Args&&... args)
+ {
+ return new T(static_cast<Args&&>(args)...);
+ }
+#elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename T,typename A1>
inline T* heap_new(A1&& a1)
{
return new T(static_cast<A1&&>(a1));
}
template<typename T,typename A1,typename A2>
@@ -57,12 +62,37 @@
return new T(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4)
{
return new T(a1,a2,a3,a4);
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5>
+ inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5)
+ {
+ return new T(a1,a2,a3,a4,a5);
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5,typename A6>
+ inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6)
+ {
+ return new T(a1,a2,a3,a4,a5,a6);
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7>
+ inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7)
+ {
+ return new T(a1,a2,a3,a4,a5,a6,a7);
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7,typename A8>
+ inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8)
+ {
+ return new T(a1,a2,a3,a4,a5,a6,a7,a8);
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7,typename A8,typename A9>
+ inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9)
+ {
+ return new T(a1,a2,a3,a4,a5,a6,a7,a8,a9);
}
template<typename T,typename A1>
inline T* heap_new(A1 const& a1)
{
return heap_new_impl<T,A1 const&>(a1);
--- boost\thread\pthread\timespec.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\thread\pthread\timespec.hpp 2017-08-26 22:32:24.000000000 -0700
@@ -68,38 +68,27 @@
return static_cast<boost::intmax_t>(ts.tv_sec) * 1000000000l + ts.tv_nsec;
}
inline bool timespec_ge_zero(timespec const& ts)
{
return (ts.tv_sec >= 0) || (ts.tv_nsec >= 0);
}
- inline timespec timespec_now()
+#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
+
+ inline timespec timespec_now_monotonic()
{
timespec ts;
-#if defined CLOCK_MONOTONIC && defined BOOST_THREAD_USEFIXES_TIMESPEC
if ( ::clock_gettime( CLOCK_MONOTONIC, &ts ) )
{
ts.tv_sec = 0;
ts.tv_nsec = 0;
BOOST_ASSERT(0 && "Boost::Thread - Internal Error");
}
-#elif defined(BOOST_THREAD_TIMESPEC_MAC_API)
- timeval tv;
- ::gettimeofday(&tv, 0);
- ts.tv_sec = tv.tv_sec;
- ts.tv_nsec = tv.tv_usec * 1000;
-#else
- if ( ::clock_gettime( CLOCK_REALTIME, &ts ) )
- {
- ts.tv_sec = 0;
- ts.tv_nsec = 0;
- BOOST_ASSERT(0 && "Boost::Thread - Internal Error");
- }
+ return ts;
+ }
#endif
- return ts;
- }
inline timespec timespec_now_realtime()
{
timespec ts;
#if defined(BOOST_THREAD_TIMESPEC_MAC_API)
--- boost\thread\win32\condition_variable.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\thread\win32\condition_variable.hpp 2017-08-26 22:32:24.000000000 -0700
@@ -208,23 +208,23 @@
#else
entry_manager(entry_ptr const& entry_, boost::mutex& mutex_):
entry(entry_), internal_mutex(mutex_)
{}
#endif
- void remove_waiter()
+ void remove_waiter_and_reset()
{
if (entry) {
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
entry->remove_waiter();
entry.reset();
}
}
~entry_manager() BOOST_NOEXCEPT_IF(false)
{
- remove_waiter();
+ remove_waiter_and_reset();
}
list_entry* operator->()
{
return entry.get();
}
@@ -247,13 +247,13 @@
return false;
}
woken=entry->woken();
}
// do it here to avoid throwing on the destructor
- entry->remove_waiter();
+ entry.remove_waiter_and_reset();
locker.lock();
return woken;
}
template<typename lock_type,typename predicate_type>
bool do_wait(lock_type& m,timeout const& abs_time,predicate_type pred)
--- boost\thread\win32\thread_heap_alloc.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\thread\win32\thread_heap_alloc.hpp 2017-08-26 22:32:24.000000000 -0700
@@ -69,13 +69,30 @@
}
inline void free_raw_heap_memory(void* heap_memory)
{
BOOST_VERIFY(detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,heap_memory)!=0);
}
-
+#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) && ! defined (BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template<typename T,typename... Args>
+ inline T* heap_new(Args&&... args)
+ {
+ void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
+ BOOST_TRY
+ {
+ T* const data=new (heap_memory) T(static_cast<Args&&>(args)...);
+ return data;
+ }
+ BOOST_CATCH(...)
+ {
+ free_raw_heap_memory(heap_memory);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
+#else
template<typename T>
inline T* heap_new()
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
BOOST_TRY
{
@@ -222,12 +239,92 @@
{
free_raw_heap_memory(heap_memory);
BOOST_RETHROW
}
BOOST_CATCH_END
}
+ template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5>
+ inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5)
+ {
+ void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
+ BOOST_TRY
+ {
+ T* const data=new (heap_memory) T(a1,a2,a3,a4,a5);
+ return data;
+ }
+ BOOST_CATCH(...)
+ {
+ free_raw_heap_memory(heap_memory);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5,typename A6>
+ inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6)
+ {
+ void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
+ BOOST_TRY
+ {
+ T* const data=new (heap_memory) T(a1,a2,a3,a4,a5,a6);
+ return data;
+ }
+ BOOST_CATCH(...)
+ {
+ free_raw_heap_memory(heap_memory);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7>
+ inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7)
+ {
+ void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
+ BOOST_TRY
+ {
+ T* const data=new (heap_memory) T(a1,a2,a3,a4,a5,a6,a7);
+ return data;
+ }
+ BOOST_CATCH(...)
+ {
+ free_raw_heap_memory(heap_memory);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7,typename A8>
+ inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8)
+ {
+ void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
+ BOOST_TRY
+ {
+ T* const data=new (heap_memory) T(a1,a2,a3,a4,a5,a6,a7,a8);
+ return data;
+ }
+ BOOST_CATCH(...)
+ {
+ free_raw_heap_memory(heap_memory);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7,typename A8,typename A9>
+ inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9)
+ {
+ void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
+ BOOST_TRY
+ {
+ T* const data=new (heap_memory) T(a1,a2,a3,a4,a5,a6,a7,a8,a9);
+ return data;
+ }
+ BOOST_CATCH(...)
+ {
+ free_raw_heap_memory(heap_memory);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
template<typename T,typename A1>
inline T* heap_new(A1 const& a1)
{
return heap_new_impl<T,A1 const&>(a1);
@@ -382,12 +479,13 @@
inline T* heap_new(A1& a1,A2& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4);
}
#endif
+#endif
template<typename T>
inline void heap_delete(T* data)
{
data->~T();
free_raw_heap_memory(data);
}
--- boost\thread\future.hpp 2017-08-19 09:49:49.000000000 -0700
+++ boost\thread\future.hpp 2017-08-26 22:32:24.000000000 -0700
@@ -296,13 +296,13 @@
end=external_waiters.end();it!=end;++it)
{
(*it)->notify_all();
}
do_continuation(lock);
}
- void make_ready()
+ void notify_deferred()
{
boost::unique_lock<boost::mutex> lock(this->mutex);
mark_finished_internal(lock);
}
void do_callback(boost::unique_lock<boost::mutex>& lock)
--- boost\type_erasure\detail\vtable.hpp 2017-08-19 09:49:50.000000000 -0700
+++ boost\type_erasure\detail\vtable.hpp 2017-08-21 15:49:42.000000000 -0700
@@ -27,13 +27,13 @@
#include <boost/type_erasure/config.hpp>
namespace boost {
namespace type_erasure {
namespace detail {
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && (!defined(BOOST_MSVC) || BOOST_MSVC_FULL_VER > 190023026)
template<class... T>
struct stored_arg_pack;
template<class It, class End, class... T>
struct make_arg_pack_impl
--- boost\uuid\random_generator.hpp 2017-08-19 09:49:50.000000000 -0700
+++ boost\uuid\random_generator.hpp 2017-08-21 15:50:03.000000000 -0700
@@ -7,13 +7,13 @@
#ifndef BOOST_UUID_RANDOM_GENERATOR_HPP
#define BOOST_UUID_RANDOM_GENERATOR_HPP
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/seed_rng.hpp>
-#include <boost/random/uniform_int.hpp>
+#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/variate_generator.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/core/null_deleter.hpp>
#include <boost/assert.hpp>
#include <boost/shared_ptr.hpp>
#include <limits>
@@ -22,56 +22,47 @@
namespace uuids {
// generate a random-based uuid
template <typename UniformRandomNumberGenerator>
class basic_random_generator {
private:
- typedef uniform_int<unsigned long> distribution_type;
+ typedef random::uniform_int_distribution<unsigned long> distribution_type;
typedef variate_generator<UniformRandomNumberGenerator*, distribution_type> generator_type;
public:
typedef uuid result_type;
// default constructor creates the random number generator
basic_random_generator()
: pURNG(new UniformRandomNumberGenerator)
, generator
( pURNG.get()
- , distribution_type
- ( (std::numeric_limits<unsigned long>::min)()
- , (std::numeric_limits<unsigned long>::max)()
- )
+ , distribution_type()
)
{
// seed the random number generator
detail::seed(*pURNG);
}
// keep a reference to a random number generator
// don't seed a given random number generator
explicit basic_random_generator(UniformRandomNumberGenerator& gen)
: pURNG(&gen, boost::null_deleter())
, generator
( pURNG.get()
- , distribution_type
- ( (std::numeric_limits<unsigned long>::min)()
- , (std::numeric_limits<unsigned long>::max)()
- )
+ , distribution_type()
)
{}
// keep a pointer to a random number generator
// don't seed a given random number generator
explicit basic_random_generator(UniformRandomNumberGenerator* pGen)
: pURNG(pGen, boost::null_deleter())
, generator
( pURNG.get()
- , distribution_type
- ( (std::numeric_limits<unsigned long>::min)()
- , (std::numeric_limits<unsigned long>::max)()
- )
+ , distribution_type()
)
{
BOOST_ASSERT(pURNG);
}
uuid operator()()
--- boost\cstdint.hpp 2017-08-19 09:49:40.000000000 -0700
+++ boost\cstdint.hpp 2017-08-28 19:23:30.000000000 -0700
@@ -364,18 +364,15 @@
// intptr_t/uintptr_t are defined separately because they are optional and not universally available
#if defined(BOOST_WINDOWS) && !defined(_WIN32_WCE) && !defined(BOOST_HAS_STDINT_H)
// Older MSVC don't have stdint.h and have intptr_t/uintptr_t defined in stddef.h
#include <stddef.h>
#endif
-// PGI seems to not support intptr_t/uintptr_t properly. BOOST_HAS_STDINT_H is not defined for this compiler by Boost.Config.
-#if !defined(__PGIC__)
-
#if (defined(BOOST_WINDOWS) && !defined(_WIN32_WCE)) \
|| (defined(_XOPEN_UNIX) && (_XOPEN_UNIX+0 > 0) && !defined(__UCLIBC__)) \
- || defined(__CYGWIN__) \
+ || defined(__CYGWIN__) || defined(__VXWORKS__) \
|| defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \
|| defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || (defined(sun) && !defined(BOOST_HAS_STDINT_H)) || defined(INTPTR_MAX)
namespace boost {
using ::intptr_t;
using ::uintptr_t;
@@ -387,16 +384,14 @@
namespace boost {
typedef __INTPTR_TYPE__ intptr_t;
typedef __UINTPTR_TYPE__ uintptr_t;
}
#define BOOST_HAS_INTPTR_T
-
-#endif
-#endif // !defined(__PGIC__)
+#endif
#endif // BOOST_CSTDINT_HPP
/****************************************************
--- boost\hana.hpp 2017-08-19 09:49:42.000000000 -0700
+++ boost\hana.hpp 2017-08-21 18:32:53.000000000 -0700
@@ -111,12 +111,13 @@
#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/hash.hpp>
#include <boost/hana/index_if.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>
---
+++ boost\mp11.hpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,22 @@
+#ifndef BOOST_MP11_HPP_INCLUDED
+#define BOOST_MP11_HPP_INCLUDED
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/utility.hpp>
+#include <boost/mp11/function.hpp>
+#include <boost/mp11/map.hpp>
+#include <boost/mp11/set.hpp>
+#include <boost/mp11/bind.hpp>
+#include <boost/mp11/integer_sequence.hpp>
+#include <boost/mp11/tuple.hpp>
+
+#endif // #ifndef BOOST_MP11_HPP_INCLUDED
--- boost\scope_exit.hpp 2017-08-19 09:49:48.000000000 -0700
+++ boost\scope_exit.hpp 2017-08-21 15:50:46.000000000 -0700
@@ -58,13 +58,13 @@
#if BOOST_WORKAROUND(BOOST_SCOPE_EXIT_AUX_GCC, BOOST_TESTED_AT(413))
# define BOOST_SCOPE_EXIT_AUX_TPL_GCC_WORKAROUND_01 1
#else
# define BOOST_SCOPE_EXIT_AUX_TPL_GCC_WORKAROUND_01 0
#endif
-#if BOOST_MSVC
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1800 )
# define BOOST_SCOPE_EXIT_AUX_TYPEOF_THIS_MSVC_WORKAROUND_01 1
#else
# define BOOST_SCOPE_EXIT_AUX_TYPEOF_THIS_MSVC_WORKAROUND_01 0
#endif
// MSVC has problems expanding __LINE__ so use (the non standard) __COUNTER__.
--- boost\type_index.hpp 2017-08-19 09:49:50.000000000 -0700
+++ boost\type_index.hpp 2017-08-21 15:51:09.000000000 -0700
@@ -22,13 +22,13 @@
#if defined(BOOST_TYPE_INDEX_USER_TYPEINDEX)
# include BOOST_TYPE_INDEX_USER_TYPEINDEX
# ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
# pragma detect_mismatch( "boost__type_index__abi", "user defined type_index class is used: " BOOST_STRINGIZE(BOOST_TYPE_INDEX_USER_TYPEINDEX))
# endif
-#elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
+#elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || (defined(BOOST_MSVC) && BOOST_MSVC < 1910)
# include <boost/type_index/stl_type_index.hpp>
# if defined(BOOST_NO_RTTI) || defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)
# include <boost/type_index/detail/stl_register_class.hpp>
# ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
# pragma detect_mismatch( "boost__type_index__abi", "RTTI is off - typeid() is used only for templates")
# endif
@@ -125,13 +125,13 @@
/// user defined type_index class.
///
/// \b See boost::typeindex::type_index_facade for a full description of type_index functions.
typedef platform_specific type_index;
#elif defined(BOOST_TYPE_INDEX_USER_TYPEINDEX)
// Nothing to do
-#elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
+#elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || (defined(BOOST_MSVC) && BOOST_MSVC < 1910)
typedef boost::typeindex::stl_type_index type_index;
#else
typedef boost::typeindex::ctti_type_index type_index;
#endif
/// Depending on a compiler flags, optimal implementation of type_info will be used
--- libs\config\checks\Jamfile.v2 2017-08-19 09:49:40.000000000 -0700
+++ libs\config\checks\Jamfile.v2 2017-08-28 19:23:29.000000000 -0700
@@ -1,9 +1,9 @@
#
# *** DO NOT EDIT THIS FILE BY HAND ***
-# This file was automatically generated on Mon May 29 10:27:35 2017
+# This file was automatically generated on Sun Jul 9 16:30:35 2017
# by libs/config/tools/generate.cpp
# Copyright John Maddock.
# Use, modification and distribution are subject to the
# Boost Software License, Version 1.0. (See accompanying file
# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -108,12 +108,13 @@
obj cxx14_aggregate_nsdmi : test_case.cpp : <define>TEST_BOOST_NO_CXX14_AGGREGATE_NSDMI ;
obj cxx14_return_type_deduction : test_case.cpp : <define>TEST_BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION ;
obj cxx14_std_exchange : test_case.cpp : <define>TEST_BOOST_NO_CXX14_STD_EXCHANGE ;
obj cxx14_variable_templates : test_case.cpp : <define>TEST_BOOST_NO_CXX14_VARIABLE_TEMPLATES ;
obj cxx17_fold_expressions : test_case.cpp : <define>TEST_BOOST_NO_CXX17_FOLD_EXPRESSIONS ;
obj cxx17_inline_variables : test_case.cpp : <define>TEST_BOOST_NO_CXX17_INLINE_VARIABLES ;
+obj cxx17_iterator_traits : test_case.cpp : <define>TEST_BOOST_NO_CXX17_ITERATOR_TRAITS ;
obj cxx17_std_apply : test_case.cpp : <define>TEST_BOOST_NO_CXX17_STD_APPLY ;
obj cxx17_std_invoke : test_case.cpp : <define>TEST_BOOST_NO_CXX17_STD_INVOKE ;
obj cxx17_structured_bindings : test_case.cpp : <define>TEST_BOOST_NO_CXX17_STRUCTURED_BINDINGS ;
obj cxx98_binders : test_case.cpp : <define>TEST_BOOST_NO_CXX98_BINDERS ;
obj cxx98_function_base : test_case.cpp : <define>TEST_BOOST_NO_CXX98_FUNCTION_BASE ;
obj cxx98_random_shuffle : test_case.cpp : <define>TEST_BOOST_NO_CXX98_RANDOM_SHUFFLE ;
--- libs\config\checks\test_case.cpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\config\checks\test_case.cpp 2017-08-28 19:23:29.000000000 -0700
@@ -1,7 +1,7 @@
-// This file was automatically generated on Mon May 29 10:27:35 2017
+// This file was automatically generated on Sun Jul 9 16:30:35 2017
// by libs/config/tools/generate.cpp
// Copyright John Maddock 2002-4.
// 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)
@@ -508,12 +508,17 @@
#endif
#ifdef TEST_BOOST_NO_CXX17_INLINE_VARIABLES
# ifdef BOOST_NO_CXX17_INLINE_VARIABLES
# error "Defect macro BOOST_NO_CXX17_INLINE_VARIABLES is defined."
# endif
#endif
+#ifdef TEST_BOOST_NO_CXX17_ITERATOR_TRAITS
+# ifdef BOOST_NO_CXX17_ITERATOR_TRAITS
+# error "Defect macro BOOST_NO_CXX17_ITERATOR_TRAITS is defined."
+# endif
+#endif
#ifdef TEST_BOOST_NO_CXX17_STD_APPLY
# ifdef BOOST_NO_CXX17_STD_APPLY
# error "Defect macro BOOST_NO_CXX17_STD_APPLY is defined."
# endif
#endif
#ifdef TEST_BOOST_NO_CXX17_STD_INVOKE
--- libs\config\doc\config.qbk 2017-08-19 09:49:40.000000000 -0700
+++ libs\config\doc\config.qbk 2017-08-28 19:23:29.000000000 -0700
@@ -19,13 +19,13 @@
[/ Cited Boost resources ]
[def __BOOST_REGRESSION_TEST_DRIVER__ [@../../../../tools/regression/doc/index.html boost regression test driver]]
[def __BOOST_CONFIG_HEADER__ [@../../../../boost/config.hpp <boost/config.hpp>]]
[def __BOOST_CONFIG_USER_HEADER__ [@../../../../boost/config/user.hpp <boost/config/user.hpp>]]
-[def __BOOST_CONFIG_SUFFIX_HEADER__ [@../../../../boost/config/user.hpp <boost/config/suffix.hpp>]]
+[def __BOOST_CONFIG_SUFFIX_HEADER__ [@../../../../boost/config/detail/suffix.hpp <boost/config/detail/suffix.hpp>]]
[def __BOOST_CONFIG_DIR__ ['<boost-root>]`/boost/config/`]
[/ Other web resources ]
[def __STL_PORT__ [@http://stlport.sourceforge.net STLport]]
--- libs\config\doc\guidelines.qbk 2017-08-19 09:49:40.000000000 -0700
+++ libs\config\doc\guidelines.qbk 2017-08-28 19:23:29.000000000 -0700
@@ -188,15 +188,15 @@
__BOOST_CONFIG_SUFFIX_HEADER__ is always included so be careful about
modifying this file as it breaks dependencies for everyone. This file should
include only "boilerplate" configuration code, and generally should change
only when new macros are added.
-[@../../../../boost/config/select_compiler_config.hpp <boost/config/select_compiler_config.hpp>],
-[@../../../../boost/config/select_platform_config.hpp <boost/config/select_platform_config.hpp>] and
-[@../../../../boost/config/select_stdlib_config.hpp <boost/config/select_stdlib_config.hpp>]
+[@../../../../boost/config/detail/select_compiler_config.hpp <boost/config/detail/select_compiler_config.hpp>],
+[@../../../../boost/config/detail/select_platform_config.hpp <boost/config/detail/select_platform_config.hpp>] and
+[@../../../../boost/config/detail/select_stdlib_config.hpp <boost/config/detail/select_stdlib_config.hpp>]
are included by default and should change only if support for a new
compiler/standard library/platform is added.
The compiler/platform/standard library selection code is set up so that unknown
platforms are ignored and assumed to be fully standards compliant - this gives
unknown platforms a "sporting chance" of working "as is" even without running
--- libs\config\doc\macro_reference.qbk 2017-08-19 09:49:40.000000000 -0700
+++ libs\config\doc\macro_reference.qbk 2017-08-28 19:23:29.000000000 -0700
@@ -942,12 +942,13 @@
that are not yet supported by a particular compiler or library.
[table
[[Macro ][Description ]]
[[`BOOST_NO_CXX17_STD_APPLY`][The compiler does not support `std::apply()`.]]
[[`BOOST_NO_CXX17_STD_INVOKE`][The compiler does not support `std::invoke()`.]]
+[[`BOOST_NO_CXX17_ITERATOR_TRAITS`][The compiler does not support SFINAE-friendly `std::iterator_traits`.]]
]
[endsect]
[section Macros that describe features that have been removed from the standard.]
@@ -1259,12 +1260,24 @@
if (BOOST_UNLIKELY(ptr == NULL))
handle_error("ptr is NULL");
``
]]
[[`BOOST_ATTRIBUTE_UNUSED`][Expands to `__attribute__((unused))` when this is available -
can be used to disable compiler warnings relating to unused types or variables.]]
+[[`BOOST_MAY_ALIAS`, `BOOST_NO_MAY_ALIAS`][
+`BOOST_MAY_ALIAS` expands to a type attribute that can be used to mark types that may
+alias other types. Pointers or references to such marked types can be used to access objects
+of other types. If the compiler supports this feature `BOOST_NO_MAY_ALIAS` is not defined.
+Otherwise `BOOST_MAY_ALIAS` expands to nothing and `BOOST_NO_MAY_ALIAS` is defined.
+
+Usage example:
+``
+ struct BOOST_MAY_ALIAS aliasing_struct;
+ typedef unsigned int BOOST_MAY_ALIAS aliasing_uint;
+``
+]]
]
[endsect]
[#config_info_macros]
--- libs\config\test\all\Jamfile.v2 2017-08-19 09:49:40.000000000 -0700
+++ libs\config\test\all\Jamfile.v2 2017-08-28 19:23:30.000000000 -0700
@@ -1,10 +1,10 @@
#
# Regression test Jamfile for boost configuration setup.
# *** DO NOT EDIT THIS FILE BY HAND ***
-# This file was automatically generated on Mon May 29 10:27:35 2017
+# This file was automatically generated on Sun Jul 9 16:30:35 2017
# by libs/config/tools/generate.cpp
# Copyright John Maddock.
# Use, modification and distribution are subject to the
# Boost Software License, Version 1.0. (See accompanying file
# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
@@ -319,12 +319,15 @@
test-suite "BOOST_NO_CXX17_FOLD_EXPRESSIONS" :
[ run ../no_cxx17_fold_expressions_pass.cpp ]
[ compile-fail ../no_cxx17_fold_expressions_fail.cpp ] ;
test-suite "BOOST_NO_CXX17_INLINE_VARIABLES" :
[ run ../no_cxx17_inline_variables_pass.cpp ]
[ compile-fail ../no_cxx17_inline_variables_fail.cpp ] ;
+test-suite "BOOST_NO_CXX17_ITERATOR_TRAITS" :
+[ run ../no_cxx17_iterator_traits_pass.cpp ]
+[ compile-fail ../no_cxx17_iterator_traits_fail.cpp ] ;
test-suite "BOOST_NO_CXX17_STD_APPLY" :
[ run ../no_cxx17_std_apply_pass.cpp ]
[ compile-fail ../no_cxx17_std_apply_fail.cpp ] ;
test-suite "BOOST_NO_CXX17_STD_INVOKE" :
[ run ../no_cxx17_std_invoke_pass.cpp ]
[ compile-fail ../no_cxx17_std_invoke_fail.cpp ] ;
--- libs\config\test\link\bc_gen.sh 2017-08-19 09:49:40.000000000 -0700
+++ libs\config\test\link\bc_gen.sh 2017-08-28 19:23:32.000000000 -0700
@@ -1,7 +1,7 @@
-#! /bin/bash
+#! /usr/bin/env bash
# copyright John Maddock 2005
# Use, modification and distribution are subject to the
# Boost Software License, Version 1.0. (See accompanying file
# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
--- libs\config\test\link\vc_gen.sh 2017-08-19 09:49:40.000000000 -0700
+++ libs\config\test\link\vc_gen.sh 2017-08-28 19:23:32.000000000 -0700
@@ -1,7 +1,7 @@
-#! /bin/bash
+#! /usr/bin/env bash
# copyright John Maddock 2005
# Use, modification and distribution are subject to the
# Boost Software License, Version 1.0. (See accompanying file
# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
libname=""
---
+++ libs\config\test\boost_no_cxx17_iterator_traits.ipp 2017-08-28 19:23:31.000000000 -0700
@@ -0,0 +1,49 @@
+// Copyright (c) Andrey Semashev 2017.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/config for most recent version.
+
+// MACRO: BOOST_NO_CXX17_ITERATOR_TRAITS
+// TITLE: C++17 std::iterator_traits
+// DESCRIPTION: The compiler does not support SFINAE-friendly std::iterator_traits defined in C++17.
+
+#include <iterator>
+
+namespace boost_no_cxx17_iterator_traits {
+
+struct iterator :
+ public std::iterator< std::random_access_iterator_tag, char >
+{
+};
+
+struct non_iterator {};
+
+template< typename T >
+struct void_type { typedef void type; };
+
+template< typename Traits, typename Void = void >
+struct has_iterator_category
+{
+ enum { value = false };
+};
+
+template< typename Traits >
+struct has_iterator_category< Traits, typename void_type< typename Traits::iterator_category >::type >
+{
+ enum { value = true };
+};
+
+int test()
+{
+ if (!has_iterator_category< std::iterator_traits< boost_no_cxx17_iterator_traits::iterator > >::value)
+ return 1;
+
+ if (has_iterator_category< std::iterator_traits< boost_no_cxx17_iterator_traits::non_iterator > >::value)
+ return 2;
+
+ return 0;
+}
+
+}
--- libs\config\test\config_info.cpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\config\test\config_info.cpp 2017-08-28 19:23:31.000000000 -0700
@@ -150,12 +150,13 @@
PRINT_MACRO(_M_MRX000);
PRINT_MACRO(_M_PPC);
PRINT_MACRO(_MFC_VER);
PRINT_MACRO(_MSC_EXTENSIONS);
PRINT_MACRO(_MSC_VER);
PRINT_MACRO(_MSC_FULL_VER);
+ PRINT_MACRO(_MSVC_LANG);
PRINT_MACRO(_MT);
PRINT_MACRO(_NATIVE_WCHAR_T_DEFINED);
// GNUC options:
PRINT_MACRO(__GNUC__);
PRINT_MACRO(__GNUC_MINOR__);
PRINT_MACRO(__GNUC_PATCHLEVEL__);
@@ -1070,12 +1071,13 @@
PRINT_MACRO(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES);
PRINT_MACRO(BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION);
PRINT_MACRO(BOOST_NO_CXX14_STD_EXCHANGE);
PRINT_MACRO(BOOST_NO_CXX14_VARIABLE_TEMPLATES);
PRINT_MACRO(BOOST_NO_CXX17_FOLD_EXPRESSIONS);
PRINT_MACRO(BOOST_NO_CXX17_INLINE_VARIABLES);
+ PRINT_MACRO(BOOST_NO_CXX17_ITERATOR_TRAITS);
PRINT_MACRO(BOOST_NO_CXX17_STD_APPLY);
PRINT_MACRO(BOOST_NO_CXX17_STD_INVOKE);
PRINT_MACRO(BOOST_NO_CXX17_STRUCTURED_BINDINGS);
PRINT_MACRO(BOOST_NO_CXX98_BINDERS);
PRINT_MACRO(BOOST_NO_CXX98_FUNCTION_BASE);
PRINT_MACRO(BOOST_NO_CXX98_RANDOM_SHUFFLE);
@@ -1136,12 +1138,13 @@
PRINT_MACRO(BOOST_NO_TYPENAME_WITH_CTOR);
PRINT_MACRO(BOOST_NO_UNREACHABLE_RETURN_DETECTION);
PRINT_MACRO(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE);
PRINT_MACRO(BOOST_NO_USING_TEMPLATE);
PRINT_MACRO(BOOST_NO_VOID_RETURNS);
+
// END GENERATED BLOCK
PRINT_MACRO(BOOST_INTEL);
PRINT_MACRO(BOOST_MSVC);
PRINT_MACRO(BOOST_STD_EXTENSION_NAMESPACE);
PRINT_MACRO(BOOST_UNREACHABLE_RETURN(0));
@@ -1149,12 +1152,14 @@
PRINT_MACRO(BOOST_CONSTEXPR_OR_CONST);
PRINT_MACRO(BOOST_STATIC_CONSTEXPR);
PRINT_MACRO(BOOST_NOEXCEPT);
PRINT_MACRO(BOOST_FORCEINLINE);
PRINT_MACRO(BOOST_NOINLINE);
PRINT_MACRO(BOOST_FALLTHROUGH);
+ PRINT_MACRO(BOOST_MAY_ALIAS);
+ PRINT_MACRO(BOOST_NO_MAY_ALIAS);
}
void print_separator()
{
std::cout <<
"\n\n*********************************************************************\n\n";
--- libs\config\test\config_test.cpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\config\test\config_test.cpp 2017-08-28 19:23:31.000000000 -0700
@@ -1,7 +1,7 @@
-// This file was automatically generated on Mon May 29 10:27:35 2017
+// This file was automatically generated on Sun Jul 9 16:30:35 2017
// by libs/config/tools/generate.cpp
// Copyright John Maddock 2002-4.
// 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)
@@ -339,12 +339,17 @@
#endif
#ifndef BOOST_NO_CXX17_INLINE_VARIABLES
#include "boost_no_cxx17_inline_variables.ipp"
#else
namespace boost_no_cxx17_inline_variables = empty_boost;
#endif
+#ifndef BOOST_NO_CXX17_ITERATOR_TRAITS
+#include "boost_no_cxx17_iterator_traits.ipp"
+#else
+namespace boost_no_cxx17_iterator_traits = empty_boost;
+#endif
#ifndef BOOST_NO_CXX17_STD_APPLY
#include "boost_no_cxx17_std_apply.ipp"
#else
namespace boost_no_cxx17_std_apply = empty_boost;
#endif
#ifndef BOOST_NO_CXX17_STD_INVOKE
@@ -1473,12 +1478,17 @@
}
if(0 != boost_no_cxx17_inline_variables::test())
{
std::cerr << "Failed test for BOOST_NO_CXX17_INLINE_VARIABLES at: " << __FILE__ << ":" << __LINE__ << std::endl;
++error_count;
}
+ if(0 != boost_no_cxx17_iterator_traits::test())
+ {
+ std::cerr << "Failed test for BOOST_NO_CXX17_ITERATOR_TRAITS at: " << __FILE__ << ":" << __LINE__ << std::endl;
+ ++error_count;
+ }
if(0 != boost_no_cxx17_std_apply::test())
{
std::cerr << "Failed test for BOOST_NO_CXX17_STD_APPLY at: " << __FILE__ << ":" << __LINE__ << std::endl;
++error_count;
}
if(0 != boost_no_cxx17_std_invoke::test())
--- libs\config\test\helper_macro_test.cpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\config\test\helper_macro_test.cpp 2017-08-28 19:23:32.000000000 -0700
@@ -31,12 +31,15 @@
BOOST_NORETURN void always_throw()
{
throw 0;
}
+struct BOOST_MAY_ALIAS aliasing_struct {};
+typedef unsigned int BOOST_MAY_ALIAS aliasing_uint;
+
#define test_fallthrough(x) foobar(x)
int main()
{
---
+++ libs\config\test\no_cxx17_iterator_traits_fail.cpp 2017-08-28 19:23:33.000000000 -0700
@@ -0,0 +1,37 @@
+// This file was automatically generated on Sun Jul 9 15:26:23 2017
+// by libs/config/tools/generate.cpp
+// Copyright John Maddock 2002-4.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/config for the most recent version.//
+// Revision $Id$
+//
+
+
+// Test file for macro BOOST_NO_CXX17_ITERATOR_TRAITS
+// This file should not compile, if it does then
+// BOOST_NO_CXX17_ITERATOR_TRAITS should not be defined.
+// See file boost_no_cxx17_iterator_traits.ipp for details
+
+// Must not have BOOST_ASSERT_CONFIG set; it defeats
+// the objective of this file:
+#ifdef BOOST_ASSERT_CONFIG
+# undef BOOST_ASSERT_CONFIG
+#endif
+
+#include <boost/config.hpp>
+#include "test.hpp"
+
+#ifdef BOOST_NO_CXX17_ITERATOR_TRAITS
+#include "boost_no_cxx17_iterator_traits.ipp"
+#else
+#error "this file should not compile"
+#endif
+
+int main( int, char *[] )
+{
+ return boost_no_cxx17_iterator_traits::test();
+}
+
---
+++ libs\config\test\no_cxx17_iterator_traits_pass.cpp 2017-08-28 19:23:33.000000000 -0700
@@ -0,0 +1,37 @@
+// This file was automatically generated on Sun Jul 9 15:26:23 2017
+// by libs/config/tools/generate.cpp
+// Copyright John Maddock 2002-4.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/config for the most recent version.//
+// Revision $Id$
+//
+
+
+// Test file for macro BOOST_NO_CXX17_ITERATOR_TRAITS
+// This file should compile, if it does not then
+// BOOST_NO_CXX17_ITERATOR_TRAITS should be defined.
+// See file boost_no_cxx17_iterator_traits.ipp for details
+
+// Must not have BOOST_ASSERT_CONFIG set; it defeats
+// the objective of this file:
+#ifdef BOOST_ASSERT_CONFIG
+# undef BOOST_ASSERT_CONFIG
+#endif
+
+#include <boost/config.hpp>
+#include "test.hpp"
+
+#ifndef BOOST_NO_CXX17_ITERATOR_TRAITS
+#include "boost_no_cxx17_iterator_traits.ipp"
+#else
+namespace boost_no_cxx17_iterator_traits = empty_boost;
+#endif
+
+int main( int, char *[] )
+{
+ return boost_no_cxx17_iterator_traits::test();
+}
+
--- libs\context\doc\callcc.qbk 2017-08-19 09:49:40.000000000 -0700
+++ libs\context\doc\callcc.qbk 2017-08-25 01:17:43.000000000 -0700
@@ -173,12 +173,13 @@
c=c.resume();
std::cout << "f1: returned second time: " << data << std::endl;
data+=1;
c=c.resume_with([&data](ctx::continuation && c){
std::cout << "f2: entered: " << data << std::endl;
data=-1;
+ return std::move( c);
});
std::cout << "f1: returned third time" << std::endl;
output:
f1: entered first time: 0
f1: returned first time: 1
@@ -218,12 +219,13 @@
}
return std::move(c);
});
c = c.resume_with(
[](ctx::continuation && c){
throw my_exception(std::move(c),"abc");
+ return std::move( c);
});
output:
entered
my_exception: abc
@@ -524,17 +526,17 @@
template<typename Fn>
continuation resume_with(Fn && fn);
[variablelist
[[Effects:] [Captures current continuation and resumes `*this`.
-The function `resume_with`, is used to execute function `fn` in continuation
+The function `resume_with`, is used to execute function `fn` in the execution context of
`*this` (e.g. the stack frame of `fn` is allocated on stack of `*this`).]]
[[Returns:] [The continuation representing the continuation that has been
suspended.]]
-[[Note:] [Function `fn` needs to return void.]]
+[[Note:] [Function `fn` needs to return `continuation`.]]
[[Note:] [The returned continuation indicates if the suspended continuation has
terminated (return from context-function) via `bool operator()`.]]
]
[operator_heading cc..operator_bool..operator bool]
--- libs\context\example\ontop.cpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\context\example\ontop.cpp 2017-08-25 01:18:30.000000000 -0700
@@ -29,11 +29,12 @@
c = c.resume();
std::cout << "f1: returned second time: " << data << std::endl;
data += 1;
c = c.resume_with( [&data](ctx::continuation && c){
std::cout << "f2: entered: " << data << std::endl;
data = -1;
+ return std::move( c);
});
std::cout << "f1: returned third time" << std::endl;
std::cout << "main: done" << std::endl;
return EXIT_SUCCESS;
}
--- libs\context\example\ontop_void.cpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\context\example\ontop_void.cpp 2017-08-25 01:19:16.000000000 -0700
@@ -18,14 +18,15 @@
std::cout << "f1: entered second time" << std::endl;
c = c.resume();
std::cout << "f1: entered third time" << std::endl;
return std::move( c);
}
-void f2( ctx::continuation && c) {
+ctx::continuation f2( ctx::continuation && c) {
std::cout << "f2: entered" << std::endl;
+ return std::move( c);
}
int main() {
ctx::continuation c = ctx::callcc( f1);
std::cout << "f1: returned first time" << std::endl;
c = c.resume();
--- libs\context\example\throw.cpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\context\example\throw.cpp 2017-08-25 01:19:36.000000000 -0700
@@ -35,12 +35,13 @@
}
return std::move( c);
});
c = c.resume_with(
[](ctx::continuation && c){
throw my_exception(std::move( c), "abc");
+ return std::move( c);
});
std::cout << "main: done" << std::endl;
return EXIT_SUCCESS;
}
--- libs\context\src\asm\jump_i386_sysv_macho_gas.S 2017-08-19 09:49:40.000000000 -0700
+++ libs\context\src\asm\jump_i386_sysv_macho_gas.S 2017-08-28 20:16:31.000000000 -0700
@@ -9,20 +9,20 @@
* *
* ---------------------------------------------------------------------------------- *
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
* ---------------------------------------------------------------------------------- *
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | *
* ---------------------------------------------------------------------------------- *
- * | fc_mxcsr|fc_x87_cw| EDI | ESI | EBX | EBP | EIP | hidden | *
+ * | fc_mxcsr|fc_x87_cw| EDI | ESI | EBX | EBP | EIP | to | *
* ---------------------------------------------------------------------------------- *
* ---------------------------------------------------------------------------------- *
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
* ---------------------------------------------------------------------------------- *
- * | 0x20 | 0x24 | | *
+ * | 0x20 | | *
* ---------------------------------------------------------------------------------- *
- * | to | data | | *
+ * | data | | *
* ---------------------------------------------------------------------------------- *
* *
****************************************************************************************/
.text
.globl _jump_fcontext
@@ -41,25 +41,23 @@
movl %ebp, 0x14(%esp) /* save EBP */
/* store ESP (pointing to context-data) in ECX */
movl %esp, %ecx
/* first arg of jump_fcontext() == fcontext to jump to */
- movl 0x20(%esp), %eax
+ movl 0x1c(%esp), %eax
/* second arg of jump_fcontext() == data to be transferred */
- movl 0x24(%esp), %edx
+ movl 0x20(%esp), %edx
/* restore ESP (pointing to context-data) from EAX */
movl %eax, %esp
- /* address of returned transport_t */
- movl 0x1c(%esp), %eax
/* return parent fcontext_t */
- movl %ecx, (%eax)
- /* return data */
+ movl %ecx, %eax
+ /* returned data is stored in EDX */
movl %edx, 0x4(%eax)
movl 0x18(%esp), %ecx /* restore EIP */
#if !defined(BOOST_USE_TSX)
ldmxcsr (%esp) /* restore MMX control- and status-word */
@@ -68,10 +66,10 @@
movl 0x8(%esp), %edi /* restore EDI */
movl 0xc(%esp), %esi /* restore ESI */
movl 0x10(%esp), %ebx /* restore EBX */
movl 0x14(%esp), %ebp /* restore EBP */
- leal 0x20(%esp), %esp /* prepare stack */
+ leal 0x1c(%esp), %esp /* prepare stack */
/* jump to context */
jmp *%ecx
--- libs\context\src\asm\make_i386_sysv_macho_gas.S 2017-08-19 09:49:40.000000000 -0700
+++ libs\context\src\asm\make_i386_sysv_macho_gas.S 2017-08-25 01:11:28.000000000 -0700
@@ -9,20 +9,20 @@
* *
* ---------------------------------------------------------------------------------- *
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
* ---------------------------------------------------------------------------------- *
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | *
* ---------------------------------------------------------------------------------- *
- * | fc_mxcsr|fc_x87_cw| EDI | ESI | EBX | EBP | EIP | hidden | *
+ * | fc_mxcsr|fc_x87_cw| EDI | ESI | EBX | EBP | EIP | to | *
* ---------------------------------------------------------------------------------- *
* ---------------------------------------------------------------------------------- *
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
* ---------------------------------------------------------------------------------- *
- * | 0x20 | 0x24 | | *
+ * | 0x20 | | *
* ---------------------------------------------------------------------------------- *
- * | to | data | | *
+ * | data | | *
* ---------------------------------------------------------------------------------- *
* *
****************************************************************************************/
.text
.globl _make_fcontext
@@ -36,28 +36,23 @@
leal -0x8(%eax), %eax
/* shift address in EAX to lower 16 byte boundary */
andl $-16, %eax
/* reserve space for context-data on context-stack */
- leal -0x28(%eax), %eax
+ leal -0x2c(%eax), %eax
/* third arg of make_fcontext() == address of context-function */
/* stored in EBX */
movl 0xc(%esp), %ecx
movl %ecx, 0x10(%eax)
/* save MMX control- and status-word */
stmxcsr (%eax)
/* save x87 control-word */
fnstcw 0x4(%eax)
-
- /* return transport_t */
- /* FCTX == EDI, DATA == ESI */
- leal 0x8(%eax), %ecx
- movl %ecx, 0x1c(%eax)
/* compute abs address of label trampoline */
call 1f
/* address of trampoline 1 */
1: popl %ecx
/* compute abs address of label trampoline */
@@ -77,19 +72,19 @@
movl %ecx, 0x14(%eax)
ret /* return pointer to context-data */
trampoline:
/* move transport_t for entering context-function */
- movl %edi, (%esp)
- movl %esi, 0x4(%esp)
+ movl %eax, (%esp)
+ movl %edx, 0x4(%esp)
pushl %ebp
/* jump to context-function */
jmp *%ebx
finish:
/* exit code is zero */
xorl %eax, %eax
movl %eax, (%esp)
/* exit application */
call __exit
hlt
--- libs\context\src\asm\ontop_i386_sysv_macho_gas.S 2017-08-19 09:49:40.000000000 -0700
+++ libs\context\src\asm\ontop_i386_sysv_macho_gas.S 2017-08-25 01:12:18.000000000 -0700
@@ -9,20 +9,20 @@
* *
* ---------------------------------------------------------------------------------- *
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
* ---------------------------------------------------------------------------------- *
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | *
* ---------------------------------------------------------------------------------- *
- * | fc_mxcsr|fc_x87_cw| EDI | ESI | EBX | EBP | EIP | hidden | *
+ * | fc_mxcsr|fc_x87_cw| EDI | ESI | EBX | EBP | EIP | to | *
* ---------------------------------------------------------------------------------- *
* ---------------------------------------------------------------------------------- *
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
* ---------------------------------------------------------------------------------- *
- * | 0x20 | 0x24 | | *
+ * | 0x20 | | *
* ---------------------------------------------------------------------------------- *
- * | to | data | | *
+ * | data | | *
* ---------------------------------------------------------------------------------- *
* *
****************************************************************************************/
.text
.globl _ontop_fcontext
@@ -41,35 +41,32 @@
movl %ebp, 0x14(%esp) /* save EBP */
/* store ESP (pointing to context-data) in ECX */
movl %esp, %ecx
/* first arg of ontop_fcontext() == fcontext to jump to */
- movl 0x20(%esp), %eax
+ movl 0x1c(%esp), %eax
/* pass parent fcontext_t */
- movl %ecx, 0x20(%eax)
+ movl %ecx, 0x1c(%eax)
/* second arg of ontop_fcontext() == data to be transferred */
- movl 0x24(%esp), %ecx
+ movl 0x20(%esp), %ecx
/* pass data */
- movl %ecx, 0x24(%eax)
+ movl %ecx, 0x20(%eax)
/* third arg of ontop_fcontext() == ontop-function */
- movl 0x28(%esp), %ecx
+ movl 0x24(%esp), %ecx
/* restore ESP (pointing to context-data) from EAX */
movl %eax, %esp
- /* address of returned transport_t */
- movl 0x1c(%esp), %eax
/* return parent fcontext_t */
- movl %ecx, (%eax)
- /* return data */
- movl %edx, 0x4(%eax)
+ movl %ecx, %eax
+ /* returned data is stored in EDX */
#if !defined(BOOST_USE_TSX)
ldmxcsr (%esp) /* restore MMX control- and status-word */
fldcw 0x4(%esp) /* restore x87 control-word */
#endif
--- libs\context\test\test_callcc.cpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\context\test\test_callcc.cpp 2017-08-28 20:16:32.000000000 -0700
@@ -249,12 +249,13 @@
}
return std::move( c);
});
c = c.resume_with(
[&i](ctx::continuation && c){
i -= 10;
+ return std::move( c);
});
BOOST_CHECK( c);
BOOST_CHECK_EQUAL( i, 200);
}
{
ctx::continuation c1;
@@ -263,12 +264,13 @@
BOOST_CHECK( ! c);
return std::move( c1);
});
c = c.resume_with(
[&c1](ctx::continuation && c){
c1 = std::move( c);
+ return std::move( c);
});
}
}
void test_ontop_exception() {
value1 = 0;
@@ -287,13 +289,14 @@
});
c = c.resume();
BOOST_CHECK_EQUAL( 3, value1);
const char * what = "hello world";
c.resume_with(
[what](ctx::continuation && c){
- throw my_exception( std::move( c), what);
+ throw my_exception( std::move( c), what);
+ return std::move( c);
});
BOOST_CHECK_EQUAL( 3, value1);
BOOST_CHECK_EQUAL( std::string( what), value2);
}
void test_termination() {
--- libs\date_time\test\gregorian\testdate.cpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\date_time\test\gregorian\testdate.cpp 2017-08-28 19:15:39.000000000 -0700
@@ -283,16 +283,16 @@
try{
date d(neg_infin);
tm d_tm = to_tm(d);
check("Exception not thrown (special_value to_tm)", false);
std::cout << d_tm.tm_sec << std::endl; //does nothing useful but stops compiler from complaining about unused d_tm
- }catch(std::out_of_range& e){
+ }catch(std::out_of_range&){
check("Caught expected exception (special_value to_tm)", true);
}catch(...){
check("Caught un-expected exception (special_value to_tm)", false);
}
return printTestStats();
}
--- libs\date_time\test\gregorian\testdate_input_facet.cpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\date_time\test\gregorian\testdate_input_facet.cpp 2017-08-28 19:11:27.000000000 -0700
@@ -477,13 +477,13 @@
// create a period_parser
period_parser p_parser; // default will do
// create date_generator_parser
typedef boost::date_time::date_generator_parser<date,char> date_gen_parser;
date_gen_parser dg_parser("Zuerst","Zweitens","Dritt","Viert",
- "Fünft","Letzt","Vor","Nach","Von");
+ "F\xC3\xBCnft","Letzt","Vor","Nach","Von");
// create the date_input_facet
date_input_facet* de_facet =
new date_input_facet("%B %d %Y",
d_parser,
sv_parser,
--- libs\date_time\test\gregorian\testgreg_durations.cpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\date_time\test\gregorian\testgreg_durations.cpp 2017-08-28 19:11:27.000000000 -0700
@@ -153,12 +153,30 @@
date d(2000, Feb, 29);
check("date - years", date(1994, Feb, 28) == d - years(6));
d -= years(6);
check("date -= years", date(1994, Feb, 28) == d);
}
+ try {
+ date d1(1400, 6, 1);
+ const date d2 = d1 + years(8600);
+ check("date + many years != overflow", d2 == date(10000, 6, 1));
+ }
+ catch (...) {
+ check("date + many years != overflow", false);
+ }
+
+ try {
+ date d1(10000, 6, 1);
+ const date d2 = d1 - years(8600);
+ check("date - many years != overflow", d2 == date(1400, 6, 1));
+ }
+ catch (...) {
+ check("date - many years != overflow", false);
+ }
+
}
/*** weeks ***/
// shouldn't need many tests, it is nothing more than a date_duration
// so all date_duration tests should prove this class
{
--- libs\date_time\test\gregorian\testparse_date.cpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\date_time\test\gregorian\testparse_date.cpp 2017-08-28 19:15:39.000000000 -0700
@@ -86,13 +86,13 @@
date d(not_a_date_time);
try {
d = date_from_iso_string(s);
check("Expected exception not thrown: from ISO string (bad_day_of_month)", false);
std::cout << date_from_iso_string(s) << std::endl;
}
- catch(bad_day_of_month& e) {
+ catch(bad_day_of_month&) {
check("Caught expected exception: bad_day_of_month ", true);
}
catch(...) {
check("Caught unexpected exception", false);
}
/* not currently passing due to a bug in boost::offset_separator (reported 2005-Aug-02)
@@ -342,12 +342,13 @@
try {
using namespace boost::gregorian;
std::string ud(""); //empty string error sf bug# 1155556
date d1(from_simple_string(ud));
check("empty string", false); //should never reach this piont
+ (void)d1;
}
catch(std::exception& e) {
check(std::string("empty string parse (exception expected): ") + e.what(), true);
}
--- libs\date_time\test\local_time\testlocal_time.cpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\date_time\test\local_time\testlocal_time.cpp 2017-08-28 19:15:39.000000000 -0700
@@ -287,13 +287,13 @@
try{
local_date_time ldt(not_a_date_time);
tm ldt_tm = to_tm(ldt);
check("Exception not thrown (special_value to_tm)", false);
//does nothing useful but stops compiler from complaining about unused ldt_tm
std::cout << ldt_tm.tm_sec << std::endl;
- }catch(std::out_of_range& e){
+ }catch(std::out_of_range&){
check("Caught expected exception (special_value to_tm)", true);
}catch(...){
check("Caught un-expected exception (special_value to_tm)", false);
}
// check that all are equal to sv_pt
check("local == utc", az_lt == utc_lt);
--- libs\date_time\test\local_time\testlocal_time_facet.cpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\date_time\test\local_time\testlocal_time_facet.cpp 2017-08-28 19:15:39.000000000 -0700
@@ -46,13 +46,13 @@
tz_database time_zones;
try {
// first try to find the data file from the test dir
time_zones.load_from_file("../data/date_time_zonespec.csv");
}
- catch(const data_not_accessible& e) {
+ catch(const data_not_accessible&) {
// couldn't find the data file so assume we are being run from
// boost_root/status and try again
try {
time_zones.load_from_file("../libs/date_time/data/date_time_zonespec.csv");
}
catch(const data_not_accessible&) {
--- libs\date_time\test\local_time\testposix_time_zone.cpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\date_time\test\local_time\testposix_time_zone.cpp 2017-08-28 19:15:39.000000000 -0700
@@ -197,13 +197,13 @@
// Mar-01 & Oct-31 Non-leap year, count begins at 0
spec = "FST+3FDT,59,304"; // "304" is not a mistake here, see posix_time_zone docs
posix_time_zone fl_2(spec);
try{
check("Non-Julian First/last of month", fl_2.dst_local_start_time(2003) ==
ptime(date(2003,Mar,1),hours(2)));
- }catch(std::exception& e){
+ }catch(std::exception&){
check("Expected exception caught for Non-Julian day of 59, in non-leap year (Feb-29)", true);
}
check("Non-Julian First/last of month", fl_2.dst_local_end_time(2003) ==
ptime(date(2003,Oct,31),hours(2)));
// Mar-01 & Oct-31 leap year, count begins at 0
--- libs\date_time\test\local_time\testtz_database.cpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\date_time\test\local_time\testtz_database.cpp 2017-08-28 19:15:39.000000000 -0700
@@ -29,13 +29,13 @@
* have all had full names added */
// run the exception tests first
try{
tz_database tz_db;
tz_db.load_from_file("missing_file.csv"); // file does not exist
- }catch(data_not_accessible& e){
+ }catch(data_not_accessible&){
check("Caught Missing data file exception", true);
}catch(...){
check("Caught first unexpected exception", false);
}
check("Caught Bad field count exception", run_bad_field_count_test());
@@ -49,13 +49,13 @@
* attempting to open it again but from a different location. If that
* also fails, we abort the test. */
tz_database tz_db;
try {
// first try to find the data file from the test dir
tz_db.load_from_file("../data/date_time_zonespec.csv");
- }catch(data_not_accessible& e) {
+ }catch(data_not_accessible&) {
// couldn't find the data file so assume we are being run from
// boost_root/status and try again
tz_db.load_from_file("../libs/date_time/data/date_time_zonespec.csv");
}catch(...) {
check("Cannot locate data file - aborting.", false);
return printTestStats();
@@ -118,21 +118,21 @@
{
using namespace boost::local_time;
bool caught_bfc = false;
tz_database other_db;
try{
other_db.load_from_file("local_time/poorly_formed_zonespec.csv");
- }catch(bad_field_count& be){
+ }catch(bad_field_count&){
caught_bfc = true;
}catch(...) {
// do nothing (file not found)
}
try{
other_db.load_from_file("../libs/date_time/test/local_time/poorly_formed_zonespec.csv");
- }catch(bad_field_count& be){
+ }catch(bad_field_count&){
caught_bfc = true;
}catch(...) {
// do nothing (file not found)
}
return caught_bfc;
}
--- libs\date_time\test\local_time\testwposix_time_zone.cpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\date_time\test\local_time\testwposix_time_zone.cpp 2017-08-28 19:15:39.000000000 -0700
@@ -200,13 +200,13 @@
// Mar-01 & Oct-31 Non-leap year, count begins at 0
spec = L"FST+3FDT,59,304"; // "304" is not a mistake here, see posix_time_zone docs
w_posix_time_zone fl_2(spec);
try{
check("Non-Julian First/last of month", fl_2.dst_local_start_time(2003) ==
ptime(date(2003,Mar,1),hours(2)));
- }catch(std::exception& e){
+ }catch(std::exception&){
check("Expected exception caught for Non-Julian day of 59, in non-leap year (Feb-29)", true);
}
check("Non-Julian First/last of month", fl_2.dst_local_end_time(2003) ==
ptime(date(2003,Oct,31),hours(2)));
// Mar-01 & Oct-31 leap year, count begins at 0
--- libs\date_time\test\posix_time\testfiletime_functions.cpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\date_time\test\posix_time\testfiletime_functions.cpp 2017-08-28 19:15:39.000000000 -0700
@@ -19,13 +19,13 @@
#if defined(BOOST_HAS_FTIME) // skip tests if no FILETIME
using namespace boost::posix_time;
// adjustor is used to truncate ptime's fractional seconds for
// comparison with SYSTEMTIME's milliseconds
- const int adjustor = time_duration::ticks_per_second() / 1000;
+ const time_duration::tick_type adjustor = time_duration::ticks_per_second() / 1000;
for(int i = 0; i < 5; ++i){
FILETIME ft;
SYSTEMTIME st;
GetSystemTime(&st);
--- libs\date_time\test\posix_time\testtime.cpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\date_time\test\posix_time\testtime.cpp 2017-08-28 19:15:39.000000000 -0700
@@ -306,13 +306,13 @@
try{
ptime pt(pos_infin);
tm pt_tm = to_tm(pt);
check("Exception not thrown (special_value to_tm)", false);
//following code does nothing useful but stops compiler from complaining about unused pt_tm
std::cout << pt_tm.tm_sec << std::endl;
- }catch(std::out_of_range& e){
+ }catch(std::out_of_range&){
check("Caught expected exception (special_value to_tm)", true);
}catch(...){
check("Caught un-expected exception (special_value to_tm)", false);
}
try{
// exception is only thrown from gregorian::to_tm. Needed to
@@ -320,17 +320,17 @@
ptime pt(date(2002,Oct,31), hours(1));
pt += time_duration(pos_infin);
tm pt_tm = to_tm(pt);
check("Exception not thrown (special_value to_tm)", false);
//following code does nothing useful but stops compiler from complaining about unused pt_tm
std::cout << pt_tm.tm_sec << std::endl;
- }catch(std::out_of_range& e){
+ }catch(std::out_of_range&){
check("Caught expected exception (special_value to_tm)", true);
}catch(...){
check("Caught un-expected exception (special_value to_tm)", false);
}
return printTestStats();
}
--- libs\date_time\test\testfrmwk.hpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\date_time\test\testfrmwk.hpp 2017-08-28 19:11:28.000000000 -0700
@@ -53,22 +53,46 @@
stat.addFailingTest();
std::cout << "FAIL :: " << testname << " " << std::endl;
return false;
}
}
+// In the comparisons below, it is possible that T and U are signed and unsigned integer types, which generates warnings in some compilers.
+#if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable: 4389)
+#elif defined(BOOST_CLANG) && defined(__has_warning)
+# if __has_warning("-Wsign-compare")
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wsign-compare"
+# endif
+#elif defined(BOOST_GCC) && (BOOST_GCC+0) >= 40600
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wsign-compare"
+#endif
+
template< typename T, typename U >
inline bool check_equal(const std::string& testname, T const& left, U const& right)
{
bool res = check(testname, left == right);
if (!res)
{
std::cout << " left = " << left << ", right = " << right << std::endl;
}
return res;
}
+
+#if defined(BOOST_MSVC)
+# pragma warning(pop)
+#elif defined(BOOST_CLANG) && defined(__has_warning)
+# if __has_warning("-Wsign-compare")
+# pragma clang diagnostic pop
+# endif
+#elif defined(BOOST_GCC) && (BOOST_GCC+0) >= 40600
+# pragma GCC diagnostic pop
+#endif
#ifndef BOOST_NO_STD_WSTRING
inline bool check_equal(const std::string& testname, std::wstring const& left, std::wstring const& right)
{
bool res = check(testname, left == right);
if (!res)
--- libs\fiber\src\context.cpp 2017-08-19 09:49:40.000000000 -0700
+++ libs\fiber\src\context.cpp 2017-08-25 00:59:05.000000000 -0700
@@ -142,12 +142,13 @@
// context_initializer::active_ will point to `this`
// prev will point to previous active context
std::swap( context_initializer::active_, prev);
// pass pointer to the context that resumes `this`
c_.resume_with([prev](boost::context::continuation && c){
prev->c_ = std::move( c);
+ return boost::context::continuation{};
});
}
void
context::resume( detail::spinlock_lock & lk) noexcept {
context * prev = this;
@@ -155,12 +156,13 @@
// prev will point to previous active context
std::swap( context_initializer::active_, prev);
// pass pointer to the context that resumes `this`
c_.resume_with([prev,&lk](boost::context::continuation && c){
prev->c_ = std::move( c);
lk.unlock();
+ return boost::context::continuation{};
});
}
void
context::resume( context * ready_ctx) noexcept {
context * prev = this;
@@ -168,12 +170,13 @@
// prev will point to previous active context
std::swap( context_initializer::active_, prev);
// pass pointer to the context that resumes `this`
c_.resume_with([prev,ready_ctx](boost::context::continuation && c){
prev->c_ = std::move( c);
context::active()->schedule( ready_ctx);
+ return boost::context::continuation{};
});
}
void
context::suspend() noexcept {
get_scheduler()->suspend();
@@ -215,12 +218,13 @@
// context_initializer::active_ will point to `this`
// prev will point to previous active context
std::swap( context_initializer::active_, prev);
// pass pointer to the context that resumes `this`
return c_.resume_with([prev](boost::context::continuation && c){
prev->c_ = std::move( c);
+ return boost::context::continuation{};
});
}
boost::context::continuation
context::terminate() noexcept {
// protect for concurrent access
--- libs\log\build\Jamfile.v2 2017-08-19 09:49:43.000000000 -0700
+++ libs\log\build\Jamfile.v2 2017-08-21 15:19:35.000000000 -0700
@@ -392,13 +392,13 @@
{
result = <cxxflags>"-xCORE-AVX2 -fabi-version=0" ;
}
}
else if <toolset>msvc in $(properties)
{
- result = <cxxflags>"/arch:AVX" ;
+ result = <cxxflags>"/arch:AVX2" ;
}
}
}
# if ! <build>no in $(result)
# {
--- libs\log\config\x86-ext\Jamfile.jam 2017-08-19 09:49:43.000000000 -0700
+++ libs\log\config\x86-ext\Jamfile.jam 2017-08-21 15:20:28.000000000 -0700
@@ -17,18 +17,19 @@
:
<toolset>gcc:<cxxflags>"-msse -msse2 -msse3 -mssse3"
<toolset>clang:<cxxflags>"-msse -msse2 -msse3 -mssse3"
<toolset>intel-linux:<cxxflags>"-xSSSE3"
<toolset>intel-darwin:<cxxflags>"-xSSSE3"
<toolset>intel-win:<cxxflags>"/QxSSSE3"
+ <toolset>msvc,<address-model>32:<cxxflags>"/arch:SSE2"
;
obj avx2 : avx2.cpp
:
<toolset>gcc:<cxxflags>"-mavx -mavx2 -fabi-version=0"
<toolset>clang:<cxxflags>"-mavx -mavx2"
<toolset>intel-linux:<cxxflags>"-xCORE-AVX2 -fabi-version=0"
<toolset>intel-darwin:<cxxflags>"-xCORE-AVX2 -fabi-version=0"
<toolset>intel-win:<cxxflags>"/arch:CORE-AVX2"
- <toolset>msvc:<cxxflags>"/arch:AVX"
+ <toolset>msvc:<cxxflags>"/arch:AVX2"
;
--- libs\math\build\Jamfile.v2 2017-08-19 09:49:43.000000000 -0700
+++ libs\math\build\Jamfile.v2 2017-08-21 15:20:55.000000000 -0700
@@ -9,13 +9,13 @@
project
: requirements
<toolset>intel-win:<cxxflags>-nologo
<toolset>intel-win:<linkflags>-nologo
#<toolset>intel-linux:<pch>off
<toolset>intel-darwin:<pch>off
- <toolset>msvc-7.1:<pch>off
+ <toolset>msvc:<pch>off
<toolset>gcc,<target-os>windows:<pch>off
#<toolset>gcc:<cxxflags>-fvisibility=hidden
<toolset>intel-linux:<cxxflags>-fvisibility=hidden
#<toolset>sun:<cxxflags>-xldscope=hidden
[ check-target-builds ../config//has_gcc_visibility "gcc visibility" : <toolset>gcc:<cxxflags>-fvisibility=hidden : ]
;
---
+++ libs\mp11\doc\article\docinfo-footer.html 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,6 @@
+<style>
+
+*:not(pre)>code { background: none; color: #600000; }
+/* table tr.even, table tr.alt, table tr:nth-of-type(even) { background: none; } */
+
+</style>
---
+++ libs\mp11\doc\article\simple_cxx11_metaprogramming.adoc 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,1218 @@
+////
+Copyright 2015-2017 Peter Dimov
+
+Distributed under the Boost Software License, Version 1.0.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+# Simple {cpp}11 metaprogramming
+Peter Dimov
+2015-05-26
+:toc: left
+:idprefix:
+:docinfo: shared-footer
+
+[.lead]
+__With variadic templates, parameter packs and template aliases__
+
+NOTE: I was motivated to write this after I read Eric Niebler's
+thought-provoking
+http://ericniebler.com/2014/11/13/tiny-metaprogramming-library/[Tiny
+Metaprogramming Library] article. Thanks Eric.
+
+## {cpp}11 changes the playing field
+
+The wide acceptance of http://www.boost.org/libs/mpl[Boost.MPL] made {cpp}
+metaprogramming seem a solved problem. Perhaps MPL wasn't ideal, but it was
+good enough to the point that there wasn't really a need to seek or produce
+alternatives.
+
+{cpp}11 changed the playing field. The addition of variadic templates with
+their associated parameter packs added a compile-time list of types structure
+directly into the language. Whereas before every metaprogramming library
+defined its own type list, and MPL defined several, in {cpp}11, type lists are
+as easy as
+```
+// C++11
+template<class... T> struct type_list {};
+```
+and there is hardly a reason to use anything else.
+
+Template aliases are another game changer. Previously, "metafunctions", that
+is, templates that took one type and produced another, looked like
+```
+// C++03
+template<class T> struct add_pointer { typedef T* type; };
+```
+and were used in the following manner:
+```
+// C++03
+typedef typename add_pointer<X>::type Xp;
+```
+In {cpp}11, metafunctions can be template aliases, instead of class templates:
+```
+// C++11
+template<class T> using add_pointer = T*;
+```
+The above example use then becomes
+```
+// C++11
+typedef add_pointer<X> Xp;
+```
+or, if you prefer to be seen as {cpp}11-savvy,
+```
+// C++11
+using Xp = add_pointer<X>;
+```
+This is a considerable improvement in more complex expressions:
+```
+// C++03
+typedef
+ typename add_reference<
+ typename add_const<
+ typename add_pointer<X>::type
+ >::type
+ >::type Xpcr;
+```
+```
+// C++11
+using Xpcr = add_reference<add_const<add_pointer<X>>>;
+```
+(The example also takes advantage of another {cpp}11 feature - you can now use
+`>>` to close templates without it being interpreted as a right shift.)
+
+In addition, template aliases can be passed to template template parameters:
+```
+// C++11
+template<template<class... T> class F> struct X
+{
+};
+
+X<add_pointer>; // works!
+```
+These language improvements allow for {cpp}11 metaprogramming that is
+substantially different than its idomatic {cpp}03 equivalent. Boost.MPL is no
+longer good enough, and __something must be done__. But what?
+
+## Type lists and mp_rename
+
+Let's start with the basics. Our basic data structure will be the type list:
+```
+template<class... T> struct mp_list {};
+```
+Why the `mp_` prefix? mp obviously stands for metaprogramming, but could we not
+have used a namespace?
+
+Indeed we could have. Past experience with Boost.MPL however indicates that
+name conflicts between our metaprogramming primitives and standard identifiers
+(such as `list`) and keywords (such as `if`, `int` or `true`) will be common
+and will be a source of problems. With a prefix, we avoid all that trouble.
+
+So we have our type list and can put things into it:
+```
+using list = mp_list<int, char, float, double, void>;
+```
+but can't do anything else with it yet. We'll need a library of primitives that
+operate on ``mp_list``s. But before we get into that, let's consider another
+interesting question first.
+
+Suppose we have our library of primitives that can do things with a `mp_list`,
+but some other code hands us a type list that is not an `mp_list`, such as for
+example an `std::tuple<int, float, void*>`, or
+``http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4115.html[std::packer]<int,
+float, void*>``.
+
+Suppose we need to modify this external list of types in some manner (change
+the types into pointers, perhaps) and give back the transformed result in the
+form it was given to us, `std::tuple<int*, float*, void$$**$$>` in the first
+case and `std::packer<int*, float*, void$$**$$>` in the second.
+
+To do that, we need to first convert `std::tuple<int, float, void*>` to
+`mp_list<int, float, void*>`, apply `add_pointer` to each element obtaining
+`mp_list<int*, float*, void$$**$$>`, then convert that back to `std::tuple`.
+
+These conversion steps are a quite common occurence, and we'll write a
+primitive that helps us perform them, called `mp_rename`. We want
+```
+mp_rename<std::tuple<int, float, void*>, mp_list>
+```
+to give us
+```
+mp_list<int, float, void*>
+```
+and conversely,
+```
+mp_rename<mp_list<int, float, void*>, std::tuple>
+```
+to give us
+```
+std::tuple<int, float, void*>
+```
+Here is the implementation of `mp_rename`:
+```
+template<class A, template<class...> class B> struct mp_rename_impl;
+
+template<template<class...> class A, class... T, template<class...> class B>
+ struct mp_rename_impl<A<T...>, B>
+{
+ using type = B<T...>;
+};
+
+template<class A, template<class...> class B>
+ using mp_rename = typename mp_rename_impl<A, B>::type;
+```
+(This pattern of a template alias forwarding to a class template doing the
+actual work is common; class templates can be specialized, whereas template
+aliases cannot.)
+
+Note that `mp_rename` does not treat any list type as special, not even
+`mp_list`; it can rename any variadic class template into any other. You could
+use it to rename `std::packer` to `std::tuple` to `std::variant` (once there is
+such a thing) and it will happily oblige.
+
+In fact, it can even rename non-variadic class templates, as in the following
+examples:
+```
+mp_rename<std::pair<int, float>, std::tuple> // -> std::tuple<int, float>
+mp_rename<mp_list<int, float>, std::pair> // -> std::pair<int, float>
+mp_rename<std::shared_ptr<int>, std::unique_ptr> // -> std::unique_ptr<int>
+```
+There is a limit to the magic; `unique_ptr` can't be renamed to `shared_ptr`:
+```
+mp_rename<std::unique_ptr<int>, std::shared_ptr> // error
+```
+because `unique_ptr<int>` is actually `unique_ptr<int,
+std::default_delete<int>>` and `mp_rename` renames it to `shared_ptr<int,
+std::default_delete<int>>`, which doesn't compile. But it still works in many
+more cases than one would naively expect at first.
+
+With conversions no longer a problem, let's move on to primitives and define a
+simple one, `mp_size`, for practice. We want `mp_size<mp_list<T$$...$$>>` to
+give us the number of elements in the list, that is, the value of the
+expression `sizeof$$...$$(T)`.
+```
+template<class L> struct mp_size_impl;
+
+template<class... T> struct mp_size_impl<mp_list<T...>>
+{
+ using type = std::integral_constant<std::size_t, sizeof...(T)>;
+};
+
+template<class L> using mp_size = typename mp_size_impl<L>::type;
+```
+This is relatively straightforward, except for the `std::integral_constant`.
+What is it and why do we need it?
+
+`std::integral_constant` is a standard {cpp}11 type that wraps an integral
+constant (that is, a compile-time constant integer value) into a type.
+
+Since metaprogramming operates on type lists, which can only hold types, it's
+convenient to represent compile-time constants as types. This allows us to
+treat lists of types and lists of values in a uniform manner. It is therefore
+idiomatic in metaprogramming to take and return types instead of values, and
+this is what we have done. If at some later point we want the actual value, we
+can use the expression `mp_size<L>::value` to retrieve it.
+
+We now have our `mp_size`, but you may have noticed that there's an interesting
+difference between `mp_size` and `mp_rename`. Whereas I made a point of
+`mp_rename` not treating `mp_list` as a special case, `mp_size` very much does:
+```
+template<class... T> struct mp_size_impl<mp_list<T...>>
+```
+Is this really necessary? Can we not use the same technique in the
+implementation of `mp_size` as we did in mp_rename?
+```
+template<class L> struct mp_size_impl;
+
+template<template<class...> class L, class... T> struct mp_size_impl<L<T...>>
+{
+ using type = std::integral_constant<std::size_t, sizeof...(T)>;
+};
+
+template<class L> using mp_size = typename mp_size_impl<L>::type;
+```
+Yes, we very much can, and this improvement allows us to use `mp_size` on any
+other type lists, such as `std::tuple`. It turns `mp_size` into a truly generic
+primitive.
+
+This is nice. It is so nice that I'd argue that all our metaprogramming
+primitives ought to have this property. If someone hands us a type list in the
+form of an `std::tuple`, we should be able to operate on it directly, avoiding
+the conversions to and from `mp_list`.
+
+So do we no longer have any need for `mp_rename`? Not quite. Apart from the
+fact that sometimes we really do need to rename type lists, there is another
+surprising task for which `mp_rename` is useful.
+
+To illustrate it, let me introduce the primitive `mp_length`. It's similar to
+`mp_size`, but while `mp_size` takes a type list as an argument, `mp_length`
+takes a variadic parameter pack and returns its length; or, stated differently,
+it returns its number of arguments:
+```
+template<class... T> using mp_length = std::integral_constant<std::size_t, sizeof...(T)>;
+```
+How would we implement `mp_size` in terms of `mp_length`? One option is to just
+substitute the implementation of the latter into the former:
+```
+template<template<class...> class L, class... T> struct mp_size_impl<L<T...>>
+{
+ using type = mp_length<T...>;
+};
+```
+but there is another way, much less mundane. Think about what `mp_size` does.
+It takes the argument
+[subs=+quotes]
+```
+**mp_list**<int, void, float>
+```
+and returns
+[subs=+quotes]
+```
+**mp_length**<int, void, float>
+```
+Do we already have a primitive that does a similar thing?
+
+(Not much of a choice, is there?)
+
+Indeed we have, and it's called `mp_rename`.
+```
+template<class L> using mp_size = mp_rename<L, mp_length>;
+```
+I don't know about you, but I find this technique fascinating. It exploits the
+structural similarity between a list, `L<T$$...$$>`, and a metafunction "call",
+`F<T$$...$$>`, and the fact that the language sees the things the same way and
+allows us to pass the template alias `mp_length` to `mp_rename` as if it were
+an ordinary class template such as `mp_list`.
+
+(Other metaprogramming libraries provide a dedicated `apply` primitive for
+this job. `apply<F, L>` calls the metafunction `F` with the contents of the
+list `L`. We'll add an alias `mp_apply<F, L>` that calls `mp_rename<L, F>` for
+readability.)
+```
+template<template<class...> class F, class L> using mp_apply = mp_rename<L, F>;
+```
+
+## mp_transform
+
+Let's revisit the example I gave earlier - someone hands us `std::tuple<X, Y,
+Z>` and we need to compute `std::tuple<X*, Y*, Z*>`. We already have
+`add_pointer`:
+```
+template<class T> using add_pointer = T*;
+```
+so we just need to apply it to each element of the input tuple.
+
+The algorithm that takes a function and a list and applies the function to each
+element is called `transform` in Boost.MPL and the STL and `map` in functional
+languages. We'll use `transform`, for consistency with the established {cpp}
+practice (`map` is a data structure in both the STL and Boost.MPL.)
+
+We'll call our algorithm `mp_transform`, and `mp_transform<F, L>` will apply
+`F` to each element of `L` and return the result. Usually, the argument order
+is reversed and the function comes last. Our reasons to put it at the front
+will become evident later.
+
+There are many ways to implement `mp_transform`; the one we'll pick will make
+use of another primitive, `mp_push_front`. `mp_push_front<L, T>`, as its name
+implies, adds `T` as a first element in `L`:
+```
+template<class L, class T> struct mp_push_front_impl;
+
+template<template<class...> class L, class... U, class T>
+ struct mp_push_front_impl<L<U...>, T>
+{
+ using type = L<T, U...>;
+};
+
+template<class L, class T>
+ using mp_push_front = typename mp_push_front_impl<L, T>::type;
+```
+There is no reason to constrain `mp_push_front` to a single element though. In
+{cpp}11, variadic templates should be our default choice, and the
+implementation of `mp_push_front` that can take an arbitrary number of elements
+is almost identical:
+```
+template<class L, class... T> struct mp_push_front_impl;
+
+template<template<class...> class L, class... U, class... T>
+ struct mp_push_front_impl<L<U...>, T...>
+{
+ using type = L<T..., U...>;
+};
+
+template<class L, class... T>
+ using mp_push_front = typename mp_push_front_impl<L, T...>::type;
+```
+On to `mp_transform`:
+```
+template<template<class...> class F, class L> struct mp_transform_impl;
+
+template<template<class...> class F, class L>
+ using mp_transform = typename mp_transform_impl<F, L>::type;
+
+template<template<class...> class F, template<class...> class L>
+ struct mp_transform_impl<F, L<>>
+{
+ using type = L<>;
+};
+
+template<template<class...> class F, template<class...> class L, class T1, class... T>
+ struct mp_transform_impl<F, L<T1, T...>>
+{
+ using _first = F<T1>;
+ using _rest = mp_transform<F, L<T...>>;
+
+ using type = mp_push_front<_rest, _first>;
+};
+```
+This is a straightforward recursive implementation that should be familiar to
+people with functional programming background.
+
+Can we do better? It turns out that in {cpp}11, we can.
+```
+template<template<class...> class F, class L> struct mp_transform_impl;
+
+template<template<class...> class F, class L>
+ using mp_transform = typename mp_transform_impl<F, L>::type;
+
+template<template<class...> class F, template<class...> class L, class... T>
+ struct mp_transform_impl<F, L<T...>>
+{
+ using type = L<F<T>...>;
+};
+```
+Here we take advantage of the fact that pack expansion is built into the
+language, so the `F<T>$$...$$` part does all the iteration work for us.
+
+We can now solve our original challenge: given an `std::tuple` of types, return
+an `std::tuple` of pointers to these types:
+```
+using input = std::tuple<int, void, float>;
+using expected = std::tuple<int*, void*, float*>;
+
+using result = mp_transform<add_pointer, input>;
+
+static_assert( std::is_same<result, expected>::value, "" );
+```
+
+## mp_transform, part two
+
+What if we had a pair of tuples as input, and had to produce the corresponding
+tuple of pairs? For example, given
+```
+using input = std::pair<std::tuple<X1, X2, X3>, std::tuple<Y1, Y2, Y3>>;
+```
+we had to produce
+```
+using expected = std::tuple<std::pair<X1, Y1>, std::pair<X2, Y2>, std::pair<X3, Y3>>;
+```
+We need to take the two lists, represented by tuples in the input, and combine
+them pairwise by using `std::pair`. If we think of `std::pair` as a function
+`F`, this task appears very similar to `mp_transform`, except we need to use a
+binary function and two lists.
+
+Changing our unary transform algorithm into a binary one isn't hard:
+```
+template<template<class...> class F, class L1, class L2>
+ struct mp_transform2_impl;
+
+template<template<class...> class F, class L1, class L2>
+ using mp_transform2 = typename mp_transform2_impl<F, L1, L2>::type;
+
+template<template<class...> class F,
+ template<class...> class L1, class... T1,
+ template<class...> class L2, class... T2>
+ struct mp_transform2_impl<F, L1<T1...>, L2<T2...>>
+{
+ static_assert( sizeof...(T1) == sizeof...(T2),
+ "The arguments of mp_transform2 should be of the same size" );
+
+ using type = L1<F<T1,T2>...>;
+};
+```
+and we can now do
+```
+using input = std::pair<std::tuple<X1, X2, X3>, std::tuple<Y1, Y2, Y3>>;
+using expected = std::tuple<std::pair<X1, Y1>, std::pair<X2, Y2>, std::pair<X3, Y3>>;
+
+using result = mp_transform2<std::pair, input::first_type, input::second_type>;
+
+static_assert( std::is_same<result, expected>::value, "" );
+```
+again exploiting the similarity between metafunctions and ordinary class
+templates such as `std::pair`, this time in the other direction; we pass
+`std::pair` where `mp_transform2` expects a metafunction.
+
+Do we _have_ to use separate transform algorithms for each arity though? If we
+need a transform algorithm that takes a ternary function and three lists,
+should we name it `mp_transform3`? No, this is exactly why we put the function
+first. We just have to change `mp_transform` to be variadic:
+```
+template<template<class...> class F, class... L> struct mp_transform_impl;
+
+template<template<class...> class F, class... L>
+ using mp_transform = typename mp_transform_impl<F, L...>::type;
+```
+and then add the unary and binary specializations:
+```
+template<template<class...> class F, template<class...> class L, class... T>
+ struct mp_transform_impl<F, L<T...>>
+{
+ using type = L<F<T>...>;
+};
+
+template<template<class...> class F,
+ template<class...> class L1, class... T1,
+ template<class...> class L2, class... T2>
+ struct mp_transform_impl<F, L1<T1...>, L2<T2...>>
+{
+ static_assert( sizeof...(T1) == sizeof...(T2),
+ "The arguments of mp_transform should be of the same size" );
+
+ using type = L1<F<T1,T2>...>;
+};
+```
+We can also add ternary and further specializations.
+
+Is it possible to implement the truly variadic `mp_transform`, one that works
+with an arbitrary number of lists? It is in principle, and I'll show one
+possible abridged implementation here for completeness:
+```
+template<template<class...> class F, class E, class... L>
+ struct mp_transform_impl;
+
+template<template<class...> class F, class... L>
+ using mp_transform = typename mp_transform_impl<F, mp_empty<L...>, L...>::type;
+
+template<template<class...> class F, class L1, class... L>
+ struct mp_transform_impl<F, mp_true, L1, L...>
+{
+ using type = mp_clear<L1>;
+};
+
+template<template<class...> class F, class... L>
+ struct mp_transform_impl<F, mp_false, L...>
+{
+ using _first = F< typename mp_front_impl<L>::type... >;
+ using _rest = mp_transform< F, typename mp_pop_front_impl<L>::type... >;
+
+ using type = mp_push_front<_rest, _first>;
+};
+```
+but will omit the primitives that it uses. These are
+
+* `mp_true` -- an alias for `std::integral_constant<bool, true>`.
+* `mp_false` -- an alias for `std::integral_constant<bool, false>`.
+* `mp_empty<L$$...$$>` -- returns `mp_true` if all lists are empty, `mp_false`
+ otherwise.
+* `mp_clear<L>` -- returns an empty list of the same type as `L`.
+* `mp_front<L>` -- returns the first element of `L`.
+* `mp_pop_front<L>` -- returns `L` without its first element.
+
+There is one interesting difference between the recursive `mp_transform`
+implementation and the language-based one. `mp_transform<add_pointer,
+std::pair<int, float>>` works with the `F<T>$$...$$` implementation and fails
+with the recursive one, because `std::pair` is not a real type list and can
+only hold exactly two types.
+
+## The infamous tuple_cat challenge
+
+Eric Niebler, in his
+http://ericniebler.com/2014/11/13/tiny-metaprogramming-library/[Tiny
+Metaprogramming Library] article, gives the function
+http://en.cppreference.com/w/cpp/utility/tuple/tuple_cat[`std::tuple_cat`] as a
+kind of a metaprogramming challenge. `tuple_cat` is a variadic template
+function that takes a number of tuples and concatenates them into another
+`std::tuple`. This is Eric's solution:
+```
+namespace detail
+{
+ template<typename Ret, typename...Is, typename ...Ks,
+ typename Tuples>
+ Ret tuple_cat_(typelist<Is...>, typelist<Ks...>,
+ Tuples tpls)
+ {
+ return Ret{std::get<Ks::value>(
+ std::get<Is::value>(tpls))...};
+ }
+}
+
+template<typename...Tuples,
+ typename Res =
+ typelist_apply_t<
+ meta_quote<std::tuple>,
+ typelist_cat_t<typelist<as_typelist_t<Tuples>...> > > >
+Res tuple_cat(Tuples &&... tpls)
+{
+ static constexpr std::size_t N = sizeof...(Tuples);
+ // E.g. [0,0,0,2,2,2,3,3]
+ using inner =
+ typelist_cat_t<
+ typelist_transform_t<
+ typelist<as_typelist_t<Tuples>...>,
+ typelist_transform_t<
+ as_typelist_t<make_index_sequence<N> >,
+ meta_quote<meta_always> >,
+ meta_quote<typelist_transform_t> > >;
+ // E.g. [0,1,2,0,1,2,0,1]
+ using outer =
+ typelist_cat_t<
+ typelist_transform_t<
+ typelist<as_typelist_t<Tuples>...>,
+ meta_compose<
+ meta_quote<as_typelist_t>,
+ meta_quote_i<std::size_t, make_index_sequence>,
+ meta_quote<typelist_size_t> > > >;
+ return detail::tuple_cat_<Res>(
+ inner{},
+ outer{},
+ std::forward_as_tuple(std::forward<Tuples>(tpls)...));
+}
+```
+All right, challenge accepted. Let's see what we can do.
+
+As Eric explains, this implementation relies on the clever trick of packing the
+input tuples into a tuple, creating two arrays of indices, `inner` and `outer`,
+then indexing the outer tuple with the outer indices and the result, which is
+one of our input tuples, with the inner indices.
+
+So, for example, if tuple_cat is invoked as
+```
+std::tuple<int, short, long> t1;
+std::tuple<> t2;
+std::tuple<float, double, long double> t3;
+std::tuple<void*, char*> t4;
+
+auto res = tuple_cat(t1, t2, t3, t4);
+```
+we'll create the tuple
+```
+std::tuple<std::tuple<int, short, long>, std::tuple<>,
+ std::tuple<float, double, long double>, std::tuple<void*, char*>> t{t1, t2, t3, t4};
+```
+and then extract the elements of t via
+```
+std::get<0>(std::get<0>(t)), // t1[0]
+std::get<1>(std::get<0>(t)), // t1[1]
+std::get<2>(std::get<0>(t)), // t1[2]
+std::get<0>(std::get<2>(t)), // t3[0]
+std::get<1>(std::get<2>(t)), // t3[1]
+std::get<2>(std::get<2>(t)), // t3[2]
+std::get<0>(std::get<3>(t)), // t4[0]
+std::get<1>(std::get<3>(t)), // t4[1]
+```
+(`t2` is empty, so we take nothing from it.)
+
+The first column of integers is the `outer` array, the second one - the `inner`
+array, and these are what we need to compute. But first, let's deal with the
+return type of `tuple_cat`.
+
+The return type of `tuple_cat` is just the concatenation of the arguments,
+viewed as type lists. The metaprogramming algorithm that concatenates lists is
+called
+https://ericniebler.github.io/meta/group__transformation.html[`meta::concat`]
+in Eric Niebler's https://github.com/ericniebler/meta[Meta] library, but I'll
+call it `mp_append`, after its classic Lisp name.
+
+(Lisp is today's equivalent of Latin. Educated people are supposed to have
+studied and forgotten it.)
+```
+template<class... L> struct mp_append_impl;
+
+template<class... L> using mp_append = typename mp_append_impl<L...>::type;
+
+template<> struct mp_append_impl<>
+{
+ using type = mp_list<>;
+};
+
+template<template<class...> class L, class... T> struct mp_append_impl<L<T...>>
+{
+ using type = L<T...>;
+};
+
+template<template<class...> class L1, class... T1,
+ template<class...> class L2, class... T2, class... Lr>
+ struct mp_append_impl<L1<T1...>, L2<T2...>, Lr...>
+{
+ using type = mp_append<L1<T1..., T2...>, Lr...>;
+};
+```
+That was fairly easy. There are other ways to implement `mp_append`, but this
+one demonstrates how the language does most of the work for us via pack
+expansion. This is a common theme in {cpp}11.
+
+Note how `mp_append` returns the same list type as its first argument. Of
+course, in the case in which no arguments are given, there is no first argument
+from which to take the type, so I've arbitrarily chosen to return an empty
+`mp_list`.
+
+We're now ready with the declaration of `tuple_cat`:
+```
+template<class... Tp,
+ class R = mp_append<typename std::remove_reference<Tp>::type...>>
+ R tuple_cat( Tp &&... tp );
+```
+The reason we need `remove_reference` is because of the rvalue reference
+parameters, used to implement perfect forwarding. If the argument is an lvalue,
+such as for example `t1` above, its corresponding type will be a reference to a
+tuple -- `std::tuple<int, short, long>&` in ``t1``'s case. Our primitives do
+not recognize references to tuples as type lists, so we need to strip them off.
+
+There are two problems with our return type computation though. One, what if
+`tuple_cat` is called without any arguments? We return `mp_list<>` in that
+case, but the correct result is `std::tuple<>`.
+
+Two, what if we call `tuple_cat` with a first argument that is a `std::pair`?
+We'll try to append more elements to `std::pair`, and it will fail.
+
+We can solve both our problems by using an empty tuple as the first argument to
+`mp_append`:
+```
+template<class... Tp,
+ class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>>
+ R tuple_cat( Tp &&... tp );
+```
+With the return type taken care of, let's now move on to computing inner. We
+have
+```
+[x1, x2, x3], [], [y1, y2, y3], [z1, z2]
+```
+as input and we need to output
+```
+[0, 0, 0, 2, 2, 2, 3, 3]
+```
+which is the concatenation of
+```
+[0, 0, 0], [], [2, 2, 2], [3, 3]
+```
+Here each tuple is the same size as the input, but is filled with a constant
+that represents its index in the argument list. The first tuple is filled with
+0, the second with 1, the third with 2, and so on.
+
+We can achieve this result if we first compute a list of indices, in our case
+`[0, 1, 2, 3]`, then use binary `mp_transform` on the two lists
+```
+[[x1, x2, x3], [], [y1, y2, y3], [z1, z2]]
+[0, 1, 2, 3]
+```
+and a function which takes a list and an integer (in the form of an
+`std::integral_constant`) and returns a list that is the same size as the
+original, but filled with the second argument.
+
+We'll call this function `mp_fill`, after `std::fill`.
+
+Functional programmers will immediately realize that `mp_fill` is
+`mp_transform` with a function that returns a constant, and here's an
+implementation along these lines:
+```
+template<class V> struct mp_constant
+{
+ template<class...> using apply = V;
+};
+
+template<class L, class V>
+ using mp_fill = mp_transform<mp_constant<V>::template apply, L>;
+```
+Here's an alternate implementation:
+```
+template<class L, class V> struct mp_fill_impl;
+
+template<template<class...> class L, class... T, class V>
+ struct mp_fill_impl<L<T...>, V>
+{
+ template<class...> using _fv = V;
+ using type = L<_fv<T>...>;
+};
+
+template<class L, class V> using mp_fill = typename mp_fill_impl<L, V>::type;
+```
+These demonstrate different styles and choosing one over the other is largely a
+matter of taste here. In the first case, we combine existing primitives; in the
+second case, we "inline" `mp_const` and even `mp_transform` in the body of
+`mp_fill_impl`.
+
+Most {cpp}11 programmers will probably find the second implementation easier to
+read.
+
+We can now `mp_fill`, but we still need the `[0, 1, 2, 3]` index sequence. We
+could write an algorithm `mp_iota` for that (named after
+http://en.cppreference.com/w/cpp/algorithm/iota[`std::iota`]), but it so
+happens that {cpp}14 already has a standard way of generating an index
+sequence, called
+http://en.cppreference.com/w/cpp/utility/integer_sequence[`std::make_index_sequence`].
+Since Eric's original solution makes use of `make_index_sequence`, let's follow
+his lead.
+
+Technically, this takes us outside of {cpp}11, but `make_index_sequence` is not
+hard to implement (if efficiency is not a concern):
+```
+template<class T, T... Ints> struct integer_sequence
+{
+};
+
+template<class S> struct next_integer_sequence;
+
+template<class T, T... Ints> struct next_integer_sequence<integer_sequence<T, Ints...>>
+{
+ using type = integer_sequence<T, Ints..., sizeof...(Ints)>;
+};
+
+template<class T, T I, T N> struct make_int_seq_impl;
+
+template<class T, T N>
+ using make_integer_sequence = typename make_int_seq_impl<T, 0, N>::type;
+
+template<class T, T I, T N> struct make_int_seq_impl
+{
+ using type = typename next_integer_sequence<
+ typename make_int_seq_impl<T, I+1, N>::type>::type;
+};
+
+template<class T, T N> struct make_int_seq_impl<T, N, N>
+{
+ using type = integer_sequence<T>;
+};
+
+template<std::size_t... Ints>
+ using index_sequence = integer_sequence<std::size_t, Ints...>;
+
+template<std::size_t N>
+ using make_index_sequence = make_integer_sequence<std::size_t, N>;
+```
+We can now obtain an `index_sequence<0, 1, 2, 3>`:
+```
+template<class... Tp,
+ class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>>
+ R tuple_cat( Tp &&... tp )
+{
+ std::size_t const N = sizeof...(Tp);
+
+ // inner
+
+ using seq = make_index_sequence<N>;
+}
+```
+but `make_index_sequence<4>` returns `integer_sequence<std::size_t, 0, 1, 2,
+3>`, which is not a type list. In order to work with it, we need to convert it
+to a type list, so we'll introduce a function `mp_from_sequence` that does
+that.
+```
+template<class S> struct mp_from_sequence_impl;
+
+template<template<class T, T... I> class S, class U, U... J>
+ struct mp_from_sequence_impl<S<U, J...>>
+{
+ using type = mp_list<std::integral_constant<U, J>...>;
+};
+
+template<class S> using mp_from_sequence = typename mp_from_sequence_impl<S>::type;
+```
+We can now compute the two lists that we wanted to transform with `mp_fill`:
+```
+template<class... Tp,
+ class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>>
+ R tuple_cat( Tp &&... tp )
+{
+ std::size_t const N = sizeof...(Tp);
+
+ // inner
+
+ using list1 = mp_list<typename std::remove_reference<Tp>::type...>;
+ using list2 = mp_from_sequence<make_index_sequence<N>>;
+
+ // list1: [[x1, x2, x3], [], [y1, y2, y3], [z1, z2]]
+ // list2: [0, 1, 2, 3]
+
+ return R{};
+}
+```
+and finish the job of computing `inner`:
+```
+template<class... Tp,
+ class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>>
+ R tuple_cat( Tp &&... tp )
+{
+ std::size_t const N = sizeof...(Tp);
+
+ // inner
+
+ using list1 = mp_list<typename std::remove_reference<Tp>::type...>;
+ using list2 = mp_from_sequence<make_index_sequence<N>>;
+
+ // list1: [[x1, x2, x3], [], [y1, y2, y3], [z1, z2]]
+ // list2: [0, 1, 2, 3]
+
+ using list3 = mp_transform<mp_fill, list1, list2>;
+
+ // list3: [[0, 0, 0], [], [2, 2, 2], [3, 3]]
+
+ using inner = mp_rename<list3, mp_append>; // or mp_apply<mp_append, list3>
+
+ // inner: [0, 0, 0, 2, 2, 2, 3, 3]
+
+ return R{};
+}
+```
+For `outer`, we again have
+```
+[x1, x2, x3], [], [y1, y2, y3], [z1, z2]
+```
+as input and we need to output
+```
+[0, 1, 2, 0, 1, 2, 0, 1]
+```
+which is the concatenation of
+```
+[0, 1, 2], [], [0, 1, 2], [0, 1]
+```
+The difference here is that instead of filling the tuple with a constant value,
+we need to fill it with increasing values, starting from 0, that is, with the
+result of `make_index_sequence<N>`, where `N` is the number of elements.
+
+The straightforward way to do that is to just define a metafunction `F` that
+does what we want, then use `mp_transform` to apply it to the input:
+```
+template<class N> using mp_iota = mp_from_sequence<make_index_sequence<N::value>>;
+
+template<class L> using F = mp_iota<mp_size<L>>;
+
+template<class... Tp,
+ class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>>
+ R tuple_cat( Tp &&... tp )
+{
+ std::size_t const N = sizeof...(Tp);
+
+ // outer
+
+ using list1 = mp_list<typename std::remove_reference<Tp>::type...>;
+ using list2 = mp_transform<F, list1>;
+
+ // list2: [[0, 1, 2], [], [0, 1, 2], [0, 1]]
+
+ using outer = mp_rename<list2, mp_append>;
+
+ // outer: [0, 1, 2, 0, 1, 2, 0, 1]
+
+ return R{};
+}
+```
+Well that was easy. Surprisingly easy. The one small annoyance is that we can't
+define `F` inside `tuple_cat` - templates can't be defined in functions.
+
+Let's put everything together.
+```
+template<class N> using mp_iota = mp_from_sequence<make_index_sequence<N::value>>;
+
+template<class L> using F = mp_iota<mp_size<L>>;
+
+template<class R, class...Is, class... Ks, class Tp>
+R tuple_cat_( mp_list<Is...>, mp_list<Ks...>, Tp tp )
+{
+ return R{ std::get<Ks::value>(std::get<Is::value>(tp))... };
+}
+
+template<class... Tp,
+ class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>>
+ R tuple_cat( Tp &&... tp )
+{
+ std::size_t const N = sizeof...(Tp);
+
+ // inner
+
+ using list1 = mp_list<typename std::remove_reference<Tp>::type...>;
+ using list2 = mp_from_sequence<make_index_sequence<N>>;
+
+ // list1: [[x1, x2, x3], [], [y1, y2, y3], [z1, z2]]
+ // list2: [0, 1, 2, 3]
+
+ using list3 = mp_transform<mp_fill, list1, list2>;
+
+ // list3: [[0, 0, 0], [], [2, 2, 2], [3, 3]]
+
+ using inner = mp_rename<list3, mp_append>; // or mp_apply<mp_append, list3>
+
+ // inner: [0, 0, 0, 2, 2, 2, 3, 3]
+
+ // outer
+
+ using list4 = mp_transform<F, list1>;
+
+ // list4: [[0, 1, 2], [], [0, 1, 2], [0, 1]]
+
+ using outer = mp_rename<list4, mp_append>;
+
+ // outer: [0, 1, 2, 0, 1, 2, 0, 1]
+
+ return tuple_cat_<R>( inner(), outer(),
+ std::forward_as_tuple( std::forward<Tp>(tp)... ) );
+}
+```
+This almost compiles, except that our `inner` happens to be a `std::tuple`, but
+our helper function expects an `mp_list`. (`outer` is already an `mp_list`, by
+sheer luck.) We can fix that easily enough.
+```
+return tuple_cat_<R>( mp_rename<inner, mp_list>(), outer(),
+ std::forward_as_tuple( std::forward<Tp>(tp)... ) );
+```
+Let's define a `print_tuple` function and see if everything checks out.
+```
+template<int I, int N, class... T> struct print_tuple_
+{
+ void operator()( std::tuple<T...> const & tp ) const
+ {
+ using Tp = typename std::tuple_element<I, std::tuple<T...>>::type;
+
+ print_type<Tp>( " ", ": " );
+
+ std::cout << std::get<I>( tp ) << ";";
+
+ print_tuple_< I+1, N, T... >()( tp );
+ }
+};
+
+template<int N, class... T> struct print_tuple_<N, N, T...>
+{
+ void operator()( std::tuple<T...> const & ) const
+ {
+ }
+};
+
+template<class... T> void print_tuple( std::tuple<T...> const & tp )
+{
+ std::cout << "{";
+ print_tuple_<0, sizeof...(T), T...>()( tp );
+ std::cout << " }\n";
+}
+
+int main()
+{
+ std::tuple<int, long> t1{ 1, 2 };
+ std::tuple<> t2;
+ std::tuple<float, double, long double> t3{ 3, 4, 5 };
+ std::pair<void const*, char const*> t4{ "pv", "test" };
+
+ using expected = std::tuple<int, long, float, double, long double,
+ void const*, char const*>;
+
+ auto result = ::tuple_cat( t1, t2, t3, t4 );
+
+ static_assert( std::is_same<decltype(result), expected>::value, "" );
+
+ print_tuple( result );
+}
+```
+Output:
+```
+{ int: 1; long: 2; float: 3; double: 4; long double: 5; void const*: 0x407086;
+ char const*: test; }
+```
+Seems to work. But there's at least one error left. To see why, replace the
+first tuple
+```
+std::tuple<int, long> t1{ 1, 2 };
+```
+with a pair:
+```
+std::pair<int, long> t1{ 1, 2 };
+```
+We now get an error at
+```
+using inner = mp_rename<list3, mp_append>;
+```
+because the first element of `list3` is an `std::pair`, which `mp_append` tries
+and fails to use as its return type.
+
+There are two ways to fix that. The first one is to apply the same trick we
+used for the return type, and insert an empty `mp_list` at the front of
+`list3`, which `mp_append` will use as a return type:
+```
+using inner = mp_rename<mp_push_front<list3, mp_list<>>, mp_append>;
+```
+The second way is to just convert all inputs to mp_list:
+```
+using list1 = mp_list<
+ mp_rename<typename std::remove_reference<Tp>::type, mp_list>...>;
+```
+In both cases, inner will now be an `mp_list`, so we can omit the `mp_rename`
+in the call to `tuple_cat_`.
+
+We're done. The results hopefully speak for themselves.
+
+## Higher order metaprogramming, or lack thereof
+
+Perhaps by now you're wondering why this article is called "Simple {cpp}11
+metaprogramming", since what we covered so far wasn't particularly simple.
+
+The _relative_ simplicity of our approach stems from the fact that we've not
+been doing any higher order metaprogramming, that is, we haven't introduced any
+primitives that return metafunctions, such as `compose`, `bind`, or a lambda
+library.
+
+I posit that such higher order metaprogramming is, in the majority of cases,
+not necessary in {cpp}11. Consider, for example, Eric Niebler's solution given
+above:
+```
+using outer =
+ typelist_cat_t<
+ typelist_transform_t<
+ typelist<as_typelist_t<Tuples>...>,
+ meta_compose<
+ meta_quote<as_typelist_t>,
+ meta_quote_i<std::size_t, make_index_sequence>,
+ meta_quote<typelist_size_t> > > >;
+```
+The `meta_compose` expression takes three other ("quoted") metafunctions and
+creates a new metafunction that applies them in order. Eric uses this example
+as motivation to introduce the concept of a "metafunction class" and then to
+supply various primitives that operate on metafunction classes.
+
+But when we have metafunctions `F`, `G` and `H`, instead of using
+`meta_compose`, in {cpp}11 we can just do
+```
+template<class... T> using Fgh = F<G<H<T...>>>;
+```
+and that's it. The language makes defining composite functions easy, and there
+is no need for library support. If the functions to be composed are
+`as_typelist_t`, `std::make_index_sequence` and `typelist_size_t`, we just
+define
+```
+template<class... T>
+ using F = as_typelist_t<std::make_index_sequence<typelist_size_t<T...>::value>>;
+```
+Similarly, if we need a metafunction that will return `sizeof(T) < sizeof(U)`,
+there is no need to enlist a metaprogramming lambda library as in
+```
+lambda<_a, _b, less<sizeof_<_a>, sizeof_<_b>>>>
+```
+We could just define it inline:
+```
+template<class T, class U> using sizeof_less = mp_bool<(sizeof(T) < sizeof(U))>;
+```
+
+## One more thing
+
+Finally, let me show the implementations of `mp_count` and `mp_count_if`, for
+no reason other than I find them interesting. `mp_count<L, V>` returns the
+number of occurences of the type `V` in the list `L`; `mp_count_if<L, P>`
+counts the number of types in `L` for which `P<T>` is `true`.
+
+As a first step, I'll implement `mp_plus`. `mp_plus` is a variadic (not just
+binary) metafunction that returns the sum of its arguments.
+```
+template<class... T> struct mp_plus_impl;
+
+template<class... T> using mp_plus = typename mp_plus_impl<T...>::type;
+
+template<> struct mp_plus_impl<>
+{
+ using type = std::integral_constant<int, 0>;
+};
+
+template<class T1, class... T> struct mp_plus_impl<T1, T...>
+{
+ static constexpr auto _v = T1::value + mp_plus<T...>::value;
+
+ using type = std::integral_constant<
+ typename std::remove_const<decltype(_v)>::type, _v>;
+};
+```
+Now that we have `mp_plus`, `mp_count` is just
+```
+template<class L, class V> struct mp_count_impl;
+
+template<template<class...> class L, class... T, class V>
+ struct mp_count_impl<L<T...>, V>
+{
+ using type = mp_plus<std::is_same<T, V>...>;
+};
+
+template<class L, class V> using mp_count = typename mp_count_impl<L, V>::type;
+```
+This is another illustration of the power of parameter pack expansion. It's a
+pity that we can't use pack expansion in `mp_plus` as well, to obtain
+```
+T1::value + T2::value + T3::value + T4::value + ...
+```
+directly. It would have been nice for `T::value + $$...$$` to have been
+supported, and it appears that in {cpp}17, it will be.
+
+`mp_count_if` is similarly straightforward:
+```
+template<class L, template<class...> class P> struct mp_count_if_impl;
+
+template<template<class...> class L, class... T, template<class...> class P>
+ struct mp_count_if_impl<L<T...>, P>
+{
+ using type = mp_plus<P<T>...>;
+};
+
+template<class L, template<class...> class P>
+ using mp_count_if = typename mp_count_if_impl<L, P>::type;
+```
+at least if we require `P` to return `bool`. If not, we'll have to coerce
+`P<T>::value` to 0 or 1, or the count will not be correct.
+```
+template<bool v> using mp_bool = std::integral_constant<bool, v>;
+
+template<class L, template<class...> class P> struct mp_count_if_impl;
+
+template<template<class...> class L, class... T, template<class...> class P>
+ struct mp_count_if_impl<L<T...>, P>
+{
+ using type = mp_plus<mp_bool<P<T>::value != 0>...>;
+};
+
+template<class L, template<class...> class P>
+ using mp_count_if = typename mp_count_if_impl<L, P>::type;
+```
+The last primitive I'll show is `mp_contains`. `mp_contains<L, V>` returns
+whether the list `L` contains the type `V`:
+```
+template<class L, class V> using mp_contains = mp_bool<mp_count<L, V>::value != 0>;
+```
+At first sight, this implementation appears horribly naive and inefficient --
+why would we need to count all the occurences just to throw that away if we're
+only interested in a boolean result -- but it's actually pretty competitive and
+perfectly usable. We just need to add one slight optimization to `mp_plus`, the
+engine behind `mp_count` and `mp_contains`:
+```
+template<class T1, class T2, class T3, class T4, class T5,
+ class T6, class T7, class T8, class T9, class T10, class... T>
+ struct mp_plus_impl<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>
+{
+ static constexpr auto _v = T1::value + T2::value + T3::value + T4::value +
+ T5::value + T6::value + T7::value + T8::value + T9::value + T10::value +
+ mp_plus<T...>::value;
+
+ using type = std::integral_constant<
+ typename std::remove_const<decltype(_v)>::type, _v>;
+};
+```
+This cuts the number of template instantiations approximately tenfold.
+
+## Conclusion
+
+I have outlined an approach to metaprogramming in {cpp}11 that
+
+* takes advantage of variadic templates, parameter pack expansion, and template
+ aliases;
+* operates on any variadic template `L<T$$...$$>`, treating it as its
+ fundamental data structure, without mandating a specific type list
+ representation;
+* uses template aliases as its metafunctions, with the expression `F<T$$...$$>`
+ serving as the equivalent of a function call;
+* exploits the structural similarity between the data structure `L<T$$...$$>`
+ and the metafunction call `F<T$$...$$>`;
+* leverages parameter pack expansion as much as possible, instead of using the
+ traditional recursive implementations;
+* relies on inline definitions of template aliases for function composition,
+ instead of providing library support for this task.
+
+## Further reading
+
+<<simple_cxx11_metaprogramming_2.adoc#,Part 2 is now available>>, in which I
+show algorithms that allow us to treat type lists as sets, maps, and vectors,
+and demonstrate various {cpp}11 implementation techniques in the process.
---
+++ libs\mp11\doc\article\simple_cxx11_metaprogramming_2.adoc 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,984 @@
+////
+Copyright 2015-2017 Peter Dimov
+
+Distributed under the Boost Software License, Version 1.0.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+# Simple {cpp}11 metaprogramming, part 2
+Peter Dimov
+2015-06-20
+:toc: left
+:idprefix:
+:docinfo: shared-footer
+
+[.lead]
+__Efficient algorithms for membership testing, random access, and retrieval by
+key__
+
+NOTE: Being late to the metaprogramming party, I make no claim of having
+invented the techniques in this article. A quick look at the implementations
+of, for example, Louis Dionne's https://github.com/ldionne/mpl11[mpl11] and
+Eric Niebler's https://github.com/ericniebler/meta[meta], shows that most of
+these tricks are already known. Dave Abrahams
+https://github.com/dabrahams/mpl11[has experimented] along these lines in 2012.
+The original inventor of the multiple inheritance trick and the `void*`
+arguments trick is probably Richard Smith, who has posted
+https://llvm.org/bugs/attachment.cgi?id=8825[two]
+https://llvm.org/bugs/attachment.cgi?id=8838[examples] in response to
+https://llvm.org/bugs/show_bug.cgi?id=13263[a Clang bug report].
+
+## Vectors, sets, and maps
+
+<<simple_cxx11_metaprogramming.adoc#,Last time>>, I outlined a style of
+metaprogramming that operated on type lists -- variadic class templates:
+```
+template<class... T> struct mp_list {};
+```
+Classic Lisp uses lists as its only data structure, but operating on a list is
+usually linear in the number of its elements.
+
+In addition to `list`, the STL has `vector`, `set`, and `map`. `vector`
+supports random access by index; `set` has efficient test for membership; `map`
+associates keys with values and has efficient lookup based on key.
+
+Instead of introducing separate data structure such as `mp_vector`, `mp_set`,
+`mp_map`, we'll keep our data in a list form, and attempt to provide efficient
+algorithms for random access, membership testing, and lookup.
+
+## mp_contains
+
+Let's starts with sets. A set is just a list with unique elements. To obtain a
+set from an arbitrary list, we'll need an algorithm that removes the
+duplicates. Let's call it `mp_unique<L>`:
+[subs=+quotes]
+```
+// mp_if
+
+template<bool C, class T, class E> struct mp_if_c_impl;
+
+template<class T, class E> struct mp_if_c_impl<true, T, E>
+{
+ using type = T;
+};
+
+template<class T, class E> struct mp_if_c_impl<false, T, E>
+{
+ using type = E;
+};
+
+template<bool C, class T, class E>
+ using mp_if_c = typename mp_if_c_impl<C, T, E>::type;
+
+template<class C, class T, class E>
+ using mp_if = typename mp_if_c_impl<C::value != 0, T, E>::type;
+
+// mp_unique
+
+template<class L> struct mp_unique_impl;
+
+template<class L> using mp_unique = typename mp_unique_impl<L>::type;
+
+template<template<class...> class L> struct mp_unique_impl<L<>>
+{
+ using type = L<>;
+};
+
+template<template<class...> class L, class T1, class... T>
+ struct mp_unique_impl<L<T1, T...>>
+{
+ using _rest = mp_unique<L<T...>>;
+ using type = mp_if<**mp_contains**<_rest, T1>, _rest, mp_push_front<_rest, T1>>;
+};
+```
+For membership testing, we've introduced an algorithm `mp_contains<L, V>` that
+returns `true` when `L` contains `V`. The straightforward recursive
+implementation of `mp_contains` is:
+```
+template<class L, class V> struct mp_contains_impl;
+
+template<class L, class V> using mp_contains = typename mp_contains_impl<L, V>::type;
+
+template<template<class...> class L, class V> struct mp_contains_impl<L<>, V>
+{
+ using type = std::false_type;
+};
+
+template<template<class...> class L, class... T, class V>
+ struct mp_contains_impl<L<V, T...>, V>
+{
+ using type = std::true_type;
+};
+
+template<template<class...> class L, class T1, class... T, class V>
+ struct mp_contains_impl<L<T1, T...>, V>: mp_contains_impl<L<T...>, V>
+{
+};
+```
+Note that `mp_unique<L>` makes `N` calls to `mp_contains`, where `N` is the
+length of the list `L`. This means that `mp_contains` needs to be as fast as
+possible, which the above implementation, well, isn't.
+
+Here are the compile times in seconds for invoking `mp_unique` on a list with
+`N` (distinct) elements:
+|===
+||N=100 |N=200 |N=300 |N=400 |N=500 |N=600 |N=700 |N=800
+
+|VC$$++$$ 2013, recursive |2.1 |DNF ||||||
+
+|clang$$++$$ 3.5.1, recursive |0.9 |4.5 |13.2 |30.2 |DNF |||
+
+|g$$++$$ 4.9.2, recursive |0.7 |3.6 |10.4 |23.2 |DNF |||
+|===
+(Tests done under Windows/Cygwin. All compilers are 32 bit. No optimizations.
+DNF stands for "did not finish", which usually means that the compiler ran out
+of heap space or crashed.)
+
+We clearly need a better alternative.
+
+I ended the previous article with an implementation of `mp_contains` that
+relied on `mp_count`, which in turn relied on `mp_plus`. Let's see how it
+fares:
+|===
+||N=100 |N=200 |N=300 |N=400 |N=500 |N=600 |N=700 |N=800
+
+|VC$$++$$ 2013, mp_count/mp_plus |1.1 |9.8 |50.5 |DNF ||||
+
+|clang$$++$$ 3.5.1, mp_count/mp_plus |0.5 |1.4 |3.1 |6.1 |DNF |||
+
+|g$$++$$ 4.9.2, mp_count/mp_plus |0.5 |1.3 |2.9 |5.8 |9.7 |15.6 |22.4 |32.3
+|===
+Not _that_ bad, at least if your compiler happens to be `g$$++$$`. Still, there
+ought to be room for improvement here.
+
+To do better, we have to somehow leverage the language features, such as pack
+expansion, to do more of the work for us. For inspiration, let's turn to
+section 14.5.3 paragraph 4 of the {cpp}11 standard, which explains that pack
+expansions can occur in the following contexts:
+
+* **In a function parameter pack (8.3.5); the pattern is the
+ __parameter-declaration__ without the ellipsis.**
+* In a template parameter pack that is a pack expansion (14.1):
+* **In an __initializer-list__ (8.5); the pattern is an
+ __initializer-clause__.**
+* **In a __base-specifier-list__ (Clause 10); the pattern is a
+ __base-specifier__.**
+* In a __mem-initializer-list__ (12.6.2); the pattern is a
+ __mem-initializer__.
+* In a __template-argument-list__ (14.3); the pattern is a
+ __template-argument__.
+* In a __dynamic-exception-specification__ (15.4); the pattern is a
+ __type-id__.
+* In an __attribute-list__ (7.6.1); the pattern is an __attribute__.
+* In an __alignment-specifier__ (7.6.2); the pattern is the
+ __alignment-specifier__ without the ellipsis.
+* In a __capture-list__ (5.1.2); the pattern is a __capture__.
+* In a `sizeof$$...$$` expression (5.3.3); the pattern is an __identifier__.
+
+The **emphasis** is mine and indicates possible leads.
+
+Our first option is to expand the parameter pack into arguments for a function
+call. Since we're interested in operations that occur at compile time, calling
+a function may not appear useful; but {cpp}11 functions can be `constexpr`, and
+`constexpr` function "calls" do occur at compile time.
+
+Recall our `mp_count`:
+```
+template<class L, class V> struct mp_count_impl;
+
+template<template<class...> class L, class... T, class V>
+ struct mp_count_impl<L<T...>, V>
+{
+ using type = mp_plus<std::is_same<T, V>...>;
+};
+
+template<class L, class V> using mp_count = typename mp_count_impl<L, V>::type;
+```
+Instead of using the template alias `mp_plus` to sum the `is_same` expressions,
+we can use a `constexpr` function:
+```
+constexpr std::size_t cx_plus()
+{
+ return 0;
+}
+
+template<class T1, class... T> constexpr std::size_t cx_plus(T1 t1, T... t)
+{
+ return t1 + cx_plus(t...);
+}
+
+// mp_size_t
+
+template<std::size_t N> using mp_size_t = std::integral_constant<std::size_t, N>;
+
+// mp_count
+
+template<class L, class V> struct mp_count_impl;
+
+template<template<class...> class L, class... T, class V>
+ struct mp_count_impl<L<T...>, V>
+{
+ using type = mp_size_t<cx_plus(std::is_same<T, V>::value...)>;
+};
+
+template<class L, class V> using mp_count = typename mp_count_impl<L, V>::type;
+```
+with the following results:
+|===
+||N=100 |N=200 |N=300 |N=400 |N=500 |N=600 |N=700 |N=800
+
+|clang$$++$$ 3.5.1, mp_count/cx_plus |0.4 |1.1 |2.5 |5.0 |DNF |||
+
+|g$$++$$ 4.9.2, mp_count/cx_plus |0.4 |0.9 |1.7 |2.9 |4.7 |6.7 |9.2 |11.8
+|===
+We've improved the times, but lost VC$$++$$ 2013 due to its not implementing
+`constexpr`.
+
+Let's try pack expansion into an __initializer-list__. Instead of passing the
+`is_same` expressions to a function, we can build a constant array out of them,
+then sum the array with a `constexpr` function:
+```
+constexpr std::size_t cx_plus2(bool const * first, bool const * last)
+{
+ return first == last? 0: *first + cx_plus2(first + 1, last);
+}
+
+// mp_count
+
+template<class L, class V> struct mp_count_impl;
+
+template<template<class...> class L, class... T, class V>
+ struct mp_count_impl<L<T...>, V>
+{
+ static constexpr bool _v[] = { std::is_same<T, V>::value... };
+ using type = mp_size_t<cx_plus2(_v, _v + sizeof...(T))>;
+};
+
+template<class L, class V> using mp_count = typename mp_count_impl<L, V>::type;
+```
+This is a neat trick, but is it fast?
+|===
+||N=100 |N=200 |N=300 |N=400 |N=500 |N=600 |N=700 |N=800
+
+|clang$$++$$ 3.5.1, mp_count/cx_plus2 |0.4 |0.9 |1.8 |DNF ||||
+
+|g$$++$$ 4.9.2, mp_count/cx_plus2 |0.4 |0.9 |1.9 |3.4 |5.4 |7.8 |11.0 |14.7
+|===
+That's a bit disappointing. Let's see what can we do with expanding a parameter
+pack into a base-specifier-list. We would be able to define a class that
+derives from every element of the pack:
+```
+struct U: T... {};
+```
+We can then use `std::is_base_of<V, U>` to test whether a type `V` is a base of
+`U`, that is, whether it's one of the elements of the parameter pack. Which is
+exactly what we need.
+
+Arbitrary types such as `void`, `int`, or `void(int)` can't be used as base
+classes, but we'll wrap the types in an empty class template, which we'll call
+`mp_identity`.
+```
+template<class T> struct mp_identity
+{
+ using type = T;
+};
+
+template<class L, class V> struct mp_contains_impl;
+
+template<class L, class V> using mp_contains = typename mp_contains_impl<L, V>::type;
+
+template<template<class...> class L, class... T, class V>
+ struct mp_contains_impl<L<T...>, V>
+{
+ struct U: mp_identity<T>... {};
+ using type = std::is_base_of<mp_identity<V>, U>;
+};
+```
+Performance?
+|===
+||N=100 |N=200 |N=300 |N=400 |N=500 |N=600 |N=700 |N=800
+
+|VC$$++$$ 2013, is_base_of |0.3 |0.6 |1.3 |2.5 |DNF |||
+
+|clang$$++$$ 3.5.1, is_base_of |0.3 |0.4 |0.6 |0.8 |DNF |||
+
+|g$$++$$ 4.9.2, is_base_of |0.3 |0.4 |0.6 |0.9 |1.3 |1.7 |2.3 |3.0
+|===
+This implementation is a clear winner.
+
+In fairness, we ought to note that the first four implementations of
+`mp_contains` do not rely on the list elements being unique. This makes
+`mp_contains` an algorithm that supports arbitrary lists, not just sets.
+
+The `is_base_of` implementation, however, does not support lists that contain
+duplicates, because it's not possible to inherit directly from the same type
+twice. So it does not implement the general `mp_contains`, but something that
+should probably be named `mp_set_contains`.
+
+We can avoid the "no duplicates" requirement by modifying the implementation to
+inherit from `mp_identity<T>` indirectly, via an intermediate base class:
+[subs=+macros]
+```
+// indirect_inherit
+
+template<std::size_t I, class T> struct inherit_second: T {};
+
+template<class L, class S> struct indirect_inherit_impl;
+
+template<template<class...> class L, class... T, std::size_t... J>
+ struct indirect_inherit_impl<L<T...>, http://en.cppreference.com/w/cpp/utility/integer_sequence[integer_sequence]<std::size_t, J...>>:
+ inherit_second<J, mp_identity<T>>... {};
+
+template<class L> using indirect_inherit =
+ indirect_inherit_impl<L, http://en.cppreference.com/w/cpp/utility/integer_sequence[make_index_sequence]<mp_size<L>::value>>;
+
+// mp_contains
+
+template<class L, class V> struct mp_contains_impl
+{
+ using U = indirect_inherit<L>;
+ using type = std::is_base_of<mp_identity<V>, U>;
+};
+
+template<class L, class V> using mp_contains = typename mp_contains_impl<L, V>::type;
+```
+This, however, pretty much nullifies the spectacular performance gains we've
+observed with the original `is_base_of`-based implementation:
+|===
+||N=100 |N=200 |N=300 |N=400 |N=500 |N=600 |N=700 |N=800
+
+|VC$$++$$ 2013, recursive |2.1 |DNF ||||||
+
+|VC$$++$$ 2013, mp_count/mp_plus |1.1 |9.8 |50.5 |DNF ||||
+
+|VC$$++$$ 2013, is_base_of |0.3 |0.6 |1.3 |2.5 |DNF |||
+
+|VC$$++$$ 2013, is_base_of/indirect |1.0 |9.3 |49.5 |153.8 |DNF |||
+|===
+|===
+||N=100 |N=200 |N=300 |N=400 |N=500 |N=600 |N=700 |N=800
+
+|clang$$++$$ 3.5.1, recursive |0.9 |4.5 |13.2 |30.2 |DNF |||
+
+|clang$$++$$ 3.5.1, mp_count/mp_plus |0.5 |1.4 |3.1 |6.1 |DNF |||
+
+|clang$$++$$ 3.5.1, mp_count/cx_plus |0.4 |1.1 |2.5 |5.0 |DNF |||
+
+|clang$$++$$ 3.5.1, mp_count/cx_plus2 |0.4 |0.9 |1.8 |DNF ||||
+
+|clang$$++$$ 3.5.1, is_base_of |0.3 |0.4 |0.6 |0.8 |DNF |||
+
+|clang$$++$$ 3.5.1, is_base_of/indirect |0.4 |0.9 |1.6 |2.5 |DNF |||
+|===
+|===
+||N=100 |N=200 |N=300 |N=400 |N=500 |N=600 |N=700 |N=800
+
+|g$$++$$ 4.9.2, recursive |0.7 |3.6 |10.4 |23.2 |DNF |||
+
+|g$$++$$ 4.9.2, mp_count/mp_plus |0.5 |1.3 |2.9 |5.8 |9.7 |15.6 |22.4 |32.3
+
+|g$$++$$ 4.9.2, mp_count/cx_plus |0.4 |0.9 |1.7 |2.9 |4.7 |6.7 |9.2 |11.8
+
+|g$$++$$ 4.9.2, mp_count/cx_plus2 |0.4 |0.9 |1.9 |3.4 |5.4 |7.8 |11.0 |14.7
+
+|g$$++$$ 4.9.2, is_base_of |0.3 |0.4 |0.6 |0.9 |1.3 |1.7 |2.3 |3.0
+
+|g$$++$$ 4.9.2, is_base_of/indirect |0.5 |1.1 |2.3 |4.0 |6.6 |9.8 |13.6 |18.2
+|===
+
+## mp_map_find
+
+A map, in the STL sense, is a data structure that associates keys with values
+and can efficiently retrieve, given a key, its associated value. For our
+purposes, a map will be any list of lists for which the inner lists have at
+least one element, the key; the rest of the elements we'll consider to be the
+associated value. For example, the list
+```
+[[A, B], [C, D, E], [F], [G, H]]
+```
+is a map with keys `A`, `C`, `F`, and `G`, with associated values `[B]`,
+`[D, E]`, `[]`, and `[H]`, respectively. We'll require unique keys, for reasons
+that'll become evident later.
+
+I'll show two other examples of maps, this time using real {cpp} code:
+```
+using Map = mp_list<mp_list<int, int*>, mp_list<void, void*>, mp_list<char, char*>>;
+```
+```
+using Map2 = std::tuple<std::pair<int, int[2]>, std::pair<char, char[2]>>;
+```
+The Lisp name of the algorithm that performs retrieval based on key is `ASSOC`,
+but I'll call it `mp_map_find`. `mp_map_find<M, K>` returns the element of `M`
+whose first element is `K`. For example, `mp_map_find<Map2, int>` would return
+`std::pair<int, int[2]>`. If there's no such key, it returns `void`.
+
+There's almost no need to implement and benchmark the recursive version of
+`mp_map_find` -- we can be pretty sure it will perform horribly. Still,
+```
+template<class M, class K> struct mp_map_find_impl;
+
+template<class M, class K> using mp_map_find = typename mp_map_find_impl<M, K>::type;
+
+template<template<class...> class M, class K> struct mp_map_find_impl<M<>, K>
+{
+ using type = void;
+};
+
+template<template<class...> class M, class T1, class... T, class K>
+ struct mp_map_find_impl<M<T1, T...>, K>
+{
+ using type = mp_if<std::is_same<mp_front<T1>, K>, T1, mp_map_find<M<T...>, K>>;
+};
+```
+The compile time, in seconds, for `N` lookups into a map of size `N`, is as
+follows:
+|===
+||N=100 |N=200 |N=300 |N=400 |N=500 |N=600 |N=700 |N=800
+
+|VC$$++$$ 2013, recursive |38.2 |DNF ||||||
+
+|clang$$++$$ 3.5.1, recursive |2.5 |13.7 |DNF |||||
+
+|g$$++$$ 4.9.2, recursive |1.9 |10.2 |28.8 |DNF ||||
+|===
+I told you there was no point.
+
+But, I hear some of you say, you're evaluating the else branch even if the
+condition is true, and that's horribly inefficient!
+
+Well, this would only improve the performance by a factor of approximately two
+on average, and only if the element is present, but fine, let's try it. The
+element happens to be present in the benchmark, so let's see.
+```
+// mp_eval_if
+
+template<bool C, class T, template<class...> class E, class... A>
+ struct mp_eval_if_c_impl;
+
+template<class T, template<class...> class E, class... A>
+ struct mp_eval_if_c_impl<true, T, E, A...>
+{
+ using type = T;
+};
+
+template<class T, template<class...> class E, class... A>
+ struct mp_eval_if_c_impl<false, T, E, A...>
+{
+ using type = E<A...>;
+};
+
+template<bool C, class T, template<class...> class E, class... A>
+ using mp_eval_if_c = typename mp_eval_if_c_impl<C, T, E, A...>::type;
+
+template<class C, class T, template<class...> class E, class... A>
+ using mp_eval_if = typename mp_eval_if_c_impl<C::value != 0, T, E, A...>::type;
+
+// mp_map_find
+
+template<class M, class K> struct mp_map_find_impl;
+
+template<class M, class K> using mp_map_find = typename mp_map_find_impl<M, K>::type;
+
+template<template<class...> class M, class K> struct mp_map_find_impl<M<>, K>
+{
+ using type = void;
+};
+
+template<template<class...> class M, class T1, class... T, class K>
+ struct mp_map_find_impl<M<T1, T...>, K>
+{
+ using type = mp_eval_if<std::is_same<mp_front<T1>, K>, T1, mp_map_find, M<T...>, K>;
+};
+```
+There you go:
+|===
+||N=100 |N=200 |N=300 |N=400 |N=500 |N=600 |N=700 |N=800
+
+|VC$$++$$ 2013, recursive |15.6 |DNF ||||||
+
+|clang$$++$$ 3.5.1, recursive |1.8 |9.5 |DNF |||||
+
+|g$$++$$ 4.9.2, recursive |1.4 |7.0 |19.7 |DNF ||||
+|===
+I told you there was no point.
+
+Point or no, to establish that the recursive implementation is inefficient is
+not the same as to come up with an efficient one. There are two things that
+make the `mp_contains` techniques inapplicable to our present case: first,
+`mp_contains` only had to return true or false, whereas `mp_map_find` returns a
+type, and second, in `mp_contains` we knew the exact type of the element for
+which we were looking, whereas here, we only know its `mp_front`.
+
+Fortunately, there does exist a language feature that can solve both: {cpp} can
+deduce the template parameters of base classes when passed a derived class. In
+this example,
+```
+struct K1 {};
+struct V1 {};
+
+struct X: std::pair<K1, V1> {};
+
+template<class A, class B> void f(std::pair<A, B> const & p);
+
+int main()
+{
+ f(X());
+}
+```
+the call to `f(X())` deduces `A` as `K1` and `B` as `V1`. If we have more than
+one `std::pair` base class, we can fix `A` to be `K1`:
+```
+struct K1 {};
+struct V1 {};
+
+struct K2 {};
+struct V2 {};
+
+struct X: std::pair<K1, V1>, std::pair<K2, V2> {};
+
+template<class B> void f(std::pair<K1, B> const & p);
+
+int main()
+{
+ f(X());
+}
+```
+and `B` will be deduced as `V1`.
+
+We can retrieve the results of the deduction by returning the type we want:
+```
+template<class B> std::pair<K1, B> f(std::pair<K1, B> const & p);
+```
+and then using `decltype(f(X()))` to obtain this return type.
+
+What if `X` doesn't have a base of type `std::pair<K1, B>`? The deduction will
+fail and we'll get an error that `f(X())` cannot be called. To avoid it, we can
+add an overload of `f` that takes anything and returns `void`. But in this
+case, what will happen if `X` has two bases of the form that match the first
+`f` overload, such as for example `std::pair<K1, Y>` and `std::pair<K1, Z>`?
+
+The deduction will fail, the second overload will again be chosen and we'll get
+`void`. This is why we require maps to have unique keys.
+
+Here's an implementation of `mp_map_find` based on this technique:
+```
+template<class M, class K> struct mp_map_find_impl;
+
+template<class M, class K>
+ using mp_map_find = typename mp_map_find_impl<M, K>::type;
+
+template<template<class...> class M, class... T, class K>
+ struct mp_map_find_impl<M<T...>, K>
+{
+ struct U: mp_identity<T>... {};
+
+ template<template<class...> class L, class... U>
+ static mp_identity<L<K, U...>>
+ f( mp_identity<L<K, U...>>* );
+
+ static mp_identity<void> f( ... );
+
+ using V = decltype( f((U*)0) );
+
+ using type = typename V::type;
+};
+```
+and its corresponding compile times:
+|===
+||N=100 |N=200 |N=300 |N=400 |N=500 |N=600 |N=700 |N=800
+
+|VC$$++$$ 2013, deduction |0.3 |0.7 |1.8 |3.6 |6.4 |10.4 |16.2 |DNF
+
+|clang$$++$$ 3.5.1, deduction |0.3 |0.4 |0.6 |0.9 |1.2 |1.6 |2.2 |2.7
+
+|g$$++$$ 4.9.2, deduction |0.3 |0.5 |0.9 |1.6 |2.3 |3.4 |4.7 |6.3
+|===
+This looks ready to ship.
+
+The implementation contains one inefficiency though. If we evaluate
+`mp_map_find<M, K1>`, then `mp_map_find<M, K2>`, the two nested `U` types are
+the same as they only depend on `M`, but the compiler doesn't know that and
+will instantiate each one separately. We should move this type outside
+`mp_map_find_impl` so that it can be reused:
+[subs=+quotes]
+```
+template<class... T> struct **mp_inherit**: T... {};
+
+template<class M, class K> struct mp_map_find_impl;
+
+template<class M, class K>
+ using mp_map_find = typename mp_map_find_impl<M, K>::type;
+
+template<template<class...> class M, class... T, class K>
+ struct mp_map_find_impl<M<T...>, K>
+{
+ **using U = mp_inherit<mp_identity<T>...>;**
+
+ template<template<class...> class L, class... U>
+ static mp_identity<L<K, U...>>
+ f( mp_identity<L<K, U...>>* );
+
+ static mp_identity<void> f( ... );
+
+ using V = decltype( f((U*)0) );
+
+ using type = typename V::type;
+};
+```
+(This same optimization, by the way, applies to our `is_base_of` implementation
+of `mp_contains`.)
+
+The improvement in compile times on our benchmark is measurable:
+|===
+||N=100 |N=200 |N=300 |N=400 |N=500 |N=600 |N=700 |N=800
+
+|VC$$++$$ 2013, deduction+mp_inherit |0.3 |0.6 |1.4 |2.6 |4.5 |7.1 |10.7 |DNF
+
+|clang$$++$$ 3.5.1, deduction+mp_inherit |0.3 |0.4 |0.6 |0.8 |1.0 |1.4 |1.8 |2.2
+
+|g$$++$$ 4.9.2, deduction+mp_inherit |0.3 |0.4 |0.6 |0.9 |1.3 |1.8 |2.3 |2.9
+|===
+
+## mp_at
+
+With sets and maps covered, it's time to tackle vectors. Vectors for us are
+just lists, to which we'll need to add the ability to efficiently access an
+element based on its index. The customary name for this accessor is
+`mp_at<L, I>`, where `L` is a list and `I` is an `integral_constant` that
+represents the index. We'll also follow the Boost.MPL convention and add
+`mp_at_c<L, I>`, where `I` is the index of type `size_t`.
+
+The recursive implementation of `mp_at` is:
+```
+template<class L, std::size_t I> struct mp_at_c_impl;
+
+template<class L, std::size_t I> using mp_at_c = typename mp_at_c_impl<L, I>::type;
+
+template<class L, class I> using mp_at = typename mp_at_c_impl<L, I::value>::type;
+
+template<template<class...> class L, class T1, class... T>
+ struct mp_at_c_impl<L<T1, T...>, 0>
+{
+ using type = T1;
+};
+
+template<template<class...> class L, class T1, class... T, std::size_t I>
+ struct mp_at_c_impl<L<T1, T...>, I>
+{
+ using type = mp_at_c<L<T...>, I-1>;
+};
+```
+and the compile times for making `N` calls to `mp_at` with a list of size `N`
+as the first argument are:
+|===
+||N=100 |N=200 |N=300 |N=400 |N=500 |N=600 |N=700 |N=800
+
+|VC$$++$$ 2013, recursive |3.6 |DNF ||||||
+
+|clang$$++$$ 3.5.1, recursive |1.0 |5.1 |15.3 |DNF ||||
+
+|g$$++$$ 4.9.2, recursive |0.9 |4.7 |14.2 |32.4 |DNF |||
+|===
+To improve upon this apalling result, we'll again exploit pack expansion into a
+function call, but in a novel way. Let's suppose that we need to access the
+fourth element (`I = 3`). We'll generate the function signature
+```
+template<class W> W f( void*, void*, void*, W*, ... );
+```
+and then, given a list `L<T1, T2, T3, T4, T5, T6, T7>`, we'll evaluate the
+expression
+```
+decltype( f( (T1*)0, (T2*)0, (T3*)0, (T4*)0, (T5*)0, (T6*)0, (T7*)0 ) )
+```
+The three `void*` parameters will eat the first three elements, `W` will be
+deduced as the fourth, and the ellipsis will take care of the rest.
+
+A working implementation based on this technique is shown below:
+```
+// mp_repeat_c
+
+template<std::size_t N, class... T> struct mp_repeat_c_impl
+{
+ using _l1 = typename mp_repeat_c_impl<N/2, T...>::type;
+ using _l2 = typename mp_repeat_c_impl<N%2, T...>::type;
+
+ using type = mp_append<_l1, _l1, _l2>;
+};
+
+template<class... T> struct mp_repeat_c_impl<0, T...>
+{
+ using type = mp_list<>;
+};
+
+template<class... T> struct mp_repeat_c_impl<1, T...>
+{
+ using type = mp_list<T...>;
+};
+
+template<std::size_t N, class... T> using mp_repeat_c =
+ typename mp_repeat_c_impl<N, T...>::type;
+
+// mp_at
+
+template<class L, class L2> struct mp_at_c_impl;
+
+template<template<class...> class L, class... T,
+ template<class...> class L2, class... U>
+ struct mp_at_c_impl<L<T...>, L2<U...>>
+{
+ template<class W> static W f( U*..., W*, ... );
+
+ using R = decltype( f( (mp_identity<T>*)0 ... ) );
+
+ using type = typename R::type;
+};
+
+template<class L, std::size_t I> using mp_at_c =
+ typename mp_at_c_impl<L, mp_repeat_c<I, void>>::type;
+
+template<class L, class I> using mp_at = mp_at_c<L, I::value>;
+```
+and the compile times in the following table show it to be good enough for most
+practical purposes.
+|===
+||N=100 |N=200 |N=300 |N=400 |N=500 |N=600 |N=700 |N=800
+
+|VC$$++$$ 2013, void* |0.4 |1.1 |2.4 |4.7 |DNF |||
+
+|clang$$++$$ 3.5.1, void* |0.4 |0.7 |1.2 |1.9 |2.7 |3.8 |5.0 |6.6
+
+|g$$++$$ 4.9.2, void* |0.3 |0.5 |0.9 |1.3 |2.1 |3.0 |4.2 |5.5
+|===
+Are we done with `mp_at`, then?
+
+Let's try something else -- transform the input list `[T1, T2, T3]` into a map
+`[[0, T1], [1, T2], [2, T3]]`, then use `mp_map_find` for the lookup:
+[subs=+macros]
+```
+// mp_map_from_list
+
+template<class L, class S> struct mp_map_from_list_impl;
+
+template<template<class...> class L, class... T, std::size_t... J>
+ struct mp_map_from_list_impl<L<T...>, http://en.cppreference.com/w/cpp/utility/integer_sequence[integer_sequence]<std::size_t, J...>>
+{
+ using type = mp_list<mp_list<mp_size_t<J>, T>...>;
+};
+
+template<class L> using mp_map_from_list = typename mp_map_from_list_impl<L,
+ http://en.cppreference.com/w/cpp/utility/integer_sequence[make_index_sequence]<mp_size<L>::value>>::type;
+
+// mp_at
+
+template<class L, std::size_t I> struct mp_at_c_impl
+{
+ using map = mp_map_from_list<L>;
+ using type = mp_second<mp_map_find<map, mp_size_t<I>>>;
+};
+
+template<class L, std::size_t I> using mp_at_c = typename mp_at_c_impl<L, I>::type;
+
+template<class L, class I> using mp_at = typename mp_at_c_impl<L, I::value>::type;
+```
+At first sight, this looks ridiculous, but metaprogramming has its own rules.
+Let's measure:
+|===
+||N=100 |N=200 |N=300 |N=400 |N=500 |N=600 |N=700 |N=800
+
+|VC$$++$$ 2013, map |0.3 |0.7 |1.5 |2.9 |5.0 |7.8 |11.9 |DNF
+
+|clang$$++$$ 3.5.1, map |0.3 |0.4 |0.6 |0.8 |1.1 |1.5 |1.8 |2.3
+
+|g$$++$$ 4.9.2, map |0.3 |0.4 |0.7 |1.0 |1.4 |1.9 |2.5 |3.2
+|===
+Surprise, this is the best implementation.
+
+## mp_drop
+
+It turned out that we didn't need the `void*` trick for `mp_at`, but I'll show
+an example where we do: `mp_drop`. `mp_drop<L, N>` returns the list `L` without
+its first `N` elements; or, in other words, it drops the first `N` elements
+(presumably on the cutting room floor) and returns what's left.
+
+To implement `mp_drop`, we just need to change
+```
+template<class W> W f( void*, void*, void*, W*, ... );
+```
+from above to return the rest of the elements, rather than just one:
+```
+template<class... W> mp_list<W> f( void*, void*, void*, W*... );
+```
+Adding the necessary `mp_identity` seasoning produces the following working
+implementation:
+```
+template<class L, class L2> struct mp_drop_c_impl;
+
+template<template<class...> class L, class... T,
+ template<class...> class L2, class... U>
+ struct mp_drop_c_impl<L<T...>, L2<U...>>
+{
+ template<class... W> static mp_identity<L<W...>> f( U*..., mp_identity<W>*... );
+
+ using R = decltype( f( (mp_identity<T>*)0 ... ) );
+
+ using type = typename R::type;
+};
+
+template<class L, std::size_t N> using mp_drop_c =
+ typename mp_drop_c_impl<L, mp_repeat_c<N, void>>::type;
+
+template<class L, class N> using mp_drop = mp_drop_c<L, N::value>;
+```
+I'll skip the recursive implementation and the performance comparison for this
+one. We can pretty much tell who's going to win, and by how much.
+
+## mp_find_index
+
+The final algorithm that I'll bring to your attention is `mp_find_index`.
+`mp_find_index<L, V>` returns an integral constant of type `size_t` with a
+value that is the index of the first occurence of `V` in `L`. If `V` is not in
+`L`, the return value is the size of `L`.
+
+We'll start with the recursive implementation, as usual:
+```
+template<class L, class V> struct mp_find_index_impl;
+
+template<class L, class V> using mp_find_index = typename mp_find_index_impl<L, V>::type;
+
+template<template<class...> class L, class V> struct mp_find_index_impl<L<>, V>
+{
+ using type = mp_size_t<0>;
+};
+
+template<template<class...> class L, class... T, class V>
+ struct mp_find_index_impl<L<V, T...>, V>
+{
+ using type = mp_size_t<0>;
+};
+
+template<template<class...> class L, class T1, class... T, class V>
+ struct mp_find_index_impl<L<T1, T...>, V>
+{
+ using type = mp_size_t<1 + mp_find_index<L<T...>, V>::value>;
+};
+```
+and will continue with the compile times for `N` calls to `mp_find_index` on a
+list with `N` elements, as usual:
+|===
+||N=100 |N=200 |N=300 |N=400 |N=500 |N=600 |N=700 |N=800
+
+|VC$$++$$ 2013, recursive |3.5 |DNF ||||||
+
+|clang$$++$$ 3.5.1, recursive |1.1 |5.5 |DNF |||||
+
+|g$$++$$ 4.9.2, recursive |0.8 |4.6 |13.6 |DNF ||||
+|===
+What can we do here?
+
+Let's go back to `mp_contains` and look at the "mp_count/cx_plus2"
+implementation which we rejected in favor of the inheritance-based one. It
+built a `constexpr` array of booleans and summed them in a `constexpr`
+function. We can do the same here, except instead of summing the array, we can
+find the index of the first true value:
+```
+template<class L, class V> struct mp_find_index_impl;
+
+template<class L, class V> using mp_find_index = typename mp_find_index_impl<L, V>::type;
+
+template<template<class...> class L, class V> struct mp_find_index_impl<L<>, V>
+{
+ using type = mp_size_t<0>;
+};
+
+constexpr std::size_t cx_find_index( bool const * first, bool const * last )
+{
+ return first == last || *first? 0: 1 + cx_find_index( first + 1, last );
+}
+
+template<template<class...> class L, class... T, class V>
+ struct mp_find_index_impl<L<T...>, V>
+{
+ static constexpr bool _v[] = { std::is_same<T, V>::value... };
+
+ using type = mp_size_t< cx_find_index( _v, _v + sizeof...(T) ) >;
+};
+```
+The performance of this version is:
+|===
+||N=100 |N=200 |N=300 |N=400 |N=500 |N=600 |N=700 |N=800
+
+|clang$$++$$ 3.5.1, constexpr |0.5 |1.3 |2.9 |DNF ||||
+
+|g$$++$$ 4.9.2, constexpr |0.5 |1.4 |3.1 |5.5 |8.7 |13.0 |18.0 |DNF
+|===
+which, while not ideal, is significantly better than our recursive punching
+bag. But if our compiler of choice is VC$$++$$ 2013, we can't use `constexpr`.
+
+We may attempt an implementation along the same lines, but with the `constexpr`
+function replaced with ordinary metaprogramming:
+```
+template<class L, class V> struct mp_find_index_impl;
+
+template<class L, class V> using mp_find_index = typename mp_find_index_impl<L, V>::type;
+
+template<template<class...> class L, class V> struct mp_find_index_impl<L<>, V>
+{
+ using type = mp_size_t<0>;
+};
+
+template<bool...> struct find_index_impl_;
+
+template<> struct find_index_impl_<>
+{
+ static const std::size_t value = 0;
+};
+
+template<bool B1, bool... R> struct find_index_impl_<B1, R...>
+{
+ static const std::size_t value = B1? 0: 1 + find_index_impl_<R...>::value;
+};
+
+template<bool B1, bool B2, bool B3, bool B4, bool B5,
+ bool B6, bool B7, bool B8, bool B9, bool B10, bool... R>
+ struct find_index_impl_<B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, R...>
+{
+ static const std::size_t value = B1? 0: B2? 1: B3? 2: B4? 3: B5? 4:
+ B6? 5: B7? 6: B8? 7: B9? 8: B10? 9: 10 + find_index_impl_<R...>::value;
+};
+
+template<template<class...> class L, class... T, class V>
+ struct mp_find_index_impl<L<T...>, V>
+{
+ using type = mp_size_t<find_index_impl_<std::is_same<T, V>::value...>::value>;
+};
+```
+This is still recursive, so we don't expect miracles, but it wouldn't hurt to
+measure:
+|===
+||N=100 |N=200 |N=300 |N=400 |N=500 |N=600 |N=700 |N=800
+
+|VC$$++$$ 2013, bool... |4.7 |94.5 |488.3 |XFA ||||
+
+|clang$$++$$ 3.5.1, bool... |0.6 |2.2 |5.8 |12.0 |21.7 |35.2 |DNF |
+
+|g$$++$$ 4.9.2, bool... |0.6 |2.4 |6.5 |13.2 |23.8 |39.1 |59.0 |DNF
+|===
+(where XFA stands for "experimenter fell asleep".)
+
+This is an interesting tradeoff for VC$$++$$ 2013 and Clang. On the one hand,
+this implementation is slower; on the other, it doesn't crash the compiler as
+easily. Which to prefer is a matter of taste and of stern evaluation of one's
+needs to manipulate type lists of length 300.
+
+Note that once we have `mp_drop` and `mp_find_index`, we can derive the
+`mp_find<L, V>` algorithm, which returns the suffix of `L` starting with the
+first occurence of `V`, if any, and an empty list otherwise, by using
+`mp_drop<L, mp_find_index<L, V>>`.
+
+## Conclusion
+
+In this article, I have shown efficient algorithms that allow us to treat type
+lists as sets, maps and vectors, demonstrating various {cpp}11 implementation
+techniques in the process.
---
+++ libs\mp11\doc\mp11\algorithm.adoc 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,605 @@
+////
+Copyright 2017 Peter Dimov
+
+Distributed under the Boost Software License, Version 1.0.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+[#algorithm]
+# Algorithms, <boost/mp11/algorithm.hpp>
+:toc:
+:toc-title:
+:idprefix:
+
+## mp_assign<L1, L2>
+
+ template<class L1, class L2> using mp_assign = /*...*/;
+
+`mp_assign<L1<T1...>, L2<T2...>>` is an alias for `L1<T2...>`. That is, it replaces the elements of `L1` with those of `L2`.
+
+.Using mp_assign with mp_list and std::tuple
+```
+using L1 = std::tuple<long>;
+using L2 = mp_list<int, float>;
+
+using R1 = mp_assign<L1, L2>; // std::tuple<int, float>
+```
+
+.Using mp_assign with mp_list and std::pair
+```
+using L1 = std::pair<long, char>;
+using L2 = mp_list<int, float>;
+
+using R1 = mp_assign<L1, L2>; // std::pair<int, float>
+```
+
+.mp_assign
+[cols="<.^4m,4*^.^1m",width=85%]
+|===
+|*L1*|A~1~|A~2~|...|A~n~
+5+|
+|*L2*|B~1~|B~2~|...|B~n~
+5+|
+|*mp_assign<L1, L2>*|B~1~|B~2~|...|B~n~
+|===
+
+## mp_clear<L>
+
+ template<class L> using mp_clear = mp_assign<L, mp_list<>>;
+
+`mp_clear<L<T...>>` is an alias for `L<>`, that is, it removes the elements of `L`.
+
+.Using mp_clear with std::tuple
+```
+using L1 = std::tuple<int, float>;
+using R1 = mp_clear<L1>; // std::tuple<>
+```
+
+## mp_transform<F, L...>
+
+ template<template<class...> class F, class... L> using mp_transform = /*...*/;
+
+`mp_transform<F, L1<T1...>, L2<T2...>, ..., Ln<Tn...>>` applies `F` to each successive tuple of elements and returns `L1<F<T1, T2, ..., Tn>...>`.
+
+.Using mp_transform to produce a list of pointers from a list of pointees
+```
+template<class T> using add_pointer_t =
+ typename std::add_pointer<T>::type; // std::add_pointer_t in C++14
+
+using L1 = std::tuple<void, int, float>;
+using R1 = mp_transform<add_pointer_t, L1>; // std::tuple<void*, int*, float*>
+```
+
+.Using mp_transform to compare the contents of two lists of types
+```
+using L1 = std::tuple<void, int, float>;
+using L2 = mp_list<void, int, float>;
+
+using R1 = mp_all<mp_transform<std::is_same, L1, L2>>; // mp_true
+```
+
+.Using mp_transform to compare the contents of two lists of integral constants
+```
+template<class T1, class T2> using eq = mp_bool<T1::value == T2::value>;
+
+using L1 = std::tuple<mp_int<1>, mp_int<2>, mp_int<3>>;
+using L2 = mp_list<mp_size_t<1>, mp_size_t<2>, mp_size_t<3>>;
+
+using R1 = mp_all<mp_transform<eq, L1, L2>>; // mp_true
+```
+
+.mp_transform on one list
+[cols="<.^4m,4*^.^1m",width=85%]
+|===
+|*L1*|A~1~|A~2~|...|A~n~
+5+|
+|*mp_transform<F, L1>*|F<A~1~>|F<A~2~>|...|F<A~n~>
+|===
+
+.mp_transform on two lists
+[cols="<.^4m,4*^.^1m",width=85%]
+|===
+|*L1*|A~1~|A~2~|...|A~n~
+5+|
+|*L2*|B~1~|B~2~|...|B~n~
+5+|
+|*mp_transform<F, L1, L2>*|F<A~1~,B~1~>|F<A~2~,B~2~>|...|F<A~n~,B~n~>
+|===
+
+## mp_transform_q<Q, L...>
+
+ template<class Q, class... L> using mp_transform_q =
+ mp_transform<Q::template fn, L...>;
+
+As `mp_transform`, but takes a quoted metafunction.
+
+.Using mp_transform_q to count the occurences of `void` in a list
+```
+using L1 = std::tuple<void, int, float, void, int>;
+
+using R1 = mp_apply<mp_plus,
+ mp_transform_q<mp_bind_front<std::is_same, void>, L1>>; // mp_int\<2>
+```
+
+[cols="<.^4m,4*^.^1m",width=85%]
+.mp_transform_q on two lists
+|===
+|*L1*|A~1~|A~2~|...|A~n~
+5+|
+|*L2*|B~1~|B~2~|...|B~n~
+5+|
+|*mp_transform_q<Q, L1, L2>*|Q::fn<A~1~,B~1~>|Q::fn<A~2~,B~2~>|...|Q::fn<A~n~,B~n~>
+|===
+
+## mp_transform_if<P, F, L...>
+
+ template<template<class...> class P, template<class...> class F, class L...>
+ using mp_transform_if = /*...*/;
+
+`mp_transform_if<P, F, L1, L2, ..., Ln>` replaces the elements of the list `L1` for which `mp_to_bool<P<T1, T2, ..., Tn>>` is `mp_true` with
+`F<T1, T2, ..., Tn>`, and returns the result, where `Ti` are the corresponding elements of `Li`.
+
+.Using mp_transform_if to replace the occurences of 'void' in a list with the corresponding elements of a second list
+```
+using L1 = std::tuple<void, int, float, void, int>;
+using L2 = std::tuple<char[1], char[2], char[3], char[4], char[5]>;
+
+template<class T1, class T2> using first_is_void = std::is_same<T1, void>;
+template<class T1, class T2> using second = T2;
+
+using R1 = mp_transform_if<first_is_void, second, L1, L2>;
+ // std::tuple<char[1], int, float, char[4], int>
+```
+
+.mp_transform_if
+[cols="<.^4m,4*^.^1m",width=85%]
+|===
+|*L1*|A~1~|A~2~|...|A~n~
+5+|
+|*P<A~i~>*|mp_false|mp_true|...|mp_false
+5+|
+|*L2*|B~1~|B~2~|...|B~n~
+5+|
+|*mp_transform_if<P, F, L1, L2>*|A~1~|F<A~2~,B~2~>|...|A~n~
+|===
+
+## mp_transform_if_q<Qp, Qf, L...>
+
+ template<class Qp, class Qf, class... L> using mp_transform_if_q =
+ mp_transform_if<Qp::template fn, Qf::template fn, L...>;
+
+As `mp_transform_if`, but takes quoted metafunctions.
+
+.Using mp_transform_if_q to replace the occurences of 'void' in a list with the corresponding elements of a second list
+```
+using L1 = std::tuple<void, int, float, void, int>;
+using L2 = std::tuple<char[1], char[2], char[3], char[4], char[5]>;
+
+using R1 = mp_transform_if_q<mp_bind<std::is_same, _1, void>, _2, L1, L2>;
+ // std::tuple<char[1], int, float, char[4], int>
+```
+
+.mp_transform_if_q
+[cols="<.^4m,4*^.^1m",width=85%]
+|===
+|*L1*|A~1~|A~2~|...|A~n~
+5+|
+|*Qp::fn<A~i~>*|mp_false|mp_true|...|mp_false
+5+|
+|*L2*|B~1~|B~2~|...|B~n~
+5+|
+|*mp_transform_if_q<Qp, _2, L1, L2>*|A~1~|B~2~|...|A~n~
+|===
+
+## mp_fill<L, V>
+
+ template<class L, class V> using mp_fill = /*...*/;
+
+`mp_fill<L<T...>, V>` returns `L<V, V, ..., V>`, with the result having the same size as the input.
+
+.Using mp_fill with std::tuple
+```
+using L1 = std::tuple<void, int, float>;
+using R1 = mp_fill<L1, double>; // std::tuple<double, double, double>
+```
+
+.Using mp_fill with std::pair
+```
+using L1 = std::pair<int, float>;
+using R1 = mp_fill<L1, void>; // std::pair<void, void>
+```
+
+.mp_fill
+[cols="<.^4m,4*^.^1m",width=85%]
+|===
+|*L1*|A~1~|A~2~|...|A~n~
+5+|
+|*mp_fill<L1, V>*|V|V|...|V
+|===
+
+## mp_count<L, V>
+
+ template<class L, class V> using mp_count = /*...*/;
+
+`mp_count<L, V>` returns `mp_size_t<N>`, where `N` is the number of elements of `L` same as `V`.
+
+## mp_count_if<L, P>
+
+ template<class L, template<class...> class P> using mp_count_if = /*...*/;
+
+`mp_count_if<L, P>` returns `mp_size_t<N>`, where `N` is the number of elements `T` of `L` for which `mp_to_bool<P<T>>` is `mp_true`.
+
+## mp_contains<L, V>
+
+ template<class L, class V> using mp_contains = mp_to_bool<mp_count<L, V>>;
+
+`mp_contains<L, V>` is `mp_true` when `L` contains an element `V`, `mp_false` otherwise.
+
+## mp_repeat_c<L, N>
+
+ template<class L, std::size_t N> using mp_repeat_c = /*...*/;
+
+`mp_repeat_c<L, N>` returns a list of the same type as `L` that consists of `N` concatenated copies of `L`.
+
+## mp_repeat<L, N>
+
+ template<class L, class N> using mp_repeat = /*...*/;
+
+Same as `mp_repeat_c` but with a type argument `N`. The number of copies is `N::value` and must be nonnegative.
+
+## mp_product<F, L...>
+
+ template<template<class...> class F, class... L> using mp_product = /*...*/;
+
+`mp_product<F, L1<T1...>, L2<T2...>, ..., Ln<Tn...>>` evaluates `F<U1, U2, ..., Un>` for values `Ui` taken from
+the Cartesian product of the lists, as if the elements `Ui` are formed by `n` nested loops, each traversing `Li`.
+It returns a list of type `L1` containing the results of the application of `F`.
+
+.mp_product on two lists
+[cols="<.^4m,4*^.^1m",width=85%]
+|===
+|*L1*|A~1~|A~2~|...|A~n~
+5+|
+|*L2*|B~1~|B~2~|...|B~m~
+5+|
+|*mp_product<F, L1, L2>*|F<A~1~,B~1~>|F<A~1~,B~2~>|...|F<A~1~,B~m~>
+||F<A~2~,B~1~>|F<A~2~,B~2~>|...|F<A~2~,B~m~>
+|
+4+|...
+||F<A~n~,B~1~>|F<A~n~,B~2~>|...|F<A~n~,B~m~>
+|===
+
+## mp_product_q<Q, L...>
+
+ template<class Q, class... L> using mp_product_q = mp_product<Q::template fn, L...>;
+
+As `mp_product`, but takes a quoted metafunction.
+
+## mp_drop_c<L, N>
+
+ template<class L, std::size_t N> using mp_drop_c = /*...*/;
+
+`mp_drop_c<L, N>` removes the first `N` elements of `L` and returns the result.
+
+.mp_drop_c
+[cols="<.^4m,6*^.^1m",width=85%]
+|===
+|*L1*|A~1~|...|A~m~|A~m+1~|...|A~n~
+7+|
+|*mp_drop_c<L1, M>*|A~m+1~|...|A~n~ 3+|
+|===
+
+## mp_drop<L, N>
+
+ template<class L, class N> using mp_drop = /*...*/;
+
+Same as `mp_drop_c`, but with a type argument `N`. `N::value` must be a nonnegative number.
+
+## mp_iota_c<N>
+
+ template<std::size_t N> using mp_iota_c = /*...*/;
+
+`mp_iota_c<N>` is an alias for `mp_list<mp_size_t<0>, mp_size_t<1>, ..., mp_size_t<N-1>>`.
+
+## mp_iota<N>
+
+ template<class N> using mp_iota = /*...*/;
+
+Same as `mp_iota_c`, but with a type argument `N`. `N::value` must be a nonnegative number. Returns
+`mp_list<std::integral_constant<T, 0>, std::integral_constant<T, 1>, ..., std::integral_constant<T, N::value-1>>`
+where `T` is the type of `N::value`.
+
+.mp_iota
+[cols="<.^4m,4*^.^1m",width=85%]
+|===
+|*mp_iota<mp_int<4>>*|mp_int<0>|mp_int<1>|mp_int<2>|mp_int<3>
+|===
+
+## mp_at_c<L, I>
+
+ template<class L, std::size_t I> using mp_at_c = /*...*/;
+
+`mp_at_c<L, I>` returns the `I`-th element of `L`, zero-based.
+
+## mp_at<L, I>
+
+ template<class L, class I> using mp_at = /*...*/;
+
+Same as `mp_at_c`, but with a type argument `I`. `I::value` must be a nonnegative number.
+
+## mp_take_c<L, N>
+
+ template<class L, std::size_t N> using mp_take_c = /*...*/;
+
+`mp_take_c<L, N>` returns a list of the same type as `L` containing the first `N` elements of `L`.
+
+.mp_take_c
+[cols="<.^4m,6*^.^1m",width=85%]
+|===
+|*L1*|A~1~|...|A~m~|A~m+1~|...|A~n~
+7+|
+|*mp_take_c<L1, M>*|A~1~|...|A~m~ 3+|
+|===
+
+## mp_take<L, N>
+
+ template<class L, class N> using mp_take = /*...*/;
+
+Same as `mp_take_c`, but with a type argument `N`. `N::value` must be a nonnegative number.
+
+## mp_insert_c<L, I, T...>
+
+ template<class L, std::size_t I, class... T> using mp_insert_c =
+ mp_append<mp_take_c<L, I>, mp_push_front<mp_drop_c<L, I>, T...>>;
+
+Inserts the elements `T...` into the list `L` at position `I` (a zero-based index).
+
+.mp_insert_c with two elements
+[cols="<.^4m,8*^.^1m",width=85%]
+|===
+|*L1*|A~1~|...|A~m~|A~m+1~|...|A~n~ 2+|
+9+|
+|*mp_insert_c<L1, M, B~1~, B~2~>*|A~1~|...|A~m~|B~1~|B~2~|A~m+1~|...|A~n~
+|===
+
+## mp_insert<L, I, T...>
+
+ template<class L, class I, class... T> using mp_insert =
+ mp_append<mp_take<L, I>, mp_push_front<mp_drop<L, I>, T...>>;
+
+Same as `mp_insert_c`, but with a type argument `I`.
+
+## mp_erase_c<L, I, J>
+
+ template<class L, std::size_t I, std::size_t J> using mp_erase_c =
+ mp_append<mp_take_c<L, I>, mp_drop_c<L, J>>;
+
+Removes from the list `L` the elements with indices from `I` (inclusive) to `J` (exclusive).
+
+.mp_erase_c
+[cols="<.^4m,9*^.^1m",width=85%]
+|===
+|*L1*|A~0~|...|A~i-1~|A~i~|...|A~j-1~|A~j~|...|A~n-1~
+10+|
+|*mp_erase_c<L1, I, J>*|A~0~|...|A~i-1~|A~j~|...|A~n-1~ 3+|
+|===
+
+## mp_erase<L, I, J>
+
+ template<class L, class I, class J> using mp_erase =
+ mp_append<mp_take<L, I>, mp_drop<L, J>>;
+
+Same as `mp_erase_c`, but with a type arguments `I` and `J`.
+
+## mp_replace<L, V, W>
+
+ template<class L, class V, class W> using mp_replace = /*...*/;
+
+Replaces all `V` elements of `L` with `W` and returns the result.
+
+.mp_replace
+[cols="<.^4m,4*^.^1m",width=85%]
+|===
+|*L1*|A~1~|V|...|A~n~
+5+|
+|*mp_replace<L1, V, W>*|A~1~|W|...|A~n~
+|===
+
+## mp_replace_if<L, P, W>
+
+ template<class L, template<class...> class P, class W> using mp_replace_if = /*...*/;
+
+Replaces all `T` elements of `L` for which `mp_to_bool<P<T>>` is `mp_true` with `W` and returns the result.
+
+.mp_replace_if
+[cols="<.^4m,4*^.^1m",width=85%]
+|===
+|*L1*|A~1~|A~2~|...|A~n~
+5+|
+|*P<A~i~>*|mp_false|mp_true|...|mp_false
+5+|
+|*mp_replace_if<L1, P, W>*|A~1~|W|...|A~n~
+|===
+
+## mp_replace_at_c<L, I, W>
+
+ template<class L, std::size_t I, class W> using mp_replace_at_c = /*...*/;
+
+Replaces the element of `L` at zero-based index `I` with `W` and returns the result.
+
+## mp_replace_at<L, I, W>
+
+ template<class L, class I, class W> using mp_replace_at = /*...*/;
+
+Same as `mp_replace_at_c`, but with a type argument `I`. `I::value` must be a nonnegative number.
+
+## mp_copy_if<L, P>
+
+ template<class L, template<class...> class P> using mp_copy_if = /*...*/;
+
+Copies the elements `T` of `L` for which `mp_to_bool<P<T>>` is `mp_true` to a new list of the same type and returns it.
+
+## mp_remove<L, V>
+
+ template<class L, class V> using mp_remove = /*...*/;
+
+Removes all `V` elements of `L` and returns the result.
+
+## mp_remove_if<L, P>
+
+ template<class L, template<class...> class P> using mp_remove_if = /*...*/;
+
+Removes all elements `T` of `L` for which `mp_to_bool<P<T>>` is `mp_true` and returns the result.
+
+## mp_partition<L, P>
+
+ template<class L, template<class...> class P> using mp_partition = /*...*/;
+
+`mp_partition<L<T...>, P>` partitions `L` into two lists `L<U1...>` and `L<U2...>` such that `mp_to_bool<P<T>>` is `mp_true`
+for the elements of `L<U1...>` and `mp_false` for the elements of `L<U2...>`. Returns `L<L<U1...>, L<U2...>>`.
+
+## mp_sort<L, P>
+
+ template<class L, template<class...> class P> using mp_sort = /*...*/;
+
+`mp_sort<L, P>` sorts the list `L` according to the strict weak ordering `mp_to_bool<P<T, U>>`.
+
+.Using mp_sort to sort a list of std::ratio values
+----
+#include <ratio>
+
+using L1 = mp_list<std::ratio<1,2>, std::ratio<1,4>>;
+using R1 = mp_sort<L1, std::ratio_less>; // mp_list<ratio<1,4>, ratio<1,2>>
+----
+
+## mp_find<L, V>
+
+ template<class L, class V> using mp_find = /*...*/;
+
+`mp_find<L, V>` returns the index at which the type `V` is located in the list `L`. It's an alias for `mp_size_t<I>`,
+where `I` is the zero-based index of the first occurence of `V` in `L`. If `L` does not contain `V`, `mp_find<L, V>`
+is `mp_size<L>`.
+
+## mp_find_if<L, P>
+
+ template<class L, template<class...> class P> using mp_find_if = /*...*/;
+
+`mp_find_f<L, P>` is an alias for `mp_size_t<I>`, where `I` is the zero-based index of the first element `T` in `L` for which
+`mp_to_bool<P<T>>` is `mp_true`. If there is no such element, `mp_find_if<L, P>` is `mp_size<L>`.
+
+## mp_reverse<L>
+
+ template<class L> using mp_reverse = /*...*/;
+
+`mp_reverse<L<T1, T2, ..., Tn>>` is `L<Tn, ..., T2, T1>`.
+
+.mp_reverse
+[cols="<.^4m,4*^.^1m",width=85%]
+|===
+|*L1*|A~1~|A~2~|...|A~n~
+5+|
+|*mp_reverse<L1>*|A~n~|A~n-1~|...|A~1~
+|===
+
+## mp_fold<L, V, F>
+
+ template<class L, class V, template<class...> class F> using mp_fold = /*...*/;
+
+`mp_fold<L<T1, T2, ..., Tn>, V, F>` is `F< F< F< F<V, T1>, T2>, ...>, Tn>`, or `V`, if `L` is empty.
+
+.Using mp_fold to add the contents of a list of std::ratio values
+----
+#include <ratio>
+
+using L1 = mp_list<std::ratio<1,8>, std::ratio<1,4>, std::ratio<1,2>>;
+using R1 = mp_fold<L1, std::ratio<0,1>, std::ratio_add>; // std::ratio<7,8>
+----
+
+## mp_reverse_fold<L, V, F>
+
+ template<class L, class V, template<class...> class F> using mp_reverse_fold =
+ /*...*/;
+
+`mp_reverse_fold<L<T1, T2, ..., Tn>, V, F>` is `F<T1, F<T2, F<..., F<Tn, V>>>>`, or `V`, if `L` is empty.
+
+## mp_unique<L>
+
+ template<class L> using mp_unique = /*...*/;
+
+`mp_unique<L>` returns a list of the same type as `L` with the duplicate elements removed.
+
+## mp_all_of<L, P>
+
+ template<class L, template<class...> class P> using mp_all_of =
+ mp_bool< mp_count_if<L, P>::value == mp_size<L>::value >;
+
+`mp_all_of<L, P>` is `mp_true` when `P` holds for all elements of `L`, `mp_false` otherwise. When `L` is empty, the result is `mp_true`.
+
+## mp_none_of<L, P>
+
+ template<class L, template<class...> class P> using mp_none_of =
+ mp_bool< mp_count_if<L, P>::value == 0 >;
+
+`mp_none_of<L, P>` is `mp_true` when `P` holds for no element of `L`, `mp_false` otherwise. When `L` is empty, the result is `mp_true`.
+
+## mp_any_of<L, P>
+
+ template<class L, template<class...> class P> using mp_any_of =
+ mp_bool< mp_count_if<L, P>::value != 0 >;
+
+`mp_any_of<L, P>` is `mp_true` when `P` holds for at least one element of `L`, `mp_false` otherwise. When `L` is empty, the result is `mp_false`.
+
+## mp_for_each<L>(f)
+
+ template<class L, class F> constexpr F mp_for_each(F&& f);
+
+`mp_for_each<L>(f)` calls `f` with `T()` for each element `T` of the list `L`, in order.
+
+Returns `std::forward<F>(f)`.
+
+.Using mp_for_each and a C++14 lambda to print a tuple
+```
+template<class... T> void print( std::tuple<T...> const & tp )
+{
+ std::size_t const N = sizeof...(T);
+
+ mp_for_each<mp_iota_c<N>>( [&]( auto I ){
+
+ // I is mp_size_t<0>, mp_size_t<1>, ..., mp_size_t<N-1>
+
+ std::cout << std::get<I>(tp) << std::endl;
+
+ });
+}
+```
+
+## mp_with_index<N>(i, f)
+
+ template<std::size_t N, class F>
+ constexpr auto mp_with_index( std::size_t i, F && f )
+ -> decltype(std::declval<F>()(std::declval<mp_size_t<0>>()));
+
+`mp_with_index<N>(i, f)` calls `f` with `mp_size_t<i>()` and returns the result. `i` must be less than `N`.
+Only `constexpr` on C++14 and higher.
+
+ template<class N, class F>
+ constexpr auto mp_with_index( std::size_t i, F && f )
+ -> decltype(std::declval<F>()(std::declval<mp_size_t<0>>()));
+
+Returns `mp_with_index<N::value>(i, f)`.
+
+.Using mp_with_index and a C++14 lambda to print the active element of a variant
+```
+template<class... T> void print( std::variant<T...> const& v )
+{
+ mp_with_index<sizeof...(T)>( v.index(), [&]( auto I ) {
+
+ // I is mp_size_t<v.index()> here
+
+ std::cout << std::get<I>( v ) << std::endl;
+
+ });
+}
+```
---
+++ libs\mp11\doc\mp11\bind.adoc 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,76 @@
+////
+Copyright 2017 Peter Dimov
+
+Distributed under the Boost Software License, Version 1.0.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+[#bind]
+# Bind, <boost/mp11/bind.hpp>
+:toc:
+:toc-title:
+:idprefix:
+
+## mp_arg<I>
+
+ template<std::size_t I> struct mp_arg;
+
+`mp_arg<I>` is a quoted metafunction whose nested template `fn<T...>` returns the `I`-th zero-based element of `T...`.
+
+## _1, ..., _9
+
+ using _1 = mp_arg<0>;
+ using _2 = mp_arg<1>;
+ using _3 = mp_arg<2>;
+ using _4 = mp_arg<3>;
+ using _5 = mp_arg<4>;
+ using _6 = mp_arg<5>;
+ using _7 = mp_arg<6>;
+ using _8 = mp_arg<7>;
+ using _9 = mp_arg<8>;
+
+`_1` to `_9` are placeholder types, the equivalent to the placeholders of `boost::bind`.
+
+## mp_bind<F, T...>
+
+ template<template<class...> class F, class... T> struct mp_bind;
+
+`mp_bind<F, T...>` is a quoted metafunction that implements the type-based equivalent of `boost::bind`. Its nested
+template `fn<U...>` returns `F<V...>`, where `V...` is `T...` with the placeholders replaced by the corresponding element
+of `U...` and the `mp_bind` expressions replaced with their corresponding evaluations against `U...`.
+
+For example, `mp_bind<F, int, _2, mp_bind<G, _1>>::fn<float, void>` is `F<int, void, G<float>>`.
+
+## mp_bind_q<Q, T...>
+
+ template<class Q, class... T> using mp_bind_q = mp_bind<Q::template fn, T...>;
+
+As `mp_bind`, but takes a quoted metafunction.
+
+## mp_bind_front<F, T...>
+
+ template<template<class...> class F, class... T> struct mp_bind_front;
+
+`mp_bind_front<F, T...>` binds the leftmost arguments of `F` to `T...`. Its nested template `fn<U...>` returns `F<T..., U...>`.
+
+## mp_bind_front_q<Q, T...>
+
+ template<class Q, class... T> using mp_bind_front_q =
+ mp_bind_front<Q::template fn, T...>;
+
+As `mp_bind_front`, but takes a quoted metafunction.
+
+## mp_bind_back<F, T...>
+
+ template<template<class...> class F, class... T> struct mp_bind_back;
+
+`mp_bind_back<F, T...>` binds the rightmost arguments of `F` to `T...`. Its nested template `fn<U...>` returns `F<U..., T...>`.
+
+## mp_bind_back_q<Q, T...>
+
+ template<class Q, class... T> using mp_bind_back_q =
+ mp_bind_back<Q::template fn, T...>;
+
+As `mp_bind_back`, but takes a quoted metafunction.
---
+++ libs\mp11\doc\mp11\definitions.adoc 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,53 @@
+////
+Copyright 2017 Peter Dimov
+
+Distributed under the Boost Software License, Version 1.0.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+[#definitions]
+# Definitions
+
+A _list_ is a -- usually but not necessarily variadic -- template class whose parameters are all types,
+for example `mp_list<char[], void>`, `mp_list<>`, `std::tuple<int, float, char>`, `std::pair<int, float>`, `std::shared_ptr<X>`.
+
+A _metafunction_ is a class template or a template alias whose parameters are all types, for example `std::add_pointer_t`,
+`std::is_const`, `mp_second`, `mp_push_front`, `mp_list`, `std::tuple`, `std::pair`, `std::shared_ptr`, or
+
+```
+template<class...> using F1 = void;
+
+template<class T> using F2 = T*;
+
+template<class... T> using F3 = std::integral_constant<std::size_t, sizeof...(T)>;
+```
+
+A _quoted metafunction_ is a class with a public metafunction member called `fn`, for example
+
+```
+struct Q1 { template<class...> using fn = void; };
+
+struct Q2 { template<class T> using fn = T*; };
+
+struct Q3 { template<class... T> using fn =
+ std::integral_constant<std::size_t, sizeof...(T)>; };
+```
+
+An _integral constant type_ is a class with a public member `value` that is an integral constant in the C++ sense. For example,
+`std::integral_constant<int, 7>`, or
+
+ struct N { static int constexpr value = 2; };
+
+A _set_ is a list whose elements are unique.
+
+A _map_ is a list of lists, the inner lists having at least one element (the key.) The keys of the map must be unique. For example,
+
+```
+using M1 = std::tuple<std::pair<int, int*>, std::pair<float, float*>,
+ std::pair<void, void*>>;
+
+using M2 = mp_list<mp_list<int, int*>, mp_list<float>,
+ mp_list<char, char[1], char[2]>>;
+```
---
+++ libs\mp11\doc\mp11\examples.adoc 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,483 @@
+////
+Copyright 2017 Peter Dimov
+
+Distributed under the Boost Software License, Version 1.0.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+[#examples]
+# Examples
+:toc:
+:toc-title:
+:idprefix:
+
+## Generating Test Cases
+
+Let's suppose that we have written a metafunction `result<T, U>`:
+
+```
+template<class T> using promote = typename std::common_type<T, int>::type;
+
+template<class T, class U> using result =
+ typename std::common_type<promote<T>, promote<U>>::type;
+```
+
+that ought to represent the result of an arithmetic operation on the integer types `T` and `U`,
+for example `t + u`. We want to test whether `result<T, U>` gives correct results for various combinations
+of `T` and `U`, so we write the function
+```
+template<class T1, class T2> void test_result()
+{
+ using T3 = decltype( T1() + T2() );
+ using T4 = result<T1, T2>;
+
+ std::cout << ( std::is_same<T3, T4>::value? "[PASS]": "[FAIL]" ) << std::endl;
+}
+```
+and then need to call it a substantial number of times:
+
+ int main()
+ {
+ test_result<char, char>();
+ test_result<char, short>();
+ test_result<char, int>();
+ test_result<char, unsigned>();
+ // ...
+ }
+
+Writing all those type combinations by hand is unwieldy, error prone, and worst of all, boring. This is
+how we can leverage Mp11 to automate the task:
+```
+#include <boost/mp11.hpp>
+#include <boost/core/demangle.hpp>
+#include <type_traits>
+#include <iostream>
+#include <typeinfo>
+
+using namespace boost::mp11;
+
+template<class T> std::string name()
+{
+ return boost::core::demangle( typeid(T).name() );
+}
+
+template<class T> using promote = typename std::common_type<T, int>::type;
+
+template<class T, class U> using result =
+ typename std::common_type<promote<T>, promote<U>>::type;
+
+template<class T1, class T2> void test_result( mp_list<T1, T2> const& )
+{
+ using T3 = decltype( T1() + T2() );
+ using T4 = result<T1, T2>;
+
+ std::cout << ( std::is_same<T3, T4>::value? "[PASS] ": "[FAIL] " )
+ << name<T1>() << " + " << name<T2>() << " -> " << name<T3>()
+ << ", result: " << name<T4>() << std::endl;
+}
+
+int main()
+{
+ using L = std::tuple<char, short, int, unsigned, long, unsigned long>;
+ tuple_for_each( mp_product<mp_list, L, L>(), [](auto&& x){ test_result(x); } );
+}
+```
+How does it work?
+
+`mp_product<F, L1, L2>` calls `F<T1, T2>` where `T1` varies over the elements of `L1` and `T2` varies over
+the elements of `L2`, as if by executing two nested loops. It then returns a list of these results, of the same
+type as `L1`.
+
+In our case, both lists are the same `std::tuple`, and `F` is `mp_list`, so `mp_product<mp_list, L, L>` will get us
+`std::tuple<mp_list<char, char>, mp_list<char, short>, mp_list<char, int>, ..., mp_list<unsigned long, long>, mp_list<unsigned long, unsigned long>>`.
+
+We then default-construct this tuple and pass it to `tuple_for_each`. `tuple_for_each(tp, f)` calls `f` for every
+tuple element; we use a (C++14) lambda that calls `test_result`.
+
+In pure C++11, we can't use a lambda with an `auto&&` parameter, so we'll have to make `test_result` a function object with
+a templated `operator()` and pass that to `tuple_for_each` directly:
+```
+struct test_result
+{
+ template<class T1, class T2> void operator()( mp_list<T1, T2> const& ) const
+ {
+ using T3 = decltype( T1() + T2() );
+ using T4 = result<T1, T2>;
+
+ std::cout << ( std::is_same<T3, T4>::value? "[PASS] ": "[FAIL] " )
+ << name<T1>() << " + " << name<T2>() << " -> " << name<T3>()
+ << ", result: " << name<T4>() << std::endl;
+ }
+};
+
+int main()
+{
+ using L = std::tuple<char, short, int, unsigned, long, unsigned long>;
+ tuple_for_each( mp_product<mp_list, L, L>(), test_result() );
+}
+```
+## Writing common_type Specializations
+
+The standard trait `std::common_type`, used to obtain a type to which all of its arguments can convert without
+unnecessary loss of precision, can be user-specialized when its default implementation (based on the ternary `?:`
+operator) is unsuitable.
+
+Let's write a `common_type` specialization for two `std::tuple` arguments. For that, we need a metafunction that
+applies `std::common_type` to each pair of elements and gathers the results into a tuple:
+```
+template<class... T> using common_type_t =
+ typename std::common_type<T...>::type; // standard in C++14
+
+template<class Tp1, class Tp2> using common_tuple =
+ mp_transform<common_type_t, Tp1, Tp2>;
+```
+then specialize `common_type` to use it:
+```
+namespace std
+{
+
+ template<class... T1, class... T2>
+ struct common_type<std::tuple<T1...>, std::tuple<T2...>>:
+ mp_defer<common_tuple, std::tuple<T1...>, std::tuple<T2...>>
+ {
+ };
+
+} // std
+```
+(There is no need to specialize `std::common_type` for more than two arguments - it takes care of synthesizing the appropriate semantics from
+the binary case.)
+
+The subtlety here is the use of `mp_defer`. We could have defined a nested `type` to `common_tuple<std::tuple<T1...>, std::tuple<T2...>>`,
+and it would still have worked in all valid cases. By letting `mp_defer` define `type`, though, we make our specialization _SFINAE-friendly_.
+
+That is, when our `common_tuple` causes a substitution failure instead of a hard error, `mp_defer` will not define a nested `type`,
+and `common_type_t`, which is defined as `typename common_type<...>::type`, will also cause a substitution failure.
+
+As another example, consider the hypothetical type `expected<T, E...>` that represents either a successful return with a value of `T`,
+or an unsucessful return with an error code of some type in the list `E...`. The common type of `expected<T1, E1, E2, E3>` and
+`expected<T2, E1, E4, E5>` is `expected<common_type_t<T1, T2>, E1, E2, E3, E4, E5>`. That is, the possible return values are
+combined into their common type, and we take the union of the set of error types.
+
+Therefore,
+```
+template<class T1, class E1, class T2, class E2> using common_expected =
+ mp_rename<mp_push_front<mp_unique<mp_append<E1, E2>>, common_type_t<T1, T2>>,
+ expected>;
+
+namespace std
+{
+
+ template<class T1, class... E1, class T2, class... E2>
+ struct common_type<expected<T1, E1...>, expected<T2, E2...>>:
+ mp_defer<common_expected, T1, mp_list<E1...>, T2, mp_list<E2...>>
+ {
+ };
+
+} // std
+```
+Here we've taken a different tack; instead of passing the `expected` types to `common_expected`, we're passing the `T` types and lists of
+the `E` types. This makes our job easier. `mp_unique<mp_append<E1, E2>>` gives us the concatenation of `E1` and `E2` with the duplicates
+removed; we then add `common_type_t<T1, T2>` to the front via `mp_push_front`; and finally, we `mp_rename` the resultant `mp_list`
+to `expected`.
+
+## Fixing tuple_cat
+
+The article http://pdimov.com/cpp2/simple_cxx11_metaprogramming.html#[Simple C++11 metaprogramming] builds an
+implementation of the standard function `tuple_cat`, with the end result given below:
+
+```
+template<class L> using F = mp_iota<mp_size<L>>;
+
+template<class R, class...Is, class... Ks, class Tp>
+R tuple_cat_( mp_list<Is...>, mp_list<Ks...>, Tp tp )
+{
+ return R{ std::get<Ks::value>(std::get<Is::value>(tp))... };
+}
+
+template<class... Tp,
+ class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>>
+ R tuple_cat( Tp &&... tp )
+{
+ std::size_t const N = sizeof...(Tp);
+
+ // inner
+
+ using list1 = mp_list<
+ mp_rename<typename std::remove_reference<Tp>::type, mp_list>...>;
+
+ using list2 = mp_iota_c<N>;
+
+ using list3 = mp_transform<mp_fill, list1, list2>;
+
+ using inner = mp_apply<mp_append, list3>;
+
+ // outer
+
+ using list4 = mp_transform<F, list1>;
+
+ using outer = mp_apply<mp_append, list4>;
+
+ //
+
+ return tuple_cat_<R>( inner(), outer(),
+ std::forward_as_tuple( std::forward<Tp>(tp)... ) );
+}
+```
+
+This function, however, is not entirely correct, in that it doesn't handle some cases properly. For example,
+trying to concatenate tuples containing move-only elements such as `unique_ptr` fails:
+
+```
+std::tuple<std::unique_ptr<int>> t1;
+std::tuple<std::unique_ptr<float>> t2;
+
+auto result = ::tuple_cat( std::move( t1 ), std::move( t2 ) );
+```
+Trying to concatenate `const` tuples fails:
+```
+std::tuple<int> const t1;
+std::tuple<float> const t2;
+
+auto result = ::tuple_cat( t1, t2 );
+```
+And finally, the standard `tuple_cat` is specified to work on arbitrary tuple-like types (that is, all types
+that support `tuple_size`, `tuple_element`, and `get`), while our implementation only works with `tuple` and
+`pair`. `std::array`, for example, fails:
+```
+std::array<int, 2> t1{ 1, 2 };
+std::array<float, 3> t2{ 3.0f, 4.0f, 5.0f };
+
+auto result = ::tuple_cat( t1, t2 );
+```
+Let's fix these one by one. Support for move-only types is easy, if one knows where to look. The problem is
+that `Tp` that we're passing to the helper `tuple_cat_` is (correctly) `tuple<unique_ptr<int>&&, unique_ptr<float>&&>`,
+but `std::get<0>(tp)` still returns `unique_ptr<int>&`, because `tp` is an lvalue. This behavior is a bit
+surprising, but is intended to prevent inadvertent double moves.
+
+Long story short, we need `std::move(tp)` in `tuple_cat_` to make `tp` an rvalue:
+
+ template<class R, class...Is, class... Ks, class Tp>
+ R tuple_cat_( mp_list<Is...>, mp_list<Ks...>, Tp tp )
+ {
+ return R{ std::get<Ks::value>(std::get<Is::value>(std::move(tp)))... };
+ }
+
+Next, `const`-qualified tuples. The issue here is that we're stripping references from the input tuples, but not
+`const`. As a result, we're trying to manipulate types such as `tuple<int> const` with Mp11 algorithms, and these
+types do not fit the list concept. We just need to strip qualifiers as well, by defining the useful `remove_cv_ref`
+primitive that is inexplicably missing from the standard library:
+
+ template<class T> using remove_cv_ref = typename std::remove_cv<
+ typename std::remove_reference<T>::type>::type;
+
+and then by using `remove_cv_ref<Tp>` in place of `typename std::remove_reference<Tp>::type`:
+
+```
+template<class... Tp,
+ class R = mp_append<std::tuple<>, remove_cv_ref<Tp>...>>
+ R tuple_cat( Tp &&... tp )
+{
+ std::size_t const N = sizeof...(Tp);
+
+ // inner
+
+ using list1 = mp_list<mp_rename<remove_cv_ref<Tp>, mp_list>...>;
+
+ // ...
+```
+
+Finally, tuple-like types. We've so far exploited the fact that `std::pair` and `std::tuple` are valid Mp11 lists,
+but in general, arbitrary tuple-like types aren't, so we need to convert them into such. For that, we'll need to
+define a metafunction `from_tuple_like` that will take an arbitrary tuple-like type and will return, in our case,
+the corresponding `mp_list`.
+
+Technically, a more principled approach would've been to return `std::tuple`, but here `mp_list` will prove more
+convenient.
+
+What we need is, given a tuple-like type `Tp`, to obtain `mp_list<std::tuple_element<0, Tp>::type, std::tuple_element<1, Tp>::type,
+..., std::tuple_element<N-1, Tp>::type>`, where `N` is `tuple_size<Tp>::value`. Here's one way to do it:
+
+```
+template<class T, class I> using tuple_element =
+ typename std::tuple_element<I::value, T>::type;
+
+template<class T> using from_tuple_like =
+ mp_product<tuple_element, mp_list<T>, mp_iota<std::tuple_size<T>>>;
+```
+
+(`mp_iota<N>` is an algorithm that returns an `mp_list` with elements `mp_size_t<0>`, `mp_size_t<1>`, ..., `mp_size_t<N-1>`.)
+
+Remember that `mp_product<F, L1, L2>` performs the equivalent of two nested loops over the elements of `L1` and `L2`,
+applying `F` to the two variables and gathering the result. In our case `L1` consists of the single element `T`, so
+only the second loop (over `mp_iota<N>`, where `N` is `tuple_size<T>`), remains, and we get a list of the same type
+as `L1` (an `mp_list`) with contents `tuple_element<T, mp_size_t<0>>`, `tuple_element<T, mp_size_t<1>>`, ...,
+`tuple_element<T, mp_size_t<N-1>>`.
+
+For completeness's sake, here's another, more traditional way to achieve the same result:
+
+ template<class T> using from_tuple_like =
+ mp_transform_q<mp_bind_front<tuple_element, T>, mp_iota<std::tuple_size<T>>>;
+
+With all these fixes applied, our fully operational `tuple_cat` now looks like this:
+
+```
+template<class L> using F = mp_iota<mp_size<L>>;
+
+template<class R, class...Is, class... Ks, class Tp>
+R tuple_cat_( mp_list<Is...>, mp_list<Ks...>, Tp tp )
+{
+ return R{ std::get<Ks::value>(std::get<Is::value>(std::move(tp)))... };
+}
+
+template<class T> using remove_cv_ref = typename std::remove_cv<
+ typename std::remove_reference<T>::type>::type;
+
+template<class T, class I> using tuple_element =
+ typename std::tuple_element<I::value, T>::type;
+
+template<class T> using from_tuple_like =
+ mp_product<tuple_element, mp_list<T>, mp_iota<std::tuple_size<T>>>;
+
+template<class... Tp,
+ class R = mp_append<std::tuple<>, from_tuple_like<remove_cv_ref<Tp>>...>>
+ R tuple_cat( Tp &&... tp )
+{
+ std::size_t const N = sizeof...(Tp);
+
+ // inner
+
+ using list1 = mp_list<from_tuple_like<remove_cv_ref<Tp>>...>;
+ using list2 = mp_iota_c<N>;
+
+ using list3 = mp_transform<mp_fill, list1, list2>;
+
+ using inner = mp_apply<mp_append, list3>;
+
+ // outer
+
+ using list4 = mp_transform<F, list1>;
+
+ using outer = mp_apply<mp_append, list4>;
+
+ //
+
+ return tuple_cat_<R>( inner(), outer(),
+ std::forward_as_tuple( std::forward<Tp>(tp)... ) );
+}
+```
+
+## Computing Return Types
+
+C++17 has a standard variant type, called `std::variant`. It also defines a function template
+`std::visit` that can be used to apply a function to the contained value of one or more variants.
+So for instance, if the variant `v1` contains `1`, and the variant `v2` contains `2.0f`,
+`std::visit(f, v1, v2)` will call `f(1, 2.0f)`.
+
+However, `std::visit` has one limitation: it cannot return a result unless all
+possible applications of the function have the same return type. If, for instance, `v1` and `v2`
+are both of type `std::variant<short, int, float>`,
+
+ std::visit( []( auto const& x, auto const& y ){ return x + y; }, v1, v2 );
+
+will fail to compile because the result of `x + y` can be either `int` or `float` depending on
+what `v1` and `v2` hold.
+
+A type that can hold either `int` or `float` already exists, called, surprisingly enough, `std::variant<int, float>`.
+Let's write our own function template `rvisit` that is the same as `visit` but returns a `variant`:
+
+```
+template<class F, class... V> auto rvisit( F&& f, V&&... v )
+{
+ using R = /*...*/;
+
+ return std::visit( [&]( auto&&... x )
+ { return R( std::forward<F>(f)( std::forward<decltype(x)>(x)... ) ); },
+ std::forward<V>( v )... );
+}
+```
+
+What this does is basically calls `std::visit` to do the work, but instead of passing it `f`, we pass a lambda that does the same as `f` except
+it converts the result to a common type `R`. `R` is supposed to be `std::variant<...>` where the ellipsis denotes the return types of
+calling `f` with all possible combinations of variant values.
+
+We'll first define a helper quoted metafunction `Qret<F>` that returns the result of the application of `F` to arguments of type `T...`:
+
+ template<class F> struct Qret
+ {
+ template<class... T> using fn =
+ decltype( std::declval<F>()( std::declval<T>()... ) );
+ };
+
+(Unfortunately, we can't just define this metafunction inside `rvisit`; the language prohibits defining template aliases inside functions.)
+
+With `Qret` in hand, a `variant` of the possible return types is just a matter of applying it over the possible combinations of the variant values:
+
+ using R = mp_product_q<Qret<F>, std::remove_reference_t<V>...>;
+
+Why does this work? `mp_product<F, L1<T1...>, L2<T2...>, ..., Ln<Tn...>>` returns `L1<F<U1, U2, ..., Un>, ...>`, where `Ui` traverse all
+possible combinations of list values. Since in our case all `Li` are `std::variant`, the result will also be `std::variant`. (`mp_product_q` is
+the same as `mp_product`, but for quoted metafunctions such as our `Qret<F>`.)
+
+One more step remains. Suppose that, as above, we're passing two variants of type `std::variant<short, int, float>` and `F` is
+`[]( auto const& x, auto const& y ){ return x + y; }`. This will generate `R` of length 9, one per each combination, but many of those
+elements will be the same, either `int` or `float`, and we need to filter out the duplicates. So, we pass the result to `mp_unique`:
+
+ using R = mp_unique<mp_product_q<Qret<F>, std::remove_reference_t<V>...>>;
+
+and we're done:
+
+```
+#include <boost/mp11.hpp>
+#include <boost/core/demangle.hpp>
+#include <variant>
+#include <type_traits>
+#include <typeinfo>
+#include <iostream>
+
+using namespace boost::mp11;
+
+template<class F> struct Qret
+{
+ template<class... T> using fn =
+ decltype( std::declval<F>()( std::declval<T>()... ) );
+};
+
+template<class F, class... V> auto rvisit( F&& f, V&&... v )
+{
+ using R = mp_unique<mp_product_q<Qret<F>, std::remove_reference_t<V>...>>;
+
+ return std::visit( [&]( auto&&... x )
+ { return R( std::forward<F>(f)( std::forward<decltype(x)>(x)... ) ); },
+ std::forward<V>( v )... );
+}
+
+template<class T> std::string name()
+{
+ return boost::core::demangle( typeid(T).name() );
+}
+
+template<class V> void print_variant( char const * n, V const& v )
+{
+ std::cout << "(" << name<decltype(v)>() << ")" << n << ": ";
+
+ std::visit( []( auto const& x )
+ { std::cout << "(" << name<decltype(x)>() << ")" << x << std::endl; }, v );
+}
+
+int main()
+{
+ std::variant<char, int, float> v1( 1 );
+
+ print_variant( "v1", v1 );
+
+ std::variant<short, int, double> v2( 3.14 );
+
+ print_variant( "v2", v2 );
+
+ auto v3 = rvisit( []( auto const& x, auto const& y ){ return x + y; }, v1, v2 );
+
+ print_variant( "v3", v3 );
+}
+```
---
+++ libs\mp11\doc\mp11\function.adoc 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,108 @@
+////
+Copyright 2017 Peter Dimov
+
+Distributed under the Boost Software License, Version 1.0.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+[#function]
+# Helper Metafunctions, <boost/mp11/function.hpp>
+:toc:
+:toc-title:
+:idprefix:
+
+## mp_void<T...>
+
+ template<class... T> using mp_void = void;
+
+Same as `std::void_t` from C++17.
+
+## mp_and<T...>
+
+ template<class... T> using mp_and = /*...*/;
+
+`mp_and<T...>` applies `mp_to_bool` to the types in `T...`, in order. If the result of an application is `mp_false`, `mp_and`
+returns `mp_false`. If the application causes a substitution failure, returns `mp_false`. If all results are `mp_true`,
+returns `mp_true`. `mp_and<>` is `mp_true`.
+
+.mp_and behavior
+```
+using R1 = mp_and<mp_true, mp_true>; // mp_true
+
+using R2 = mp_and<mp_false, void>; // mp_false, void is not reached
+
+using R3 = mp_and<mp_false, mp_false>; // mp_false
+
+using R4 = mp_and<void, mp_true>; // mp_false (!)
+```
+
+## mp_all<T...>
+
+ template<class... T> using mp_all = /*...*/;
+
+`mp_all<T...>` is `mp_true` if `mp_to_bool<U>` is `mp_true` for all types `U` in `T...`, `mp_false` otherwise. Same as
+`mp_and`, but does not perform short-circuit evaluation. `mp_and<mp_false, void>` is `mp_false`, but `mp_all<mp_false, void>`
+is an error because `void` does not have a nested `value`. The upside is that `mp_all` is potentially faster and does not
+mask substitution failures as `mp_and` does.
+
+.mp_all behavior
+```
+using R1 = mp_all<mp_true, mp_true>; // mp_true
+
+using R2 = mp_all<mp_false, void>; // compile-time error
+
+using R3 = mp_all<mp_false, mp_false>; // mp_false
+
+using R4 = mp_all<void, mp_true>; // compile-time error
+```
+
+## mp_or<T...>
+
+ template<class... T> using mp_or = /*...*/;
+
+`mp_or<T...>` applies `mp_to_bool` to the types in `T...`, in order. If the result of an application is `mp_true`, `mp_or`
+returns `mp_true`. If all results are `mp_false`, returns `mp_false`. `mp_or<>` is `mp_false`.
+
+.mp_or behavior
+```
+using R1 = mp_or<mp_true, mp_false>; // mp_true
+
+using R2 = mp_or<mp_true, void>; // mp_true, void is not reached
+
+using R3 = mp_or<mp_false, mp_false>; // mp_false
+
+using R4 = mp_or<void, mp_true>; // compile-time error
+```
+
+## mp_any<T...>
+
+ template<class... T> using mp_any = /*...*/;
+
+`mp_any<T...>` is `mp_true` if `mp_to_bool<U>` is `mp_true` for any type `U` in `T...`, `mp_false` otherwise. Same as
+`mp_or`, but does not perform short-circuit evaluation.
+
+.mp_any behavior
+```
+using R1 = mp_any<mp_true, mp_false>; // mp_true
+
+using R2 = mp_any<mp_true, void>; // compile-time error
+
+using R3 = mp_any<mp_false, mp_false>; // mp_false
+
+using R4 = mp_any<void, mp_true>; // compile-time error
+```
+
+## mp_same<T...>
+
+ template<class... T> using mp_same = /*...*/;
+
+`mp_same<T...>` is `mp_true` if all the types in `T...` are the same type, `mp_false` otherwise. `mp_same<>` is `mp_true`.
+
+## mp_plus<T...>
+
+ template<class... T> using mp_plus = /*...*/;
+
+`mp_plus<T...>` is an integral constant type with a value that is the sum of `U::value` for all types `U` in `T...`.
+`mp_plus<>` is `mp_int<0>`.
---
+++ libs\mp11\doc\mp11\integer_sequence.adoc 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,48 @@
+////
+Copyright 2017 Peter Dimov
+
+Distributed under the Boost Software License, Version 1.0.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+[#integer_sequence]
+# Integer Sequences, <boost/mp11/integer_sequence.hpp>
+:toc:
+:toc-title:
+:idprefix:
+
+## integer_sequence<T, I...>
+
+ template<class T, T... I> struct integer_sequence
+ {
+ };
+
+`integer_sequence<T, I...>` holds a sequence of integers of type `T`. Same as C++14's `std::integer_sequence`.
+
+## make_integer_sequence<T, N>
+
+ template<class T, T N> using make_integer_sequence = /*...*/;
+
+`make_integer_sequence<T, N>` is `integer_sequence<T, 0, 1, ..., N-1>`. Same as C++14's `std::make_integer_sequence`.
+
+## index_sequence<I...>
+
+ template<std::size_t... I> using index_sequence = integer_sequence<std::size_t, I...>;
+
+`index_sequence<I...>` is an alias for `integer_sequence<size_t, I...>`. Same as C++14's `std::index_sequence`.
+
+## make_index_sequence<N>
+
+ template<std::size_t N> using make_index_sequence =
+ make_integer_sequence<std::size_t, N>;
+
+`make_index_sequence<N>` is `index_sequence<0, 1, ..., N-1>`. Same as C++14's `std::make_index_sequence`.
+
+## index_sequence_for<T...>
+
+ template<class... T> using index_sequence_for =
+ make_integer_sequence<std::size_t, sizeof...(T)>;
+
+`index_sequence_for<N>` is `make_index_sequence<sizeof...(T)>`. Same as C++14's `std::index_sequence_for`.
---
+++ libs\mp11\doc\mp11\integral.adoc 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,50 @@
+////
+Copyright 2017 Peter Dimov
+
+Distributed under the Boost Software License, Version 1.0.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+[#integral]
+# Integral Constants, <boost/mp11/integral.hpp>
+:toc:
+:toc-title:
+:idprefix:
+
+For an Mp11 integral constant type `T`, `T::value` is an integral constant in the C++ sense.
+
+## mp_bool<B>
+
+ template<bool B> using mp_bool = std::integral_constant<bool, B>;
+
+Same as `std::bool_constant` in C++17.
+
+## mp_true
+
+ using mp_true = mp_bool<true>;
+
+Same as `std::true_type`.
+
+## mp_false
+
+ using mp_false = mp_bool<false>;
+
+Same as `std::false_type`.
+
+## mp_to_bool<T>
+
+ template<class T> using mp_to_bool = mp_bool<static_cast<bool>(T::value)>;
+
+## mp_not<T>
+
+ template<class T> using mp_not = mp_bool< !T::value >;
+
+## mp_int<I>
+
+ template<int I> using mp_int = std::integral_constant<int, I>;
+
+## mp_size_t<N>
+
+ template<std::size_t N> using mp_size_t = std::integral_constant<std::size_t, N>;
---
+++ libs\mp11\doc\mp11\list.adoc 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,335 @@
+////
+Copyright 2017 Peter Dimov
+
+Distributed under the Boost Software License, Version 1.0.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+[#list]
+# List Operations, <boost/mp11/list.hpp>
+:toc:
+:toc-title:
+:idprefix:
+
+## mp_list<T...>
+
+ template<class... T> struct mp_list {};
+
+`mp_list` is the standard list type of Mp11, although the library is not restricted to it and can operate on arbitrary class templates
+such as `std::tuple` or `std::variant`. Even `std::pair` can be used if the transformation does not alter the number of the elements in
+the list.
+
+## mp_size<L>
+
+ template<class L> using mp_size = /*...*/;
+
+`mp_size<L>` returns the number of elements in the list `L`, as a `mp_size_t`. In other words, `mp_size<L<T...>>` is an alias for
+`mp_size_t<sizeof...(T)>`.
+
+.Using mp_size with mp_list
+```
+using L1 = mp_list<>;
+using R1 = mp_size<L1>; // mp_size_t\<0>
+```
+
+.Using mp_size with std::pair
+```
+using L2 = std::pair<int, int>;
+using R2 = mp_size<L2>; // mp_size_t\<2>
+```
+
+.Using mp_size with std::tuple
+```
+using L3 = std::tuple<float>;
+using R3 = mp_size<L3>; // mp_size_t\<1>
+```
+
+## mp_empty<L>
+
+ template<class L> using mp_empty = mp_bool<mp_size<L>::value == 0>;
+
+`mp_empty<L>` is an alias for `mp_true` if the list `L` is empty, for `mp_false` otherwise.
+
+.Using mp_empty with std::tuple
+```
+using L1 = std::tuple<float>;
+using R1 = mp_empty<L1>; // mp_false
+
+using L2 = std::tuple<>;
+using R2 = mp_empty<L2>; // mp_true
+```
+
+## mp_front<L>
+
+ template<class L> using mp_front = /*...*/;
+
+`mp_front<L>` is the first element of the list `L`. That is, `mp_front<L<T1, T...>>` is an alias for `T1`.
+
+.Using mp_front with std::pair
+```
+using L1 = std::pair<int, float>;
+using R1 = mp_front<L1>; // int
+```
+
+.Using mp_front with std::tuple
+```
+using L2 = std::tuple<float, double, long double>;
+using R2 = mp_front<L2>; // float
+```
+
+.Using mp_front with mp_list
+```
+using L3 = mp_list<char[1], char[2], char[3], char[4]>;
+using R3 = mp_front<L3>; // char[1]
+```
+
+## mp_pop_front<L>
+
+ template<class L> using mp_pop_front = /*...*/;
+
+`mp_pop_front<L>` removes the first element of the list `L`. That is, `mp_pop_front<L<T1, T...>>` is an alias for `L<T...>`.
+
+.Using mp_pop_front with std::tuple
+```
+using L1 = std::tuple<float, double, long double>;
+using R1 = mp_pop_front<L1>; // std::tuple<double, long double>
+```
+
+.Using mp_pop_front with mp_list
+```
+using L2 = mp_list<void>;
+using R2 = mp_pop_front<L2>; // mp_list<>
+```
+
+## mp_first<L>
+
+ template<class L> using mp_first = mp_front<L>;
+
+`mp_first` is another name for `mp_front`.
+
+## mp_rest<L>
+
+ template<class L> using mp_rest = mp_pop_front<L>;
+
+`mp_rest` is another name for `mp_pop_front`.
+
+## mp_second<L>
+
+ template<class L> using mp_second = /*...*/;
+
+`mp_second<L>` is the second element of the list `L`. That is, `mp_second<L<T1, T2, T...>>` is an alias for `T2`.
+
+.Using mp_second with std::pair
+```
+using L1 = std::pair<int, float>;
+using R1 = mp_second<L1>; // float
+```
+
+.Using mp_second with std::tuple
+```
+using L2 = std::tuple<float, double, long double>;
+using R2 = mp_second<L2>; // double
+```
+
+.Using mp_second with mp_list
+```
+using L3 = mp_list<char[1], char[2], char[3], char[4]>;
+using R3 = mp_second<L3>; // char[2]
+```
+
+## mp_third<L>
+
+ template<class L> using mp_third = /*...*/;
+
+`mp_third<L>` is the third element of the list `L`. That is, `mp_third<L<T1, T2, T3, T...>>` is an alias for `T3`.
+
+.Using mp_third with std::tuple
+```
+using L1 = std::tuple<float, double, long double>;
+using R1 = mp_third<L1>; // long double
+```
+
+.Using mp_third with mp_list
+```
+using L2 = mp_list<char[1], char[2], char[3], char[4]>;
+using R2 = mp_third<L2>; // char[3]
+```
+
+## mp_push_front<L, T...>
+
+ template<class L, class... T> using mp_push_front = /*...*/;
+
+`mp_push_front<L, T...>` inserts the elements `T...` at the front of the list `L`. That is, `mp_push_front<L<U...>, T...>`
+is an alias for `L<T..., U...>`.
+
+.Using mp_push_front with std::tuple
+```
+using L1 = std::tuple<double, long double>;
+using R1 = mp_push_front<L1, float>; // std::tuple<float, double, long double>
+```
+
+.Using mp_push_front with mp_list
+```
+using L2 = mp_list<void>;
+using R2 = mp_push_front<L2, char[1], char[2]>; // mp_list<char[1], char[2], void>
+```
+
+## mp_push_back<L, T...>
+
+ template<class L, class... T> using mp_push_back = /*...*/;
+
+`mp_push_back<L, T...>` inserts the elements `T...` at the back of the list `L`. That is, `mp_push_back<L<U...>, T...>`
+is an alias for `L<U..., T...>`.
+
+.Using mp_push_back with std::tuple
+```
+using L1 = std::tuple<double, long double>;
+using R1 = mp_push_back<L1, float>; // std::tuple<double, long double, float>
+```
+
+.Using mp_push_back with mp_list
+```
+using L2 = mp_list<void>;
+using R2 = mp_push_back<L2, char[1], char[2]>; // mp_list<void, char[1], char[2]>
+```
+
+## mp_rename<L, Y>
+
+ template<class L, template<class...> class Y> using mp_rename = /*...*/;
+
+`mp_rename<L, Y>` changes the type of the list `L` to `Y`. That is, `mp_rename<L<T...>, Y>` is an alias for `Y<T...>`.
+
+.Using mp_rename to rename std::pair to std::tuple
+```
+using L1 = std::pair<double, long double>;
+using R1 = mp_rename<L1, std::tuple>; // std::tuple<double, long double>
+```
+
+.Using mp_rename to rename std::tuple to mp_list
+```
+using L2 = std::tuple<void>;
+using R2 = mp_rename<L2, mp_list>; // mp_list<void>
+```
+
+## mp_apply<F, L>
+
+ template<template<class...> class F, class L> using mp_apply = mp_rename<L, F>;
+
+`mp_apply<F, L>` applies the metafunction `F` to the contents of the list `L`, that is, `mp_apply<F, L<T...>>` is an alias for `F<T...>`.
+(`mp_apply` is the same as `mp_rename` with the arguments reversed.)
+
+.Using mp_apply with std::pair
+```
+using L1 = std::pair<double, long double>;
+using R1 = mp_apply<std::is_same, L1>; // std::is_same<double, long double>
+```
+
+## mp_apply_q<Q, L>
+
+ template<class Q, class L> using mp_apply_q = mp_apply<Q::template fn, L>;
+
+Same as `mp_apply`, but takes a quoted metafunction.
+
+.Using mp_apply_q with mp_bind_front
+```
+using L1 = std::tuple<double, long double>;
+using L2 = mp_list<int, long>;
+
+using R1 = mp_apply_q<mp_bind_front<mp_push_back, L1>, L2>;
+ // R1 is std::tuple<double, long double, int, long>
+```
+
+## mp_append<L...>
+
+ template<class... L> using mp_append = /*...*/;
+
+`mp_append<L...>` concatenates the lists in `L...` into a single list that has the same type as the first list. `mp_append<>`
+is an alias for `mp_list<>`. `mp_append<L1<T1...>, L2<T2...>, ..., Ln<Tn...>>` is an alias for `L1<T1..., T2..., ..., Tn...>`.
+
+.Using mp_append with lists of various types
+```
+using L1 = std::tuple<double, long double>;
+using L2 = mp_list<int>;
+using L3 = std::pair<short, long>;
+using L4 = mp_list<>;
+
+using R1 = mp_append<L1, L2, L3, L4>;
+ // std::tuple<double, long double, int, short, long>
+```
+
+## mp_replace_front<L, T>
+
+ template<class L, class T> using mp_replace_front = /*...*/;
+
+`mp_replace_front<L, T>` replaces the first element of the list `L` with `T`. That is, `mp_replace_front<L<U1, U...>, T>` is
+an alias for `L<T, U...>`.
+
+.Using mp_replace_front with std::pair
+```
+using L1 = std::pair<int, float>;
+using R1 = mp_replace_front<L1, void>; // std::pair<void, float>
+```
+
+.Using mp_replace_front with std::tuple
+```
+using L2 = std::tuple<float, double, long double>;
+using R2 = mp_replace_front<L2, void>; // std::tuple<void, double, long double>
+```
+
+.Using mp_replace_front with mp_list
+```
+using L3 = mp_list<char[1], char[2], char[3], char[4]>;
+using R3 = mp_replace_front<L3, void>; // mp_list<void, char[2], char[3], char[4]>;
+```
+
+## mp_replace_first<L, T>
+
+ template<class L, class T> using mp_replace_first = mp_replace_front<L, T>;
+
+`mp_replace_first` is another name for `mp_replace_front`.
+
+## mp_replace_second<L, T>
+
+ template<class L, class T> using mp_replace_second = /*...*/;
+
+`mp_replace_second<L, T>` replaces the second element of the list `L` with `T`. That is, `mp_replace_second<L<U1, U2, U...>, T>`
+is an alias for `L<U1, T, U...>`.
+
+.Using mp_replace_second with std::pair
+```
+using L1 = std::pair<int, float>;
+using R1 = mp_replace_second<L1, void>; // std::pair<int, void>
+```
+
+.Using mp_replace_second with std::tuple
+```
+using L2 = std::tuple<float, double, long double>;
+using R2 = mp_replace_second<L2, void>; // std::tuple<float, void, long double>
+```
+
+.Using mp_replace_front with mp_list
+```
+using L3 = mp_list<char[1], char[2], char[3], char[4]>;
+using R3 = mp_replace_second<L3, void>; // mp_list<char[1], void, char[3], char[4]>;
+```
+
+## mp_replace_third<L, T>
+
+ template<class L, class T> using mp_replace_third = /*...*/;
+
+`mp_replace_third<L, T>` replaces the third element of the list `L` with `T`. That is, `mp_replace_third<L<U1, U2, U3, U...>, T>`
+is an alias for `L<U1, U2, T, U...>`.
+
+.Using mp_replace_third with std::tuple
+```
+using L1 = std::tuple<float, double, long double>;
+using R1 = mp_replace_third<L1, void>; // std::tuple<float, double, void>
+```
+
+.Using mp_replace_third with mp_list
+```
+using L2 = mp_list<char[1], char[2], char[3], char[4]>;
+using R2 = mp_replace_third<L2, void>; // mp_list<char[1], char[2], void, char[4]>;
+```
---
+++ libs\mp11\doc\mp11\map.adoc 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,68 @@
+////
+Copyright 2017 Peter Dimov
+
+Distributed under the Boost Software License, Version 1.0.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+[#map]
+# Map Operations, <boost/mp11/map.hpp>
+:toc:
+:toc-title:
+:idprefix:
+
+A map is a list of lists, the inner lists having at least one element (the key.) The keys of the map must be unique.
+
+## mp_is_map<M>
+
+ template<class M> using mp_is_map = /*...*/;
+
+`mp_is_map<M>` is `mp_true` if `M` is a map, `mp_false` otherwise.
+
+## mp_map_find<M, K>
+
+ template<class M, class K> using mp_map_find = /*...*/;
+
+`mp_map_find<M, K>` is an alias for the element of the map `M` with a key `K`, or for `void`, if there is no such element.
+
+## mp_map_contains<M, K>
+
+ template<class M, class K> using mp_map_contains =
+ mp_not<std::is_same<mp_map_find<M, K>, void>>;
+
+`mp_map_contains<M, K>` is `mp_true` if the map `M` contains an element with a key `K`, `mp_false` otherwise.
+
+## mp_map_insert<M, T>
+
+ template<class M, class T> using mp_map_insert =
+ mp_if< mp_map_contains<M, mp_first<T>>, M, mp_push_back<M, T> >;
+
+Inserts the element `T` into the map `M`, if an element with a key `mp_first<T>` is not already in `M`.
+
+## mp_map_replace<M, T>
+
+ template<class M, class T> using mp_map_replace = /*...*/;
+
+If the map `M` does not contain an element with a key `mp_first<T>`, inserts it (using `mp_push_back<M, T>`); otherwise,
+replaces the existing element with `T`.
+
+## mp_map_update<M, T, F>
+
+ template<class M, class T, template<class...> class F> using mp_map_update = /*...*/;
+
+If the map `M` does not contain an element with a key `mp_first<T>`, inserts it (using `mp_push_back<M, T>`); otherwise,
+replaces the existing element `L<X, Y...>` with `L<X, F<X, Y...>>`.
+
+## mp_map_erase<M, K>
+
+ template<class M, class K> using mp_map_erase = /*...*/;
+
+If the map `M` contains an element with a key `K`, removes it.
+
+## mp_map_keys<M>
+
+ template<class M> using mp_map_keys = mp_transform<mp_first, M>;
+
+`mp_map_keys<M>` returns a list of the keys of `M`. When `M` is a valid map, the keys are unique, so the result is a set.
---
+++ libs\mp11\doc\mp11\mp11.adoc 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,17 @@
+////
+Copyright 2017 Peter Dimov
+
+Distributed under the Boost Software License, Version 1.0.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+[#mp11]
+# Convenience Header, <boost/mp11.hpp>
+:toc:
+:toc-title:
+:idprefix:
+
+The convenience header `<boost/mp11.hpp>` includes all of the
+headers listed previously in this reference.
---
+++ libs\mp11\doc\mp11\mpl.adoc 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,20 @@
+////
+Copyright 2017 Peter Dimov
+
+Distributed under the Boost Software License, Version 1.0.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+[#mpl]
+# MPL Support, <boost/mp11/mpl.hpp>
+:toc:
+:toc-title:
+:idprefix:
+
+The header `<boost/mp11/mpl.hpp>`, when included, defines the
+necessary support infrastructure for `mp_list` and `std::tuple`
+to be valid link:../../../../libs/mpl[MPL] sequences.
+
+NOTE: `mpl.hpp` is not included by `<boost/mp11.hpp>`.
---
+++ libs\mp11\doc\mp11\overview.adoc 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,35 @@
+////
+Copyright 2017 Peter Dimov
+
+Distributed under the Boost Software License, Version 1.0.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+[#overview]
+# Overview
+
+Mp11 is a C++11 metaprogramming library for compile-time manipulation of data structures
+that contain types. It's based on template aliases and variadic templates and implements the
+approach outlined in the article
+<<simple_cxx11_metaprogramming.adoc#,"Simple {cpp} metaprogramming">>
+and <<simple_cxx11_metaprogramming_2.adoc#,its sequel>>. Reading these
+articles before proceeding with this documentation is _highly_ recommended.
+
+The general principles upon which Mp11 is built are that algorithms and metafunctions are
+template aliases of the form `F<T...>` and data structures are lists of the form `L<T...>`,
+with the library placing no requirements on `L`. `mp_list<T...>` is the built-in list type,
+but `std::tuple<T...>`, `std::pair<T1, T2>` and `std::variant<T...>` are also perfectly
+legitimate list types, although of course `std::pair<T1, T2>`, due to having exactly two elements,
+is not resizeable and will consequently not work with algorithms that need to add or remove
+elements.
+
+Another distinguishing feature of this approach is that lists (`L<T...>`) have the same form as
+metafunctions (`F<T...>`) and can therefore be used as such. For example, applying `std::add_pointer_t`
+to the list `std::tuple<int, float>` by way of `mp_transform<std::add_pointer_t, std::tuple<int, float>>`
+gives us `std::tuple<int*, float*>`, but we can also apply `mp_list` to the same tuple:
+
+ using R = mp_transform<mp_list, std::tuple<int, float>>;
+
+and get `std::tuple<mp_list<int>, mp_list<float>>`.
---
+++ libs\mp11\doc\mp11\reference.adoc 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,44 @@
+////
+Copyright 2017 Peter Dimov
+
+Distributed under the Boost Software License, Version 1.0.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+[#reference]
+# Reference
+:toc:
+:toc-title:
+:idprefix:
+
+The contents of the library are in namespace `boost::mp11`.
+
+:leveloffset: +1
+
+include::integral.adoc[]
+
+include::list.adoc[]
+
+include::utility.adoc[]
+
+include::algorithm.adoc[]
+
+include::set.adoc[]
+
+include::map.adoc[]
+
+include::function.adoc[]
+
+include::bind.adoc[]
+
+include::integer_sequence.adoc[]
+
+include::tuple.adoc[]
+
+include::mp11.adoc[]
+
+include::mpl.adoc[]
+
+:leveloffset: -1
---
+++ libs\mp11\doc\mp11\set.adoc 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,40 @@
+////
+Copyright 2017 Peter Dimov
+
+Distributed under the Boost Software License, Version 1.0.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+[#set]
+# Set Operations, <boost/mp11/set.hpp>
+:toc:
+:toc-title:
+:idprefix:
+
+A set is a list whose elements are unique.
+
+## mp_is_set<S>
+
+ template<class S> using mp_is_set = /*...*/;
+
+`mp_is_set<S>` is `mp_true` if `S` is a set, `mp_false` otherwise.
+
+## mp_set_contains<S, V>
+
+ template<class S, class V> using mp_set_contains = /*...*/;
+
+`mp_set_contains<S, V>` is `mp_true` if the type `V` is an element of the set `S`, `mp_false` otherwise.
+
+## mp_set_push_back<S, T...>
+
+ template<class S, class... T> using mp_set_push_back = /*...*/;
+
+For each `T1` in `T...`, `mp_set_push_back<S, T...>` appends `T1` to the end of `S` if it's not already an element of `S`.
+
+## mp_set_push_front<S, T...>
+
+ template<class S, class... T> using mp_set_push_front = /*...*/;
+
+`mp_set_push_front<S, T...>` inserts at the front of `S` those elements of `T...` for which `S` does not already contain the same type.
---
+++ libs\mp11\doc\mp11\tuple.adoc 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,38 @@
+////
+Copyright 2017 Peter Dimov
+
+Distributed under the Boost Software License, Version 1.0.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+[#tuple]
+# Tuple Operations, <boost/mp11/tuple.hpp>
+:toc:
+:toc-title:
+:idprefix:
+
+## tuple_apply(f, tp)
+
+ template<class F, class Tp> constexpr /*...*/ tuple_apply(F&& f, Tp&& tp);
+
+`tuple_apply(f, tp)` returns `std::forward<F>(f)(std::get<J>(std::forward<Tp>(tp))...)` for `J` in 0..`N-1`,
+where `N` is `std::tuple_size<typename std::remove_reference<Tp>::type>::value`. Same as `std::apply` in C++17.
+
+## construct_from_tuple<T>(tp)
+
+ template<class T, class Tp> T construct_from_tuple(Tp&& tp);
+
+`construct_from_tuple<T>(tp)` returns `T(std::get<J>(std::forward<Tp>(tp))...)` for `J` in 0..`N-1`,
+where `N` is `std::tuple_size<typename std::remove_reference<Tp>::type>::value`. Same as `std::make_from_tuple` in {cpp}17.
+The name of the function doesn't match the {cpp}17 one to avoid ambiguities when both are visible or in unqualified calls.
+
+## tuple_for_each(tp, f)
+
+ template<class Tp, class F> constexpr F tuple_for_each(Tp&& tp, F&& f);
+
+`tuple_for_each(tp, f)` applies the function object `f` to each element of `tp` by evaluating the
+expression `f(std::get<J>(std::forward<Tp>(tp)))` for `J` in 0..`N-1`, where `N` is `std::tuple_size<typename std::remove_reference<Tp>::type>::value`.
+
+Returns `std::forward<F>(f)`.
---
+++ libs\mp11\doc\mp11\utility.adoc 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,212 @@
+////
+Copyright 2017 Peter Dimov
+
+Distributed under the Boost Software License, Version 1.0.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+[#utility]
+# Utility Components, <boost/mp11/utility.hpp>
+:toc:
+:toc-title:
+:idprefix:
+
+## mp_identity<T>
+
+ template<class T> struct mp_identity
+ {
+ using type = T;
+ };
+
+`mp_identity` is a simple _transformation type trait_ (as per the C++ standard)
+that just returns the same type. It's useful both as such, and as a type wrapper
+useful for passing types as values to functions.
+
+.Using mp_identity as a type trait
+```
+template<class T> using addp_if_not_ref =
+ typename mp_if<std::is_reference<T>, mp_identity<T>, std::add_pointer<T>>::type;
+```
+
+.Using mp_identity to protect qualifiers and references
+```
+template<class T> void print1()
+{
+ std::cout << typeid(T).name() << std::endl;
+}
+
+template<class T> void print2()
+{
+ std::cout << typeid(mp_identity<T>).name() << std::endl;
+}
+
+int main()
+{
+ print1<int const&>(); // 'int'
+ print2<int const&>(); // 'mp_identity<int const &>'
+}
+```
+
+## mp_identity_t<T>
+
+ template<class T> using mp_identity_t = typename mp_identity<T>::type;
+
+## mp_inherit<T...>
+
+ template<class... T> struct mp_inherit: T... {};
+
+## mp_if_c<C, T, E...>
+
+ template<bool C, class T, class... E> using mp_if_c = /*...*/;
+
+`mp_if_c<true, T, E...>` is an alias for `T`. `mp_if_c<false, T, E>` is an alias for `E`. Otherwise, the result is a substitution failure.
+
+.Using mp_if_c to select between two alternatives
+```
+using R1 = mp_if_c<true, int, void>; // int
+
+using R2 = mp_if_c<false, int, void>; // void
+```
+
+.Using mp_if_c to fail substitution when a condition is not met
+```
+template<class I> using void_if_5 = mp_if_c<I::value == 5, void>;
+```
+This example returns `void` when `I::value` is 5, and generates a substitution failure
+otherwise. It's the same as `std::enable_if_t<I::value == 5>` in {cpp}14, or
+`typename std::enable_if<I::value == 5>::type` in {cpp}11.
+
+## mp_if<C, T, E...>
+
+ template<class C, class T, class E...> using mp_if =
+ mp_if_c<static_cast<bool>(C::value), T, E...>;
+
+Like `mp_if_c`, but the first argument is a type.
+
+.Using mp_if to select between two alternatives
+```
+using R1 = mp_if<mp_true, int, void>; // int
+
+using R2 = mp_if<mp_false, int, void>; // void
+```
+
+.Using mp_if to fail substitution when a condition is not met
+```
+template<class T> using void_if_const = mp_if<std::is_const<T>, void>;
+
+template<class... T> using void_if_all_const =
+ mp_if<mp_all<std::is_const<T>...>, void>;
+
+template<class T> using if_non_const = mp_if<mp_not<std::is_const<T>>, T>;
+```
+
+## mp_eval_if_c<C, T, F, U...>
+
+ template<bool C, class T, template<class...> class F, class... U> using mp_eval_if_c =
+ /*...*/;
+
+`mp_eval_if_c<C, T, F, U...>` is an alias for `T` when `C` is `true`, for `F<U...>` otherwise. Its purpose
+is to avoid evaluating `F<U...>` when the condition is `true` as it may not be valid in this case.
+
+.Using mp_eval_if_c to select the first pack element, or void
+```
+template<class... T> using first_or_void =
+ mp_eval_if_c<sizeof...(T) == 0, void, mp_apply, mp_first, mp_list<T...>>;
+```
+
+## mp_eval_if<C, T, F, U...>
+
+ template<class C, class T, template<class...> class F, class... U> using mp_eval_if =
+ mp_eval_if_c<static_cast<bool>(C::value), T, F, U...>;
+
+Like `mp_eval_if_c`, but the first argument is a type.
+
+.Using mp_eval_if to select the first list element, or void
+```
+template<class L> using first_or_void = mp_eval_if<mp_empty<L>, void, mp_first, L>;
+```
+
+## mp_eval_if_q<C, T, Q, U...>
+
+ template<class C, class T, class Q, class... U> using mp_eval_if_q =
+ mp_eval_if<C, T, Q::template fn, U...>;
+
+Like `mp_eval_if`, but takes a quoted metafunction.
+
+## mp_valid<F, T...>
+
+ template<template<class...> class F, class... T> using mp_valid = /*...*/;
+
+`mp_valid<F, T...>` is an alias for `mp_true` when `F<T...>` is a valid expression, for `mp_false` otherwise.
+
+.Using mp_valid to write a metafunction that checks for the existence of a nested type
+```
+template<class T> using get_nested_type = typename T::type;
+
+template<class T> struct has_nested_type: mp_valid<get_nested_type, T> {};
+```
+
+## mp_defer<F, T...>
+
+ template<template<class...> class F, class... T> using mp_defer = /*...*/;
+
+When `mp_valid<F, T...>` is `mp_true`, `mp_defer<F, T...>` is a struct with a nested type `type` which is an alias for `F<T...>`. Otherwise,
+`mp_defer<F, T...>` is an empty struct.
+
+## mp_quote<F>
+
+ template<template<class...> class F> struct mp_quote
+ {
+ template<class... T> using fn = F<T...>;
+ };
+
+`mp_quote<F>` transforms the template `F` into a type with a nested template `fn` such that `fn<T...>` returns `F<T...>`.
+
+.Using mp_quote to make a list of metafunctions
+```
+using LQ = mp_list<mp_quote<std::is_const>, mp_quote<std::is_volatile>>;
+```
+
+## mp_quote_trait<F>
+
+ template<template<class...> class F> struct mp_quote_trait
+ {
+ template<class... T> using fn = typename F<T...>::type;
+ };
+
+`mp_quote_trait<F>` transforms the C++03-style trait `F` into a quoted metafunction.
+
+.Using mp_quote_trait with std::add_pointer
+```
+using L1 = mp_list<int, void, float>;
+using R1 = mp_transform_q<mp_quote_trait<std::add_pointer>, L1>;
+ // mp_list<int*, void*, float*>
+```
+
+## mp_invoke<Q, T...>
+
+ template<class Q, class... T> using mp_invoke = typename Q::template fn<T...>;
+
+`mp_invoke<Q, T...>` evaluates the nested template `fn` of a quoted metafunction. `mp_invoke<mp_quote<F>, T...>` returns `F<T...>`.
+
+.Using mp_invoke to invoke a list of metafunctions, technique 1
+```
+using LQ = mp_list<mp_quote<std::is_const>, mp_quote<std::is_volatile>>;
+
+template<class T> using is_const_and_volatile =
+ mp_all<mp_product<mp_invoke, LQ, mp_list<T>>>;
+```
+
+.Using mp_invoke to invoke a list of metafunctions, technique 2
+```
+template<class T> using is_const_and_volatile =
+ mp_all<mp_transform_q<mp_bind_back<mp_invoke, T>, LQ>>;
+```
+
+.Using mp_invoke to invoke a list of metafunctions, technique 3
+```
+template<class T> using is_const_and_volatile =
+ mp_all<mp_transform<mp_invoke, LQ, mp_fill<LQ, T>>>;
+```
---
+++ libs\mp11\doc\asciidoctor.jam 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,50 @@
+# Copyright 2017 Peter Dimov
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import type ;
+import scanner ;
+import generators ;
+import boostbook ;
+
+# File type
+
+type.register ASCIIDOC : asciidoc adoc ;
+
+# Define dependency scanner
+
+class asciidoc-scanner : common-scanner
+{
+ rule pattern ( )
+ {
+ return "include::([^[]+)\\[" ;
+ }
+}
+
+scanner.register asciidoc-scanner : include ;
+type.set-scanner ASCIIDOC : asciidoc-scanner ;
+
+# Define generators
+
+generators.register-standard asciidoctor.asciidoc-to-html : ASCIIDOC : HTML ;
+generators.register-standard asciidoctor.asciidoc-to-pdf : ASCIIDOC : PDF ;
+# generators.register-standard asciidoctor.asciidoc-to-docbook : ASCIIDOC : DOCBOOK ;
+
+# Define actions
+
+actions asciidoc-to-html
+{
+ asciidoctor -b html -o $(1) $(2)
+}
+
+actions asciidoc-to-pdf
+{
+ asciidoctor -r asciidoctor-pdf -b pdf -o $(1) $(2)
+}
+
+actions asciidoc-to-docbook
+{
+ asciidoctor -b docbook -o $(1) $(2)
+}
---
+++ libs\mp11\doc\Jamfile 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,50 @@
+# Copyright 2017 Peter Dimov
+#
+# Distributed under the Boost Software License, Version 1.0.
+#
+# See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt
+
+project doc/mp11 ;
+
+import asciidoctor ;
+
+html mp11.html : mp11.adoc ;
+
+html simple_cxx11_metaprogramming.html :
+ article/simple_cxx11_metaprogramming.adoc ;
+
+html simple_cxx11_metaprogramming_2.html :
+ article/simple_cxx11_metaprogramming_2.adoc ;
+
+install html_ :
+ mp11.html
+ simple_cxx11_metaprogramming.html
+ simple_cxx11_metaprogramming_2.html :
+ <location>html ;
+
+pdf mp11.pdf : mp11.adoc ;
+
+pdf simple_cxx11_metaprogramming.pdf :
+ article/simple_cxx11_metaprogramming.adoc ;
+
+pdf simple_cxx11_metaprogramming_2.pdf :
+ article/simple_cxx11_metaprogramming_2.adoc ;
+
+explicit mp11.pdf
+ simple_cxx11_metaprogramming.pdf
+ simple_cxx11_metaprogramming_2.pdf ;
+
+install pdf_ :
+ mp11.pdf
+ simple_cxx11_metaprogramming.pdf
+ simple_cxx11_metaprogramming_2.pdf :
+ <location>pdf ;
+
+explicit pdf_ ;
+
+###############################################################################
+alias boostdoc ;
+explicit boostdoc ;
+alias boostrelease : html_ ;
+explicit boostrelease ;
---
+++ libs\mp11\doc\mp11.adoc 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,42 @@
+////
+Copyright 2017 Peter Dimov
+
+Distributed under the Boost Software License, Version 1.0.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+# Boost.Mp11: A C++11 metaprogramming library
+Peter Dimov
+:toc: left
+:toclevels: 3
+:idprefix:
+:listing-caption: Code Example
+:table-caption: Illustration
+:docinfo: private-footer
+
+:leveloffset: +1
+
+include::mp11/overview.adoc[]
+
+include::mp11/definitions.adoc[]
+
+include::mp11/examples.adoc[]
+
+include::mp11/reference.adoc[]
+
+:leveloffset: -1
+
+[appendix]
+## Copyright, License, and Acknowledgments
+
+This documentation is
+
+* Copyright 2017 Peter Dimov
+* Copyright 2017 Bjørn Reese
+
+and is distributed under the http://www.boost.org/LICENSE_1_0.txt[Boost Software License, Version 1.0].
+
+The "Simple {cpp}11 metaprogramming" articles have been graciously converted to Asciidoc format for incorporation
+into this documentation by Glen Fernandes.
---
+++ libs\mp11\doc\mp11-docinfo-footer.html 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,6 @@
+<style>
+
+*:not(pre)>code { background: none; color: #600000; }
+table tr.even, table tr.alt, table tr:nth-of-type(even) { background: none; }
+
+</style>
---
+++ libs\mp11\meta\libraries.json 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,14 @@
+{
+ "key": "mp11",
+ "name": "Mp11",
+ "authors": [
+ "Peter Dimov"
+ ],
+ "maintainers": [
+ "Peter Dimov <pdimov -at- pdimov.com>"
+ ],
+ "description": "Simple C++11 metaprogramming library.",
+ "category": [
+ "Metaprogramming"
+ ]
+}
---
+++ libs\mp11\test\construct_from_tuple.cpp 2017-08-28 02:56:56.000000000 -0700
@@ -0,0 +1,219 @@
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/tuple.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+#include <tuple>
+#include <memory>
+#include <utility>
+#include <array>
+
+struct T1
+{
+ int x, y, z;
+
+ T1( int x = 0, int y = 0, int z = 0 ): x(x), y(y), z(z) {}
+};
+
+struct T2
+{
+ std::unique_ptr<int> x, y, z;
+
+ T2( std::unique_ptr<int> x, std::unique_ptr<int> y, std::unique_ptr<int> z ): x(std::move(x)), y(std::move(y)), z(std::move(z)) {}
+
+#if BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
+
+ T2( T2&& r ): x( std::move(r.x) ), y( std::move(r.y) ), z( std::move(r.z) ) {}
+
+#endif
+};
+
+int main()
+{
+ using boost::mp11::construct_from_tuple;
+
+ {
+ std::tuple<int, short, char> tp{ 1, 2, 3 };
+
+ {
+ T1 t1 = construct_from_tuple<T1>( tp );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 3 );
+ }
+
+ {
+ T1 t1 = construct_from_tuple<T1>( std::move(tp) );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 3 );
+ }
+ }
+
+ {
+ std::tuple<int, short, char> const tp{ 1, 2, 3 };
+
+ {
+ T1 t1 = construct_from_tuple<T1>( tp );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 3 );
+ }
+
+ {
+ T1 t1 = construct_from_tuple<T1>( std::move(tp) );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 3 );
+ }
+ }
+
+#if defined( __clang_major__ ) && __clang_major__ == 3 && __clang_minor__ < 8
+#else
+
+ {
+ std::tuple<std::unique_ptr<int>, std::unique_ptr<int>, std::unique_ptr<int>> tp{ std::unique_ptr<int>(new int(1)), std::unique_ptr<int>(new int(2)), std::unique_ptr<int>(new int(3)) };
+
+ T2 t2 = construct_from_tuple<T2>( std::move(tp) );
+
+ BOOST_TEST_EQ( *t2.x, 1 );
+ BOOST_TEST_EQ( *t2.y, 2 );
+ BOOST_TEST_EQ( *t2.z, 3 );
+ }
+
+#endif
+
+ {
+ std::pair<int, short> tp{ 1, 2 };
+
+ {
+ T1 t1 = construct_from_tuple<T1>( tp );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 0 );
+ }
+
+ {
+ T1 t1 = construct_from_tuple<T1>( std::move(tp) );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 0 );
+ }
+ }
+
+ {
+ std::pair<int, short> const tp{ 1, 2 };
+
+ {
+ T1 t1 = construct_from_tuple<T1>( tp );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 0 );
+ }
+
+ {
+ T1 t1 = construct_from_tuple<T1>( std::move(tp) );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 0 );
+ }
+ }
+
+ {
+ std::array<int, 3> tp{{ 1, 2, 3 }};
+
+ {
+ T1 t1 = construct_from_tuple<T1>( tp );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 3 );
+ }
+
+ {
+ T1 t1 = construct_from_tuple<T1>( std::move(tp) );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 3 );
+ }
+ }
+
+ {
+ std::array<int, 3> const tp{{ 1, 2, 3 }};
+
+ {
+ T1 t1 = construct_from_tuple<T1>( tp );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 3 );
+ }
+
+ {
+ T1 t1 = construct_from_tuple<T1>( std::move(tp) );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 3 );
+ }
+ }
+
+ {
+ std::tuple<> tp;
+
+ {
+ T1 t1 = construct_from_tuple<T1>( tp );
+
+ BOOST_TEST_EQ( t1.x, 0 );
+ BOOST_TEST_EQ( t1.y, 0 );
+ BOOST_TEST_EQ( t1.z, 0 );
+ }
+
+ {
+ T1 t1 = construct_from_tuple<T1>( std::move(tp) );
+
+ BOOST_TEST_EQ( t1.x, 0 );
+ BOOST_TEST_EQ( t1.y, 0 );
+ BOOST_TEST_EQ( t1.z, 0 );
+ }
+ }
+
+ {
+ std::array<int, 0> tp;
+
+ {
+ T1 t1 = construct_from_tuple<T1>( tp );
+
+ BOOST_TEST_EQ( t1.x, 0 );
+ BOOST_TEST_EQ( t1.y, 0 );
+ BOOST_TEST_EQ( t1.z, 0 );
+ }
+
+ {
+ T1 t1 = construct_from_tuple<T1>( std::move(tp) );
+
+ BOOST_TEST_EQ( t1.x, 0 );
+ BOOST_TEST_EQ( t1.y, 0 );
+ BOOST_TEST_EQ( t1.z, 0 );
+ }
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\construct_from_tuple_cx.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,82 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/mp11/tuple.hpp>
+#include <boost/config.hpp>
+
+// Technically std::tuple isn't constexpr enabled in C++11, but it works with libstdc++
+
+#if defined( BOOST_NO_CXX11_CONSTEXPR ) || ( defined( _LIBCPP_VERSION ) && __cplusplus < 201400L )
+
+int main() {}
+
+#else
+
+#include <tuple>
+#include <array>
+#include <utility>
+
+struct T1
+{
+ int x, y, z;
+
+ constexpr T1( int x = 0, int y = 0, int z = 0 ): x(x), y(y), z(z) {}
+};
+
+int main()
+{
+ using boost::mp11::construct_from_tuple;
+
+ {
+ constexpr std::tuple<int, short, char> tp{ 1, 2, 3 };
+
+ constexpr auto r = construct_from_tuple<T1>( tp );
+
+ static_assert( r.x == 1, "r.x == 1" );
+ static_assert( r.y == 2, "r.y == 2" );
+ static_assert( r.z == 3, "r.z == 3" );
+ }
+
+ {
+ constexpr std::pair<short, char> tp{ 1, 2 };
+
+ constexpr auto r = construct_from_tuple<T1>( tp );
+
+ static_assert( r.x == 1, "r.x == 1" );
+ static_assert( r.y == 2, "r.y == 2" );
+ static_assert( r.z == 0, "r.z == 0" );
+ }
+
+ {
+ constexpr std::array<short, 3> tp{{ 1, 2, 3 }};
+
+ constexpr auto r = construct_from_tuple<T1>( tp );
+
+ static_assert( r.x == 1, "r.x == 1" );
+ static_assert( r.y == 2, "r.y == 2" );
+ static_assert( r.z == 3, "r.z == 3" );
+ }
+
+#if defined( __clang_major__ ) && __clang_major__ == 3 && __clang_minor__ < 9
+// "error: default initialization of an object of const type 'const std::tuple<>' without a user-provided default constructor"
+#else
+
+ {
+ constexpr std::tuple<> tp;
+
+ constexpr auto r = construct_from_tuple<T1>( tp );
+
+ static_assert( r.x == 0, "r.x == 0" );
+ static_assert( r.y == 0, "r.y == 0" );
+ static_assert( r.z == 0, "r.z == 0" );
+ }
+
+#endif
+}
+
+#endif
---
+++ libs\mp11\test\integer_sequence.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,59 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/integer_sequence.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+int main()
+{
+ using boost::mp11::integer_sequence;
+ using boost::mp11::make_integer_sequence;
+ using boost::mp11::index_sequence;
+ using boost::mp11::make_index_sequence;
+ using boost::mp11::index_sequence_for;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_integer_sequence<int, 0>, integer_sequence<int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_integer_sequence<int, 1>, integer_sequence<int, 0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_integer_sequence<int, 2>, integer_sequence<int, 0, 1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_integer_sequence<int, 3>, integer_sequence<int, 0, 1, 2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_integer_sequence<int, 4>, integer_sequence<int, 0, 1, 2, 3>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_integer_sequence<char, 0>, integer_sequence<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_integer_sequence<char, 1>, integer_sequence<char, 0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_integer_sequence<char, 2>, integer_sequence<char, 0, 1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_integer_sequence<char, 3>, integer_sequence<char, 0, 1, 2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_integer_sequence<char, 4>, integer_sequence<char, 0, 1, 2, 3>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_integer_sequence<std::size_t, 0>, integer_sequence<std::size_t>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_integer_sequence<std::size_t, 1>, integer_sequence<std::size_t, 0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_integer_sequence<std::size_t, 2>, integer_sequence<std::size_t, 0, 1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_integer_sequence<std::size_t, 3>, integer_sequence<std::size_t, 0, 1, 2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_integer_sequence<std::size_t, 4>, integer_sequence<std::size_t, 0, 1, 2, 3>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_index_sequence<0>, integer_sequence<std::size_t>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_index_sequence<1>, integer_sequence<std::size_t, 0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_index_sequence<2>, integer_sequence<std::size_t, 0, 1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_index_sequence<3>, integer_sequence<std::size_t, 0, 1, 2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_index_sequence<4>, integer_sequence<std::size_t, 0, 1, 2, 3>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_index_sequence<0>, index_sequence<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_index_sequence<1>, index_sequence<0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_index_sequence<2>, index_sequence<0, 1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_index_sequence<3>, index_sequence<0, 1, 2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<make_index_sequence<4>, index_sequence<0, 1, 2, 3>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<index_sequence_for<>, index_sequence<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<index_sequence_for<void>, index_sequence<0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<index_sequence_for<void, void>, index_sequence<0, 1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<index_sequence_for<void, void, void>, index_sequence<0, 1, 2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<index_sequence_for<void, void, void, void>, index_sequence<0, 1, 2, 3>>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\integral.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,70 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <cstddef>
+
+int main()
+{
+ using boost::mp11::mp_bool;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bool<false>, std::integral_constant<bool, false>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bool<true>, std::integral_constant<bool, true>>));
+
+ using boost::mp11::mp_true;
+ using boost::mp11::mp_false;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_false, std::integral_constant<bool, false>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_true, std::integral_constant<bool, true>>));
+
+ using boost::mp11::mp_int;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_int<0>, std::integral_constant<int, 0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_int<814>, std::integral_constant<int, 814>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_int<-144>, std::integral_constant<int, -144>>));
+
+ using boost::mp11::mp_size_t;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_size_t<0>, std::integral_constant<std::size_t, 0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_size_t<1972>, std::integral_constant<std::size_t, 1972>>));
+
+ using boost::mp11::mp_to_bool;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_to_bool<mp_false>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_to_bool<mp_true>, mp_true>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_to_bool<mp_int<0>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_to_bool<mp_int<1>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_to_bool<mp_int<107>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_to_bool<mp_int<-1>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_to_bool<mp_int<-91>>, mp_true>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_to_bool<mp_size_t<0>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_to_bool<mp_size_t<1>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_to_bool<mp_size_t<442>>, mp_true>));
+
+ using boost::mp11::mp_not;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_not<mp_false>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_not<mp_true>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_not<mp_int<0>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_not<mp_int<1>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_not<mp_int<107>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_not<mp_int<-1>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_not<mp_int<-91>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_not<mp_size_t<0>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_not<mp_size_t<1>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_not<mp_size_t<442>>, mp_false>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\Jamfile 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,136 @@
+# Boost.Mp11 Library Test Jamfile
+#
+# Copyright 2015-2017 Peter Dimov
+#
+# Distributed under the Boost Software License, Version 1.0.
+# See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt
+
+import testing ;
+import ../../config/checks/config : requires ;
+
+project : requirements [ requires cxx11_variadic_templates cxx11_template_aliases cxx11_decltype cxx11_hdr_tuple ] ;
+
+# include-only
+compile mp11.cpp ;
+
+# list
+run mp_size.cpp ;
+run mp_empty.cpp ;
+run mp_front.cpp ;
+run mp_pop_front.cpp ;
+run mp_second.cpp ;
+run mp_third.cpp ;
+run mp_push_front.cpp ;
+run mp_push_back.cpp ;
+run mp_rename.cpp ;
+run mp_append.cpp ;
+run mp_append_2.cpp ;
+run mp_replace_front.cpp ;
+run mp_replace_second.cpp ;
+run mp_replace_third.cpp ;
+run mp_apply_q.cpp ;
+
+# algorithm
+run mp_assign.cpp ;
+run mp_clear.cpp ;
+run mp_transform.cpp ;
+run mp_transform_q.cpp ;
+run mp_transform_sf.cpp ;
+run mp_transform_if.cpp ;
+run mp_transform_if_q.cpp ;
+run mp_fill.cpp ;
+run mp_count.cpp ;
+run mp_count_if.cpp ;
+run mp_contains.cpp ;
+run mp_repeat.cpp ;
+run mp_product.cpp ;
+run mp_drop.cpp ;
+run mp_iota.cpp ;
+run mp_at.cpp ;
+run mp_at_sf.cpp ;
+run mp_take.cpp ;
+run mp_replace.cpp ;
+run mp_replace_if.cpp ;
+run mp_copy_if.cpp ;
+run mp_remove.cpp ;
+run mp_remove_if.cpp ;
+run mp_partition.cpp ;
+run mp_sort.cpp ;
+run mp_find.cpp ;
+run mp_find_if.cpp ;
+run mp_reverse.cpp ;
+run mp_fold.cpp ;
+run mp_reverse_fold.cpp ;
+run mp_unique.cpp ;
+run mp_all_of.cpp ;
+run mp_any_of.cpp ;
+run mp_none_of.cpp ;
+run mp_replace_at.cpp ;
+run mp_replace_at_c.cpp ;
+run mp_for_each.cpp ;
+run mp_insert.cpp ;
+run mp_erase.cpp ;
+run mp_with_index.cpp ;
+run mp_with_index_cx.cpp ;
+
+# integral
+run integral.cpp ;
+
+# utility
+run mp_identity.cpp ;
+run mp_inherit.cpp ;
+run mp_if.cpp ;
+run mp_if_sf.cpp ;
+run mp_eval_if.cpp ;
+run mp_eval_if_sf.cpp ;
+run mp_valid.cpp ;
+run mp_defer.cpp ;
+run mp_quote.cpp ;
+run mp_invoke.cpp ;
+run mp_invoke_sf.cpp ;
+run mp_quote_trait.cpp ;
+
+# integer_sequence
+run integer_sequence.cpp ;
+
+# tuple
+run tuple_for_each.cpp ;
+compile tuple_for_each_cx.cpp ;
+run tuple_apply.cpp ;
+compile tuple_apply_cx.cpp ;
+run construct_from_tuple.cpp ;
+compile construct_from_tuple_cx.cpp ;
+
+# set
+run mp_set_contains.cpp ;
+run mp_set_push_back.cpp ;
+run mp_set_push_front.cpp ;
+run mp_is_set.cpp ;
+
+# function
+run mp_all.cpp ;
+run mp_and.cpp ;
+run mp_any.cpp ;
+run mp_or.cpp ;
+run mp_same.cpp ;
+run mp_plus.cpp ;
+
+# map
+run mp_map_find.cpp ;
+run mp_map_contains.cpp ;
+run mp_map_insert.cpp ;
+run mp_map_replace.cpp ;
+run mp_map_erase.cpp ;
+run mp_map_update.cpp ;
+run mp_map_keys.cpp ;
+run mp_is_map.cpp ;
+
+# bind
+run mp_bind.cpp ;
+run mp_bind_q.cpp ;
+run mp_bind_front.cpp ;
+run mp_bind_back.cpp ;
+
+# mpl
+run mpl.cpp ;
---
+++ libs\mp11\test\mp_all.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,69 @@
+
+// Copyright 2015, 2016 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/function.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+using boost::mp11::mp_all;
+
+template<class V, class... T> using check1 = mp_all<std::is_same<V, void>, std::is_copy_constructible<T>..., std::is_copy_assignable<T>...>;
+template<class V, class... T> using check2 = mp_all<std::is_same<V, void>, mp_all<std::is_copy_constructible<T>..., mp_all<std::is_copy_assignable<T>...>>>;
+
+int main()
+{
+ using boost::mp11::mp_true;
+ using boost::mp11::mp_false;
+ using boost::mp11::mp_int;
+ using boost::mp11::mp_size_t;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<>, mp_true>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_true>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_false>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_int<-7>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_int<0>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_size_t<7>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_size_t<0>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_true, mp_true>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_false, mp_true>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_true, mp_false>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_false, mp_false>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_int<-7>, mp_int<7>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_size_t<(size_t)-1>, mp_size_t<1>>, mp_true>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_true, mp_true, mp_true>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_true, mp_false, mp_true>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_false, mp_false, mp_false>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_true, mp_true, mp_true, mp_true>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_true, mp_false, mp_true, mp_true>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_false, mp_false, mp_false, mp_false>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_int<1>, mp_int<2>, mp_int<-11>, mp_int<14>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_int<1>, mp_int<0>, mp_int<-11>, mp_int<14>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_size_t<1>, mp_size_t<2>, mp_size_t<114>, mp_size_t<8>, mp_size_t<94>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all<mp_size_t<1>, mp_size_t<2>, mp_size_t<114>, mp_size_t<0>, mp_size_t<94>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<check1<void, int, float>, mp_true>));
+
+#if !BOOST_WORKAROUND( BOOST_GCC, < 40900 )
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<check2<void, int, float>, mp_true>));
+
+#endif
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_all_of.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,57 @@
+
+// Copyright 2015, 2016 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_all_of;
+ using boost::mp11::mp_true;
+ using boost::mp11::mp_false;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all_of<L1, std::is_const>, mp_true>));
+
+ using L2 = mp_list<X1 const, X1 const, X1 const volatile, X1 const, X1 const volatile>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all_of<L2, std::is_volatile>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all_of<L2, std::is_const>, mp_true>));
+ }
+
+ {
+ using L1 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all_of<L1, std::is_const>, mp_true>));
+
+ using L2 = std::tuple<X1 const, X1 const, X1 const volatile, X1 const, X1 const volatile>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all_of<L2, std::is_volatile>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all_of<L2, std::is_const>, mp_true>));
+ }
+
+ {
+ using L2 = std::pair<X1 const, X1 const volatile>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all_of<L2, std::is_volatile>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_all_of<L2, std::is_const>, mp_true>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_and.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,64 @@
+
+// Copyright 2015-2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/function.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+int main()
+{
+ using boost::mp11::mp_and;
+ using boost::mp11::mp_true;
+ using boost::mp11::mp_false;
+ using boost::mp11::mp_int;
+ using boost::mp11::mp_size_t;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<>, mp_true>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_true>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_false>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<-7>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<0>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_size_t<7>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_size_t<0>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_true, mp_true>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_true, mp_false>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_false, void>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<-4>, mp_int<5>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<-4>, mp_int<0>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<0>, void>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_size_t<7>, mp_size_t<8>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_size_t<7>, mp_size_t<0>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_size_t<0>, void>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_true, mp_true, mp_true>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_true, mp_true, mp_false>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_true, mp_false, void>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_false, void, void>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_true, mp_true, mp_true, mp_true>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_true, mp_true, mp_true, mp_false>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_true, mp_true, mp_false, void>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_true, mp_false, void, void>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_false, void, void, void>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<1>, mp_int<2>, mp_int<-11>, mp_int<14>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<1>, mp_int<0>, void, void>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_size_t<1>, mp_size_t<2>, mp_size_t<114>, mp_size_t<8>, mp_size_t<94>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_size_t<1>, mp_size_t<2>, mp_size_t<0>, void, void>, mp_false>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_any.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,81 @@
+
+// Copyright 2015, 2016 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/function.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+using boost::mp11::mp_any;
+using boost::mp11::mp_all;
+
+template<class... T> using check1 = mp_any<std::is_nothrow_copy_constructible<T>..., mp_any<std::is_nothrow_move_constructible<T>...>>;
+template<class... T> using check2 = mp_any<mp_any<std::is_nothrow_copy_constructible<T>...>, std::is_nothrow_move_constructible<T>...>;
+template<class... T> using check3 = mp_any<mp_all<std::is_nothrow_copy_constructible<T>...>, std::is_nothrow_default_constructible<T>...>;
+
+template<bool is_trivially_destructible, bool is_single_buffered, class... T> struct variant_base_impl {};
+#if BOOST_WORKAROUND( BOOST_GCC, < 40800 )
+template<class... T> using variant_base = variant_base_impl<mp_all<std::has_trivial_destructor<T>...>::value, mp_any<mp_all<std::is_nothrow_move_constructible<T>...>, std::is_nothrow_default_constructible<T>...>::value, T...>;
+#else
+template<class... T> using variant_base = variant_base_impl<mp_all<std::is_trivially_destructible<T>...>::value, mp_any<mp_all<std::is_nothrow_move_constructible<T>...>, std::is_nothrow_default_constructible<T>...>::value, T...>;
+#endif
+
+int main()
+{
+ using boost::mp11::mp_true;
+ using boost::mp11::mp_false;
+ using boost::mp11::mp_int;
+ using boost::mp11::mp_size_t;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_true>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_false>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_int<-7>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_int<0>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_size_t<7>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_size_t<0>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_true, mp_true>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_false, mp_true>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_true, mp_false>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_false, mp_false>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_int<-7>, mp_int<7>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_size_t<(size_t)-1>, mp_size_t<1>>, mp_true>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_true, mp_true, mp_true>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_false, mp_false, mp_true>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_false, mp_false, mp_false>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_true, mp_true, mp_true, mp_true>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_false, mp_false, mp_true, mp_false>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_false, mp_false, mp_false, mp_false>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_int<1>, mp_int<2>, mp_int<-11>, mp_int<14>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_int<0>, mp_int<0>, mp_int<-11>, mp_int<0>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_int<0>, mp_int<0>, mp_int<0>, mp_int<0>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_size_t<1>, mp_size_t<2>, mp_size_t<114>, mp_size_t<8>, mp_size_t<94>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_size_t<0>, mp_size_t<0>, mp_size_t<114>, mp_size_t<0>, mp_size_t<0>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_size_t<0>, mp_size_t<0>, mp_size_t<0>, mp_size_t<0>, mp_size_t<0>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_size_t<0>, mp_int<0>, mp_false, mp_size_t<141>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any<mp_size_t<0>, mp_int<0>, mp_false>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<check1<void, int, float>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<check2<void, int, float>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<check3<void, int, float>, mp_true>));
+
+ variant_base<void, int, float>();
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_any_of.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,72 @@
+
+// Copyright 2015, 2016 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_any_of;
+ using boost::mp11::mp_true;
+ using boost::mp11::mp_false;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any_of<L1, std::is_const>, mp_false>));
+
+ using L2 = mp_list<X1, X1 const, X1, X1, X1>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any_of<L2, std::is_volatile>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any_of<L2, std::is_const>, mp_true>));
+
+ using L3 = mp_list<X1 const, X1 const, X1, X1 const, X1>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any_of<L3, std::is_volatile>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any_of<L3, std::is_const>, mp_true>));
+ }
+
+ {
+ using L1 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any_of<L1, std::is_const>, mp_false>));
+
+ using L2 = std::tuple<X1, X1 const, X1, X1, X1>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any_of<L2, std::is_volatile>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any_of<L2, std::is_const>, mp_true>));
+
+ using L3 = std::tuple<X1 const, X1 const, X1, X1 const, X1>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any_of<L3, std::is_volatile>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any_of<L3, std::is_const>, mp_true>));
+ }
+
+ {
+ using L2 = std::pair<X1 const, X1>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any_of<L2, std::is_volatile>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any_of<L2, std::is_const>, mp_true>));
+
+ using L3 = std::pair<X1 const, X1 const>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any_of<L3, std::is_volatile>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_any_of<L3, std::is_const>, mp_true>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_append.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,76 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/core/lightweight_test_trait.hpp>
+#include <boost/mp11/list.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+struct X4 {};
+struct X5 {};
+struct X6 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_append;
+
+ using L1 = mp_list<char[1], char[1]>;
+ using L2 = mp_list<char[2], char[2]>;
+ using L3 = mp_list<char[3], char[3]>;
+ using L4 = mp_list<char[4], char[4]>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<L1>, mp_list<char[1], char[1]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<L1, L2>, mp_list<char[1], char[1], char[2], char[2]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<L1, L2, L3>, mp_list<char[1], char[1], char[2], char[2], char[3], char[3]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<L1, L2, L3, L4>, mp_list<char[1], char[1], char[2], char[2], char[3], char[3], char[4], char[4]>>));
+
+ //
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::tuple<>>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::tuple<>, std::tuple<X1>>, std::tuple<X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::tuple<>, std::tuple<X1>, std::tuple<X2>>, std::tuple<X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::tuple<>, std::tuple<X1>, std::tuple<X2>, std::tuple<X3>>, std::tuple<X1, X2, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::tuple<>, std::tuple<X1>, std::tuple<X2>, std::tuple<X3>, std::tuple<X4>>, std::tuple<X1, X2, X3, X4>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::tuple<>, std::tuple<X1>, std::tuple<X2>, std::tuple<X3>, std::tuple<X4>, std::tuple<X5>>, std::tuple<X1, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::tuple<>, std::tuple<X1>, std::tuple<X2>, std::tuple<X3>, std::tuple<X4>, std::tuple<X5>, std::tuple<X6>>, std::tuple<X1, X2, X3, X4, X5, X6>>));
+
+ //
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::tuple<>, mp_list<>>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::tuple<>, mp_list<X1>>, std::tuple<X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::tuple<>, mp_list<X1>, std::tuple<X2>>, std::tuple<X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::tuple<>, mp_list<X1>, std::tuple<X2>, mp_list<X3>>, std::tuple<X1, X2, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::tuple<>, mp_list<X1>, std::tuple<X2>, mp_list<X3>, std::tuple<X4>>, std::tuple<X1, X2, X3, X4>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::tuple<>, mp_list<X1>, std::tuple<X2>, mp_list<X3>, std::tuple<X4>, mp_list<X5>>, std::tuple<X1, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::tuple<>, mp_list<X1>, std::tuple<X2>, mp_list<X3>, std::tuple<X4>, mp_list<X5>, std::tuple<X6>>, std::tuple<X1, X2, X3, X4, X5, X6>>));
+
+ //
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::tuple<>, std::pair<X1, X2>>, std::tuple<X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::tuple<>, std::pair<X1, X2>, std::pair<X3, X4>>, std::tuple<X1, X2, X3, X4>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::tuple<>, std::pair<X1, X2>, std::pair<X3, X4>, std::pair<X5, X6>>, std::tuple<X1, X2, X3, X4, X5, X6>>));
+
+ //
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::pair<X1, X2>>, std::pair<X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::pair<X1, X2>, mp_list<>>, std::pair<X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::pair<X1, X2>, mp_list<>, mp_list<>>, std::pair<X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::pair<X1, X2>, mp_list<>, mp_list<>, mp_list<>>, std::pair<X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_append<std::pair<X1, X2>, mp_list<>, mp_list<>, mp_list<>, mp_list<>>, std::pair<X1, X2>>));
+
+ //
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_append_2.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,38 @@
+
+// Copyright 2015-2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/core/lightweight_test_trait.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+template<class T> struct W;
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_append;
+ using boost::mp11::mp_iota_c;
+ using boost::mp11::mp_transform;
+ using boost::mp11::mp_rename;
+ using boost::mp11::mp_push_front;
+
+ using L1 = mp_iota_c<125>;
+ using L2 = mp_transform<W, L1>;
+ using L3 = mp_push_front<L2, mp_list<>>;
+ using L4 = mp_rename<L3, mp_append>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<L4, L1>));
+
+ //
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_apply_q.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,113 @@
+
+// Copyright 2015-2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/core/lightweight_test_trait.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/utility.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+template<class... T> struct X {};
+template<class... T> using Y = X<T...>;
+
+struct Q
+{
+ template<class... T> using fn = X<T...>;
+};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_quote;
+ using boost::mp11::mp_apply_q;
+
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<mp_list>, L1>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<std::tuple>, L1>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<X>, L1>, X<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<Y>, L1>, Y<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<Q, L1>, X<>>));
+
+ using L2 = mp_list<char>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<mp_list>, L2>, mp_list<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<std::tuple>, L2>, std::tuple<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<X>, L2>, X<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<Y>, L2>, Y<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<Q, L2>, X<char>>));
+
+ using L3 = mp_list<char, double>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<mp_list>, L3>, mp_list<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<std::tuple>, L3>, std::tuple<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<X>, L3>, X<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<Y>, L3>, Y<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<std::pair>, L3>, std::pair<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<Q, L3>, X<char, double>>));
+
+ using L4 = mp_list<int, char, float>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<mp_list>, L4>, mp_list<int, char, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<std::tuple>, L4>, std::tuple<int, char, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<X>, L4>, X<int, char, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<Y>, L4>, Y<int, char, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<Q, L4>, X<int, char, float>>));
+
+ //
+
+ using L5 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<mp_list>, L5>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<std::tuple>, L5>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<X>, L5>, X<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<Y>, L5>, Y<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<Q, L5>, X<>>));
+
+ using L6 = std::tuple<char>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<mp_list>, L6>, mp_list<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<std::tuple>, L6>, std::tuple<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<X>, L6>, X<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<Y>, L6>, Y<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<Q, L6>, X<char>>));
+
+ using L7 = std::tuple<char, double>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<mp_list>, L7>, mp_list<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<std::tuple>, L7>, std::tuple<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<X>, L7>, X<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<Y>, L7>, Y<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<std::pair>, L7>, std::pair<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<Q, L7>, X<char, double>>));
+
+ using L8 = std::tuple<int, char, float>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<mp_list>, L8>, mp_list<int, char, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<std::tuple>, L8>, std::tuple<int, char, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<X>, L8>, X<int, char, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<Y>, L8>, Y<int, char, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<Q, L8>, X<int, char, float>>));
+
+ //
+
+ using L9 = std::pair<char, double>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<mp_list>, L9>, mp_list<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<std::tuple>, L9>, std::tuple<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<X>, L9>, X<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<Y>, L9>, Y<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<mp_quote<std::pair>, L9>, std::pair<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply_q<Q, L9>, X<char, double>>));
+
+ //
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_assign.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,65 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/core/lightweight_test_trait.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_assign;
+
+ using L1 = mp_list<int, void(), float[]>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_assign<L1, mp_list<>>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_assign<L1, mp_list<X1>>, mp_list<X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_assign<L1, mp_list<X1, X2>>, mp_list<X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_assign<L1, mp_list<X1, X2, X3>>, mp_list<X1, X2, X3>>));
+
+ //
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_assign<L1, std::tuple<>>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_assign<L1, std::tuple<X1>>, mp_list<X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_assign<L1, std::tuple<X1, X2>>, mp_list<X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_assign<L1, std::tuple<X1, X2, X3>>, mp_list<X1, X2, X3>>));
+
+ //
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_assign<L1, std::pair<X1, X2>>, mp_list<X1, X2>>));
+
+ //
+
+ using L2 = std::tuple<int, char, float>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_assign<L2, mp_list<>>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_assign<L2, mp_list<X1>>, std::tuple<X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_assign<L2, mp_list<X1, X2>>, std::tuple<X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_assign<L2, mp_list<X1, X2, X3>>, std::tuple<X1, X2, X3>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_assign<L2, std::pair<X1, X2>>, std::tuple<X1, X2>>));
+
+ //
+
+ using L3 = std::pair<int, char>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_assign<L3, mp_list<X1, X2>>, std::pair<X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_assign<L3, std::pair<X1, X2>>, std::pair<X1, X2>>));
+
+ //
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_at.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,74 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+struct X4 {};
+struct X5 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_at;
+ using boost::mp11::mp_at_c;
+ using boost::mp11::mp_size_t;
+
+ {
+ using L1 = mp_list<X1, X2, X3, X4, X5>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at_c<L1, 0>, X1>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at_c<L1, 1>, X2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at_c<L1, 2>, X3>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at_c<L1, 3>, X4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at_c<L1, 4>, X5>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at<L1, mp_size_t<0>>, X1>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at<L1, mp_size_t<1>>, X2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at<L1, mp_size_t<2>>, X3>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at<L1, mp_size_t<3>>, X4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at<L1, mp_size_t<4>>, X5>));
+ }
+
+ {
+ using L1 = std::tuple<X1, X2, X3, X4, X5>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at_c<L1, 0>, X1>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at_c<L1, 1>, X2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at_c<L1, 2>, X3>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at_c<L1, 3>, X4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at_c<L1, 4>, X5>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at<L1, mp_size_t<0>>, X1>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at<L1, mp_size_t<1>>, X2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at<L1, mp_size_t<2>>, X3>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at<L1, mp_size_t<3>>, X4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at<L1, mp_size_t<4>>, X5>));
+ }
+
+ {
+ using L1 = std::pair<X1, X2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at_c<L1, 0>, X1>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at_c<L1, 1>, X2>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at<L1, mp_size_t<0>>, X1>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_at<L1, mp_size_t<1>>, X2>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_at_sf.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,39 @@
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/utility.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+using boost::mp11::mp_valid;
+using boost::mp11::mp_at;
+using boost::mp11::mp_size_t;
+using boost::mp11::mp_list;
+
+int main()
+{
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_at>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_at, void>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_at, void, void>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_at, void, void, void>));
+
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_at, void, mp_size_t<0>>));
+
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_at, mp_list<>, mp_size_t<0>>));
+
+ BOOST_TEST_TRAIT_TRUE((mp_valid<mp_at, mp_list<void>, mp_size_t<0>>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_at, mp_list<void>, mp_size_t<1>>));
+
+ BOOST_TEST_TRAIT_TRUE((mp_valid<mp_at, mp_list<void, void>, mp_size_t<0>>));
+ BOOST_TEST_TRAIT_TRUE((mp_valid<mp_at, mp_list<void, void>, mp_size_t<1>>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_at, mp_list<void, void>, mp_size_t<2>>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_bind.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,106 @@
+
+// Copyright 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/bind.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+struct X4 {};
+struct X5 {};
+struct X6 {};
+struct X7 {};
+struct X8 {};
+struct X9 {};
+
+template<class T> using add_pointer = typename std::add_pointer<T>::type;
+
+int main()
+{
+ using namespace boost::mp11;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<_1::fn<X1>, X1>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<_1::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X1>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<_2::fn<X1, X2>, X2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<_2::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X2>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<_3::fn<X1, X2, X3>, X3>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<_3::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X3>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<_4::fn<X1, X2, X3, X4>, X4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<_4::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X4>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<_5::fn<X1, X2, X3, X4, X5>, X5>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<_5::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X5>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<_6::fn<X1, X2, X3, X4, X5, X6>, X6>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<_6::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X6>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<_7::fn<X1, X2, X3, X4, X5, X6, X7>, X7>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<_7::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X7>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<_8::fn<X1, X2, X3, X4, X5, X6, X7, X8>, X8>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<_8::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X8>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<_9::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X9>));
+
+ //
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind<add_pointer, _1>::fn<X1>, X1*>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind<add_pointer, _1>::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X1*>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind<add_pointer, _2>::fn<X1, X2>, X2*>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind<add_pointer, _2>::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X2*>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind<add_pointer, _3>::fn<X1, X2, X3>, X3*>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind<add_pointer, _3>::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X3*>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind<add_pointer, _4>::fn<X1, X2, X3, X4>, X4*>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind<add_pointer, _4>::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X4*>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind<add_pointer, _5>::fn<X1, X2, X3, X4, X5>, X5*>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind<add_pointer, _5>::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X5*>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind<add_pointer, _6>::fn<X1, X2, X3, X4, X5, X6>, X6*>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind<add_pointer, _6>::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X6*>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind<add_pointer, _7>::fn<X1, X2, X3, X4, X5, X6, X7>, X7*>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind<add_pointer, _7>::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X7*>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind<add_pointer, _8>::fn<X1, X2, X3, X4, X5, X6, X7, X8>, X8*>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind<add_pointer, _8>::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X8*>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind<add_pointer, _9>::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X9*>));
+
+ //
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<
+ mp_bind<std::tuple,
+ mp_bind<add_pointer, _9>,
+ mp_bind<add_pointer, _8>,
+ mp_bind<add_pointer, _7>,
+ mp_bind<add_pointer, _6>,
+ mp_bind<add_pointer, _5>,
+ mp_bind<add_pointer, _4>,
+ mp_bind<add_pointer, _3>,
+ mp_bind<add_pointer, _2>,
+ mp_bind<add_pointer, _1>
+ >::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, std::tuple<X9*, X8*, X7*, X6*, X5*, X4*, X3*, X2*, X1*>>));
+
+ //
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_bind_back.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,63 @@
+
+// Copyright 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/bind.hpp>
+#include <boost/mp11/utility.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+template<class...> struct L {};
+template<class, class> struct P {};
+
+template<class T, class U> using is_base_of_t = typename std::is_base_of<T, U>::type;
+
+struct B1 {};
+struct B2 {};
+struct D: B1, B2 {};
+struct NB {};
+
+int main()
+{
+ using namespace boost::mp11;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_back<L, char[1], char[2]>::fn<int[1], int[2], int[3]>, L<int[1], int[2], int[3], char[1], char[2]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_back_q<mp_quote<L>, char[1], char[2]>::fn<int[1], int[2], int[3]>, L<int[1], int[2], int[3], char[1], char[2]>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_back<P, char[1]>::fn<int[1]>, P<int[1], char[1]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_back_q<mp_quote<P>, char[1]>::fn<int[1]>, P<int[1], char[1]>>));
+
+ //
+
+ using L1 = L<B1, B2, NB>;
+
+ {
+ using L2 = mp_transform<mp_bind_back<is_base_of_t, D>::fn, L1>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<L2, L<std::true_type, std::true_type, std::false_type>>));
+ }
+
+ {
+ using L2 = mp_transform_q<mp_bind_back<is_base_of_t, D>, L1>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<L2, L<std::true_type, std::true_type, std::false_type>>));
+ }
+
+ {
+ using L2 = mp_transform<mp_bind_back_q<mp_quote<is_base_of_t>, D>::fn, L1>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<L2, L<std::true_type, std::true_type, std::false_type>>));
+ }
+
+ {
+ using L2 = mp_transform_q<mp_bind_back_q<mp_quote<is_base_of_t>, D>, L1>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<L2, L<std::true_type, std::true_type, std::false_type>>));
+ }
+
+ //
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_bind_front.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,63 @@
+
+// Copyright 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/bind.hpp>
+#include <boost/mp11/utility.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+template<class...> struct L {};
+template<class, class> struct P {};
+
+template<class T, class U> using is_base_of_t = typename std::is_base_of<T, U>::type;
+
+struct B {};
+struct D1: B {};
+struct D2: B {};
+struct ND {};
+
+int main()
+{
+ using namespace boost::mp11;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_front<L, char[1], char[2]>::fn<int[1], int[2], int[3]>, L<char[1], char[2], int[1], int[2], int[3]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_front_q<mp_quote<L>, char[1], char[2]>::fn<int[1], int[2], int[3]>, L<char[1], char[2], int[1], int[2], int[3]>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_front<P, char[1]>::fn<int[1]>, P<char[1], int[1]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_front_q<mp_quote<P>, char[1]>::fn<int[1]>, P<char[1], int[1]>>));
+
+ //
+
+ using L1 = L<D1, D2, ND>;
+
+ {
+ using L2 = mp_transform<mp_bind_front<is_base_of_t, B>::fn, L1>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<L2, L<std::true_type, std::true_type, std::false_type>>));
+ }
+
+ {
+ using L2 = mp_transform_q<mp_bind_front<is_base_of_t, B>, L1>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<L2, L<std::true_type, std::true_type, std::false_type>>));
+ }
+
+ {
+ using L2 = mp_transform<mp_bind_front_q<mp_quote<is_base_of_t>, B>::fn, L1>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<L2, L<std::true_type, std::true_type, std::false_type>>));
+ }
+
+ {
+ using L2 = mp_transform_q<mp_bind_front_q<mp_quote<is_base_of_t>, B>, L1>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<L2, L<std::true_type, std::true_type, std::false_type>>));
+ }
+
+ //
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_bind_q.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,62 @@
+
+// Copyright 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/bind.hpp>
+#include <boost/mp11/utility.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+struct X4 {};
+struct X5 {};
+struct X6 {};
+struct X7 {};
+struct X8 {};
+struct X9 {};
+
+template<class T> using add_pointer = typename std::add_pointer<T>::type;
+
+int main()
+{
+ using namespace boost::mp11;
+
+ using Q_addp = mp_quote<add_pointer>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_q<Q_addp, _1>::fn<X1>, X1*>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_q<Q_addp, _1>::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X1*>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_q<Q_addp, _2>::fn<X1, X2>, X2*>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_q<Q_addp, _2>::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X2*>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_q<Q_addp, _3>::fn<X1, X2, X3>, X3*>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_q<Q_addp, _3>::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X3*>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_q<Q_addp, _4>::fn<X1, X2, X3, X4>, X4*>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_q<Q_addp, _4>::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X4*>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_q<Q_addp, _5>::fn<X1, X2, X3, X4, X5>, X5*>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_q<Q_addp, _5>::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X5*>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_q<Q_addp, _6>::fn<X1, X2, X3, X4, X5, X6>, X6*>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_q<Q_addp, _6>::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X6*>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_q<Q_addp, _7>::fn<X1, X2, X3, X4, X5, X6, X7>, X7*>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_q<Q_addp, _7>::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X7*>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_q<Q_addp, _8>::fn<X1, X2, X3, X4, X5, X6, X7, X8>, X8*>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_q<Q_addp, _8>::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X8*>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_bind_q<Q_addp, _9>::fn<X1, X2, X3, X4, X5, X6, X7, X8, X9>, X9*>));
+
+ //
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_clear.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,33 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/core/lightweight_test_trait.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_clear;
+
+ using L1 = mp_list<int, void(), float[]>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_clear<L1>, mp_list<>>));
+
+ //
+
+ using L2 = std::tuple<int, char, float>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_clear<L2>, std::tuple<>>));
+
+ //
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_contains.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,64 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_contains;
+ using boost::mp11::mp_true;
+ using boost::mp11::mp_false;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_contains<L1, void>, mp_false>));
+
+ using L2 = mp_list<X1, X2, X3, X2, X3, X3>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_contains<L2, void>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_contains<L2, X1>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_contains<L2, X2>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_contains<L2, X3>, mp_true>));
+ }
+
+ {
+ using L3 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_contains<L3, void>, mp_false>));
+
+ using L4 = std::tuple<X1, X2, X3, X2, X3, X3>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_contains<L4, void>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_contains<L4, X1>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_contains<L4, X2>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_contains<L4, X3>, mp_true>));
+ }
+
+ {
+ using L5 = std::pair<X1, X2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_contains<L5, void>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_contains<L5, X1>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_contains<L5, X2>, mp_true>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_copy_if.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,67 @@
+
+// Copyright 2015-2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+
+using boost::mp11::mp_bool;
+
+template<class N> using is_even = mp_bool<N::value % 2 == 0>;
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_copy_if;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_copy_if<L1, std::is_const>, L1>));
+
+ using L2 = mp_list<X1, X1 const, X1*, X2 const, X2*, X3*>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_copy_if<L2, std::is_volatile>, L1>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_copy_if<L2, std::is_const>, mp_list<X1 const, X2 const>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_copy_if<L2, std::is_pointer>, mp_list<X1*, X2*, X3*>>));
+ }
+
+ {
+ using L1 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_copy_if<L1, std::is_const>, L1>));
+
+ using L2 = std::tuple<X1, X1 const, X1*, X2 const, X2*, X3*>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_copy_if<L2, std::is_volatile>, L1>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_copy_if<L2, std::is_const>, std::tuple<X1 const, X2 const>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_copy_if<L2, std::is_pointer>, std::tuple<X1*, X2*, X3*>>));
+ }
+
+ using boost::mp11::mp_iota_c;
+ using boost::mp11::mp_size_t;
+
+ {
+ int const N = 12;
+ using L1 = mp_iota_c<N>;
+
+ using R1 = mp_copy_if<L1, is_even>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<R1, mp_list<mp_size_t<0>, mp_size_t<2>, mp_size_t<4>, mp_size_t<6>, mp_size_t<8>, mp_size_t<10>>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_count.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,63 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_count;
+ using boost::mp11::mp_size_t;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count<L1, void>, mp_size_t<0>>));
+
+ using L2 = mp_list<X1, X2, X3, X2, X3, X3>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count<L2, void>, mp_size_t<0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count<L2, X1>, mp_size_t<1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count<L2, X2>, mp_size_t<2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count<L2, X3>, mp_size_t<3>>));
+ }
+
+ {
+ using L3 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count<L3, void>, mp_size_t<0>>));
+
+ using L4 = std::tuple<X1, X2, X3, X2, X3, X3>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count<L4, void>, mp_size_t<0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count<L4, X1>, mp_size_t<1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count<L4, X2>, mp_size_t<2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count<L4, X3>, mp_size_t<3>>));
+ }
+
+ {
+ using L5 = std::pair<X1, X2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count<L5, void>, mp_size_t<0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count<L5, X1>, mp_size_t<1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count<L5, X2>, mp_size_t<1>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_count_if.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,59 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_count_if;
+ using boost::mp11::mp_size_t;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count_if<L1, std::is_const>, mp_size_t<0>>));
+
+ using L2 = mp_list<X1, X1 const, X1*, X1 const, X1*, X1*>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count_if<L2, std::is_volatile>, mp_size_t<0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count_if<L2, std::is_const>, mp_size_t<2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count_if<L2, std::is_pointer>, mp_size_t<3>>));
+ }
+
+ {
+ using L1 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count_if<L1, std::is_const>, mp_size_t<0>>));
+
+ using L2 = std::tuple<X1, X1 const, X1*, X1 const, X1*, X1*>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count_if<L2, std::is_volatile>, mp_size_t<0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count_if<L2, std::is_const>, mp_size_t<2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count_if<L2, std::is_pointer>, mp_size_t<3>>));
+ }
+
+ {
+ using L2 = std::pair<X1 const, X1*>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count_if<L2, std::is_volatile>, mp_size_t<0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count_if<L2, std::is_const>, mp_size_t<1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_count_if<L2, std::is_pointer>, mp_size_t<1>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_defer.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,46 @@
+
+// Copyright 2015-2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/utility.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+using boost::mp11::mp_identity;
+using boost::mp11::mp_true;
+using boost::mp11::mp_false;
+
+template<class T> struct has_type
+{
+ template<class U> static mp_true f( mp_identity<typename U::type>* );
+ template<class U> static mp_false f( ... );
+
+ using type = decltype( f<T>(0) );
+
+ static const bool value = type::value;
+};
+
+using boost::mp11::mp_defer;
+
+template<class T> using add_pointer = T*;
+template<class... T> using add_pointer_impl = mp_defer<add_pointer, T...>;
+
+int main()
+{
+ BOOST_TEST_TRAIT_TRUE((has_type<add_pointer_impl<void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<add_pointer_impl<void>::type, void*>));
+
+ BOOST_TEST_TRAIT_TRUE((has_type<add_pointer_impl<int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<add_pointer_impl<int>::type, int*>));
+
+ BOOST_TEST_TRAIT_FALSE((has_type<add_pointer_impl<>>));
+ BOOST_TEST_TRAIT_FALSE((has_type<add_pointer_impl<void, void>>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_drop.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,85 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+struct X4 {};
+struct X5 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_drop;
+ using boost::mp11::mp_drop_c;
+ using boost::mp11::mp_size_t;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop_c<L1, 0>, L1>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop<L1, mp_size_t<0>>, L1>));
+
+ using L2 = mp_list<X1, X2, X3, X4, X5>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop_c<L2, 0>, mp_list<X1, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop_c<L2, 1>, mp_list<X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop_c<L2, 2>, mp_list<X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop_c<L2, 3>, mp_list<X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop_c<L2, 4>, mp_list<X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop_c<L2, 5>, mp_list<>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop<L2, mp_size_t<0>>, mp_list<X1, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop<L2, mp_size_t<1>>, mp_list<X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop<L2, mp_size_t<2>>, mp_list<X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop<L2, mp_size_t<3>>, mp_list<X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop<L2, mp_size_t<4>>, mp_list<X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop<L2, mp_size_t<5>>, mp_list<>>));
+ }
+
+ {
+ using L1 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop_c<L1, 0>, L1>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop<L1, mp_size_t<0>>, L1>));
+
+ using L2 = std::tuple<X1, X2, X3, X4, X5>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop_c<L2, 0>, std::tuple<X1, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop_c<L2, 1>, std::tuple<X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop_c<L2, 2>, std::tuple<X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop_c<L2, 3>, std::tuple<X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop_c<L2, 4>, std::tuple<X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop_c<L2, 5>, std::tuple<>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop<L2, mp_size_t<0>>, std::tuple<X1, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop<L2, mp_size_t<1>>, std::tuple<X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop<L2, mp_size_t<2>>, std::tuple<X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop<L2, mp_size_t<3>>, std::tuple<X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop<L2, mp_size_t<4>>, std::tuple<X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop<L2, mp_size_t<5>>, std::tuple<>>));
+ }
+
+ {
+ using L1 = std::pair<X1, X2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop_c<L1, 0>, L1>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_drop<L1, mp_size_t<0>>, L1>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_empty.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,49 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/core/lightweight_test_trait.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_empty;
+ using boost::mp11::mp_true;
+ using boost::mp11::mp_false;
+
+ using L1 = mp_list<>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_empty<L1>, mp_true>));
+
+ using L2 = mp_list<void>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_empty<L2>, mp_false>));
+
+ using L3 = mp_list<int[], void, float>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_empty<L3>, mp_false>));
+
+ using L4 = std::tuple<>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_empty<L4>, mp_true>));
+
+ using L5 = std::tuple<int>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_empty<L5>, mp_false>));
+
+ using L6 = std::tuple<int, int>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_empty<L6>, mp_false>));
+
+ using L7 = std::pair<char, double>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_empty<L7>, mp_false>));
+
+ using L8 = std::add_const<void()>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_empty<L8>, mp_false>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_erase.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,171 @@
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+struct X4 {};
+struct X5 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_erase;
+ using boost::mp11::mp_erase_c;
+ using boost::mp11::mp_size_t;
+
+ using _0 = mp_size_t<0>;
+ using _1 = mp_size_t<1>;
+ using _2 = mp_size_t<2>;
+ using _3 = mp_size_t<3>;
+ using _4 = mp_size_t<4>;
+ using _5 = mp_size_t<5>;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L1, 0, 0>, L1>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L1, _0, _0>, L1>));
+
+ using L2 = mp_list<X1, X2, X3, X4, X5>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 0, 0>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 1, 1>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 2, 2>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 3, 3>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 4, 4>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 5, 5>, L2>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _0, _0>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _1, _1>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _2, _2>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _3, _3>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _4, _4>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _5, _5>, L2>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 0, 1>, mp_list<X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 1, 2>, mp_list<X1, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 2, 3>, mp_list<X1, X2, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 3, 4>, mp_list<X1, X2, X3, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 4, 5>, mp_list<X1, X2, X3, X4>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _0, _1>, mp_list<X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _1, _2>, mp_list<X1, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _2, _3>, mp_list<X1, X2, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _3, _4>, mp_list<X1, X2, X3, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _4, _5>, mp_list<X1, X2, X3, X4>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 0, 2>, mp_list<X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 1, 3>, mp_list<X1, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 2, 4>, mp_list<X1, X2, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 3, 5>, mp_list<X1, X2, X3>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _0, _2>, mp_list<X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _1, _3>, mp_list<X1, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _2, _4>, mp_list<X1, X2, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _3, _5>, mp_list<X1, X2, X3>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 0, 3>, mp_list<X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 1, 4>, mp_list<X1, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 2, 5>, mp_list<X1, X2>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _0, _3>, mp_list<X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _1, _4>, mp_list<X1, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _2, _5>, mp_list<X1, X2>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 0, 4>, mp_list<X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 1, 5>, mp_list<X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 0, 5>, mp_list<>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _0, _4>, mp_list<X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _1, _5>, mp_list<X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _0, _5>, mp_list<>>));
+
+ using L3 = mp_list<X1, X2, X3, X4, X5, X1, X2, X3, X4, X5, X1, X2, X3, X4, X5, X1, X2, X3, X4, X5>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L3, 8, 18>, mp_list<X1, X2, X3, X4, X5, X1, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L3, mp_size_t<8>, mp_size_t<18>>, mp_list<X1, X2, X3, X4, X5, X1, X2, X3, X4, X5>>));
+ }
+
+ {
+ using L1 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L1, 0, 0>, L1>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L1, _0, _0>, L1>));
+
+ using L2 = std::tuple<X1, X2, X3, X4, X5>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 0, 0>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 1, 1>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 2, 2>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 3, 3>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 4, 4>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 5, 5>, L2>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _0, _0>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _1, _1>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _2, _2>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _3, _3>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _4, _4>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _5, _5>, L2>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 0, 1>, std::tuple<X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 1, 2>, std::tuple<X1, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 2, 3>, std::tuple<X1, X2, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 3, 4>, std::tuple<X1, X2, X3, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 4, 5>, std::tuple<X1, X2, X3, X4>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _0, _1>, std::tuple<X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _1, _2>, std::tuple<X1, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _2, _3>, std::tuple<X1, X2, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _3, _4>, std::tuple<X1, X2, X3, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _4, _5>, std::tuple<X1, X2, X3, X4>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 0, 2>, std::tuple<X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 1, 3>, std::tuple<X1, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 2, 4>, std::tuple<X1, X2, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 3, 5>, std::tuple<X1, X2, X3>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _0, _2>, std::tuple<X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _1, _3>, std::tuple<X1, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _2, _4>, std::tuple<X1, X2, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _3, _5>, std::tuple<X1, X2, X3>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 0, 3>, std::tuple<X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 1, 4>, std::tuple<X1, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 2, 5>, std::tuple<X1, X2>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _0, _3>, std::tuple<X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _1, _4>, std::tuple<X1, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _2, _5>, std::tuple<X1, X2>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 0, 4>, std::tuple<X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 1, 5>, std::tuple<X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L2, 0, 5>, std::tuple<>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _0, _4>, std::tuple<X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _1, _5>, std::tuple<X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L2, _0, _5>, std::tuple<>>));
+
+ using L3 = std::tuple<X1, X2, X3, X4, X5, X1, X2, X3, X4, X5, X1, X2, X3, X4, X5, X1, X2, X3, X4, X5>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase_c<L3, 8, 18>, std::tuple<X1, X2, X3, X4, X5, X1, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_erase<L3, mp_size_t<8>, mp_size_t<18>>, std::tuple<X1, X2, X3, X4, X5, X1, X2, X3, X4, X5>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_eval_if.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,52 @@
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/utility.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+int main()
+{
+ using boost::mp11::mp_eval_if_c;
+ using boost::mp11::mp_identity;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_eval_if_c<true, char[], mp_identity, void, void, void>, char[]>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_eval_if_c<false, char[], mp_identity, void()>, mp_identity<void()>>));
+
+ using boost::mp11::mp_eval_if;
+ using boost::mp11::mp_eval_if_q;
+ using boost::mp11::mp_quote;
+
+ using qt_identity = mp_quote<mp_identity>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_eval_if<std::true_type, char[], mp_identity, void, void, void>, char[]>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_eval_if<std::false_type, char[], mp_identity, void()>, mp_identity<void()>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_eval_if_q<std::true_type, char[], qt_identity, void, void, void>, char[]>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_eval_if_q<std::false_type, char[], qt_identity, void()>, mp_identity<void()>>));
+
+ using boost::mp11::mp_int;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_eval_if<mp_int<-7>, char[], mp_identity, void, void, void>, char[]>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_eval_if<mp_int<0>, char[], mp_identity, void()>, mp_identity<void()>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_eval_if_q<mp_int<-7>, char[], qt_identity, void, void, void>, char[]>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_eval_if_q<mp_int<0>, char[], qt_identity, void()>, mp_identity<void()>>));
+
+ using boost::mp11::mp_size_t;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_eval_if<mp_size_t<14>, char[], mp_identity, void, void, void>, char[]>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_eval_if<mp_size_t<0>, char[], mp_identity, void()>, mp_identity<void()>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_eval_if_q<mp_size_t<14>, char[], qt_identity, void, void, void>, char[]>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_eval_if_q<mp_size_t<0>, char[], qt_identity, void()>, mp_identity<void()>>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_eval_if_sf.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,47 @@
+
+// Copyright 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/utility.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+using boost::mp11::mp_eval_if;
+using boost::mp11::mp_eval_if_q;
+using boost::mp11::mp_identity_t;
+using boost::mp11::mp_valid;
+using boost::mp11::mp_quote;
+
+template<class C, class... A> using eval_if = mp_eval_if<C, void, mp_identity_t, A...>;
+
+int main()
+{
+ BOOST_TEST_TRAIT_TRUE((mp_valid<eval_if, std::true_type>));
+ BOOST_TEST_TRAIT_TRUE((mp_valid<eval_if, std::true_type, void>));
+ BOOST_TEST_TRAIT_TRUE((mp_valid<eval_if, std::true_type, void, void>));
+ BOOST_TEST_TRAIT_TRUE((mp_valid<eval_if, std::true_type, void, void, void>));
+
+ BOOST_TEST_TRAIT_FALSE((mp_valid<eval_if, std::false_type>));
+ BOOST_TEST_TRAIT_TRUE((mp_valid<eval_if, std::false_type, void>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<eval_if, std::false_type, void, void>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<eval_if, std::false_type, void, void, void>));
+
+ using Qi = mp_quote<mp_identity_t>;
+
+ BOOST_TEST_TRAIT_TRUE((mp_valid<mp_eval_if_q, std::true_type, void, Qi>));
+ BOOST_TEST_TRAIT_TRUE((mp_valid<mp_eval_if_q, std::true_type, void, Qi, void>));
+ BOOST_TEST_TRAIT_TRUE((mp_valid<mp_eval_if_q, std::true_type, void, Qi, void, void>));
+ BOOST_TEST_TRAIT_TRUE((mp_valid<mp_eval_if_q, std::true_type, void, Qi, void, void, void>));
+
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_eval_if_q, std::false_type, void, Qi>));
+ BOOST_TEST_TRAIT_TRUE((mp_valid<mp_eval_if_q, std::false_type, void, Qi, void>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_eval_if_q, std::false_type, void, Qi, void, void>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_eval_if_q, std::false_type, void, Qi, void, void, void>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_fill.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,40 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/core/lightweight_test_trait.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_fill;
+
+ using L1 = mp_list<int, void(), float[]>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_fill<L1, X1>, mp_list<X1, X1, X1>>));
+
+ //
+
+ using L2 = std::tuple<int, char, float>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_fill<L2, X1>, std::tuple<X1, X1, X1>>));
+
+ //
+
+ using L3 = std::pair<char, double>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_fill<L3, X1>, std::pair<X1, X1>>));
+
+ //
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_find.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,63 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_find;
+ using boost::mp11::mp_size_t;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find<L1, void>, mp_size_t<0>>));
+
+ using L2 = mp_list<X1, X2, X2, X3, X3, X3>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find<L2, void>, mp_size_t<6>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find<L2, X1>, mp_size_t<0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find<L2, X2>, mp_size_t<1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find<L2, X3>, mp_size_t<3>>));
+ }
+
+ {
+ using L3 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find<L3, void>, mp_size_t<0>>));
+
+ using L4 = std::tuple<X1, X2, X2, X3, X3, X3>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find<L4, void>, mp_size_t<6>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find<L4, X1>, mp_size_t<0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find<L4, X2>, mp_size_t<1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find<L4, X3>, mp_size_t<3>>));
+ }
+
+ {
+ using L5 = std::pair<X1, X2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find<L5, void>, mp_size_t<2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find<L5, X1>, mp_size_t<0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find<L5, X2>, mp_size_t<1>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_find_if.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,59 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_find_if;
+ using boost::mp11::mp_size_t;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find_if<L1, std::is_const>, mp_size_t<0>>));
+
+ using L2 = mp_list<X1, X1 const, X1 const, X1*, X1*, X1*>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find_if<L2, std::is_volatile>, mp_size_t<6>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find_if<L2, std::is_const>, mp_size_t<1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find_if<L2, std::is_pointer>, mp_size_t<3>>));
+ }
+
+ {
+ using L1 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find_if<L1, std::is_const>, mp_size_t<0>>));
+
+ using L2 = std::tuple<X1, X1 const, X1 const, X1*, X1*, X1*>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find_if<L2, std::is_volatile>, mp_size_t<6>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find_if<L2, std::is_const>, mp_size_t<1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find_if<L2, std::is_pointer>, mp_size_t<3>>));
+ }
+
+ {
+ using L2 = std::pair<X1 const, X1*>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find_if<L2, std::is_volatile>, mp_size_t<2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find_if<L2, std::is_const>, mp_size_t<0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_find_if<L2, std::is_pointer>, mp_size_t<1>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_fold.cpp 2017-08-28 02:56:56.000000000 -0700
@@ -0,0 +1,81 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+#include <type_traits>
+#include <tuple>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+struct X4 {};
+
+template<class T1, class T2> struct F {};
+
+using boost::mp11::mp_plus;
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_fold;
+
+ {
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_fold<mp_list<>, void, F>, void>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_fold<mp_list<X1>, void, F>, F<void, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_fold<mp_list<X1, X2>, void, F>, F<F<void, X1>, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_fold<mp_list<X1, X2, X3>, void, F>, F<F<F<void, X1>, X2>, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_fold<mp_list<X1, X2, X3, X4>, void, F>, F<F<F<F<void, X1>, X2>, X3>, X4>>));
+ }
+
+ {
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_fold<std::tuple<>, void, F>, void>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_fold<std::tuple<X1>, void, F>, F<void, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_fold<std::tuple<X1, X2>, void, F>, F<F<void, X1>, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_fold<std::tuple<X1, X2, X3>, void, F>, F<F<F<void, X1>, X2>, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_fold<std::tuple<X1, X2, X3, X4>, void, F>, F<F<F<F<void, X1>, X2>, X3>, X4>>));
+ }
+
+ using boost::mp11::mp_push_back;
+
+ {
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_fold<std::tuple<X1, X2, X3, X4>, mp_list<>, mp_push_back>, mp_list<X1, X2, X3, X4>>));
+ }
+
+ using boost::mp11::mp_push_front;
+
+ {
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_fold<std::tuple<X1, X2, X3, X4>, mp_list<>, mp_push_front>, mp_list<X4, X3, X2, X1>>));
+ }
+
+ using boost::mp11::mp_iota_c;
+ using boost::mp11::mp_reverse;
+ using boost::mp11::mp_size_t;
+
+ {
+ int const N = 37;
+
+ using L = mp_iota_c<N>;
+
+ using R1 = mp_fold<L, mp_list<>, mp_push_back>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<R1, L>));
+
+ using R2 = mp_fold<L, mp_list<>, mp_push_front>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<R2, mp_reverse<L>>));
+
+ using R3 = mp_fold<L, mp_size_t<0>, mp_plus>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<R3, mp_size_t<N*(N-1)/2>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_for_each.cpp 2017-08-28 02:56:56.000000000 -0700
@@ -0,0 +1,71 @@
+
+// Copyright 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+#include <tuple>
+
+#if !defined( BOOST_NO_CXX14_CONSTEXPR )
+# define CONSTEXPR14 constexpr
+#else
+# define CONSTEXPR14
+#endif
+
+struct F
+{
+ int s;
+
+ CONSTEXPR14 void operator()( int ) { s = s * 10 + 1; }
+ CONSTEXPR14 void operator()( short ) { s = s * 10 + 2; }
+ CONSTEXPR14 void operator()( char ) { s = s * 10 + 3; }
+};
+
+using boost::mp11::mp_list;
+using boost::mp11::mp_for_each;
+
+int main()
+{
+ BOOST_TEST_EQ( (mp_for_each<mp_list<>>( 11 )), 11 );
+ BOOST_TEST_EQ( (mp_for_each<mp_list<int>>( F{0} ).s), 1 );
+ BOOST_TEST_EQ( (mp_for_each<mp_list<int, short>>( F{0} ).s), 12 );
+ BOOST_TEST_EQ( (mp_for_each<mp_list<int, short, char>>( F{0} ).s), 123 );
+
+ BOOST_TEST_EQ( (mp_for_each<std::tuple<>>( 11 )), 11 );
+ BOOST_TEST_EQ( (mp_for_each<std::tuple<int>>( F{0} ).s), 1 );
+ BOOST_TEST_EQ( (mp_for_each<std::tuple<int, short>>( F{0} ).s), 12 );
+ BOOST_TEST_EQ( (mp_for_each<std::tuple<int, short, char>>( F{0} ).s), 123 );
+
+ BOOST_TEST_EQ( (mp_for_each<std::pair<int, short>>( F{0} ).s), 12 );
+
+#if defined( BOOST_NO_CXX11_CONSTEXPR ) || ( defined( _LIBCPP_VERSION ) && __cplusplus < 201400L )
+#else
+
+ static_assert( mp_for_each<mp_list<>>( 11 ) == 11, "mp_for_each<mp_list<>>( 11 ) == 11" );
+ static_assert( mp_for_each<std::tuple<>>( 12 ) == 12, "mp_for_each<std::tuple<>>( 12 ) == 12" );
+
+#endif
+
+#if !defined( BOOST_NO_CXX14_CONSTEXPR ) && !BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
+
+ constexpr auto r1 = mp_for_each<mp_list<int, short, char>>( F{0} );
+ static_assert( r1.s == 123, "r1.s == 123" );
+
+ constexpr auto r2 = mp_for_each<std::tuple<int, short, char>>( F{0} );
+ static_assert( r2.s == 123, "r2.s == 123" );
+
+ constexpr auto r3 = mp_for_each<std::pair<int, short>>( F{0} );
+ static_assert( r3.s == 12, "r3.s == 12" );
+
+#endif
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_front.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,43 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/core/lightweight_test_trait.hpp>
+#include <boost/mp11/list.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_front;
+ using boost::mp11::mp_first;
+
+ using L1 = mp_list<void>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_front<L1>, void>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_first<L1>, void>));
+
+ using L2 = mp_list<int[], void, float>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_front<L2>, int[]>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_first<L2>, int[]>));
+
+ using L3 = std::tuple<int>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_front<L3>, int>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_first<L3>, int>));
+
+ using L4 = std::pair<char, double>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_front<L4>, char>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_first<L4>, char>));
+
+ using L5 = std::add_const<void()>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_front<L5>, void()>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_first<L5>, void()>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_identity.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,33 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/utility.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+struct X {};
+
+int main()
+{
+ using boost::mp11::mp_identity;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_identity<void const volatile>::type, void const volatile>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_identity<void()>::type, void()>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_identity<int const[]>::type, int const[]>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_identity<X>::type, X>));
+
+ using boost::mp11::mp_identity_t;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_identity_t<void const volatile>, void const volatile>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_identity_t<void()>, void()>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_identity_t<int const[]>, int const[]>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_identity_t<X>, X>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_if.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,38 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/utility.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+int main()
+{
+ using boost::mp11::mp_if_c;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_if_c<true, char[], void()>, char[]>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_if_c<false, char[], void()>, void()>));
+
+ using boost::mp11::mp_if;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_if<std::true_type, char[], void()>, char[]>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_if<std::false_type, char[], void()>, void()>));
+
+ using boost::mp11::mp_int;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_if<mp_int<-7>, char[], void()>, char[]>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_if<mp_int<0>, char[], void()>, void()>));
+
+ using boost::mp11::mp_size_t;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_if<mp_size_t<14>, char[], void()>, char[]>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_if<mp_size_t<0>, char[], void()>, void()>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_if_sf.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,24 @@
+
+// Copyright 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/utility.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+int main()
+{
+ using boost::mp11::mp_if;
+ using boost::mp11::mp_valid;
+
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_if, std::false_type, void>));
+ BOOST_TEST_TRAIT_TRUE((mp_valid<mp_if, std::false_type, void, void>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_if, std::false_type, void, void, void>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_inherit.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,27 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/core/lightweight_test_trait.hpp>
+#include <boost/mp11/utility.hpp>
+#include <type_traits>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+
+int main()
+{
+ using boost::mp11::mp_inherit;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_base_of<X1, mp_inherit<X1, X2, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_base_of<X2, mp_inherit<X1, X2, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_base_of<X3, mp_inherit<X1, X2, X3>>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_insert.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,137 @@
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+struct X4 {};
+struct X5 {};
+
+struct Y1 {};
+struct Y2 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_insert;
+ using boost::mp11::mp_insert_c;
+ using boost::mp11::mp_size_t;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L1, 0>, L1>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L1, mp_size_t<0>>, L1>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L1, 0, Y1>, mp_list<Y1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L1, mp_size_t<0>, Y1>, mp_list<Y1>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L1, 0, Y1, Y2>, mp_list<Y1, Y2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L1, mp_size_t<0>, Y1, Y2>, mp_list<Y1, Y2>>));
+
+ using L2 = mp_list<X1, X2, X3, X4, X5>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 0>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 1>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 2>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 3>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 4>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 5>, L2>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 0, Y1, Y2>, mp_list<Y1, Y2, X1, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 1, Y1, Y2>, mp_list<X1, Y1, Y2, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 2, Y1, Y2>, mp_list<X1, X2, Y1, Y2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 3, Y1, Y2>, mp_list<X1, X2, X3, Y1, Y2, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 4, Y1, Y2>, mp_list<X1, X2, X3, X4, Y1, Y2, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 5, Y1, Y2>, mp_list<X1, X2, X3, X4, X5, Y1, Y2>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<0>>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<1>>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<2>>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<3>>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<4>>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<5>>, L2>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<0>, Y1, Y2>, mp_list<Y1, Y2, X1, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<1>, Y1, Y2>, mp_list<X1, Y1, Y2, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<2>, Y1, Y2>, mp_list<X1, X2, Y1, Y2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<3>, Y1, Y2>, mp_list<X1, X2, X3, Y1, Y2, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<4>, Y1, Y2>, mp_list<X1, X2, X3, X4, Y1, Y2, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<5>, Y1, Y2>, mp_list<X1, X2, X3, X4, X5, Y1, Y2>>));
+
+ using L3 = mp_list<X1, X2, X3, X4, X5, X1, X2, X3, X4, X5, X1, X2, X3, X4, X5, X1, X2, X3, X4, X5>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L3, 8>, L3>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L3, mp_size_t<9>>, L3>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L3, 8, Y1, Y2>, mp_list<X1, X2, X3, X4, X5, X1, X2, X3, Y1, Y2, X4, X5, X1, X2, X3, X4, X5, X1, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L3, mp_size_t<9>, Y1, Y2>, mp_list<X1, X2, X3, X4, X5, X1, X2, X3, X4, Y1, Y2, X5, X1, X2, X3, X4, X5, X1, X2, X3, X4, X5>>));
+ }
+
+ {
+ using L1 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L1, 0>, L1>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L1, mp_size_t<0>>, L1>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L1, 0, Y1>, std::tuple<Y1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L1, mp_size_t<0>, Y1>, std::tuple<Y1>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L1, 0, Y1, Y2>, std::tuple<Y1, Y2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L1, mp_size_t<0>, Y1, Y2>, std::tuple<Y1, Y2>>));
+
+ using L2 = std::tuple<X1, X2, X3, X4, X5>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 0>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 1>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 2>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 3>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 4>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 5>, L2>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 0, Y1, Y2>, std::tuple<Y1, Y2, X1, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 1, Y1, Y2>, std::tuple<X1, Y1, Y2, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 2, Y1, Y2>, std::tuple<X1, X2, Y1, Y2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 3, Y1, Y2>, std::tuple<X1, X2, X3, Y1, Y2, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 4, Y1, Y2>, std::tuple<X1, X2, X3, X4, Y1, Y2, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L2, 5, Y1, Y2>, std::tuple<X1, X2, X3, X4, X5, Y1, Y2>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<0>>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<1>>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<2>>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<3>>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<4>>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<5>>, L2>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<0>, Y1, Y2>, std::tuple<Y1, Y2, X1, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<1>, Y1, Y2>, std::tuple<X1, Y1, Y2, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<2>, Y1, Y2>, std::tuple<X1, X2, Y1, Y2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<3>, Y1, Y2>, std::tuple<X1, X2, X3, Y1, Y2, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<4>, Y1, Y2>, std::tuple<X1, X2, X3, X4, Y1, Y2, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L2, mp_size_t<5>, Y1, Y2>, std::tuple<X1, X2, X3, X4, X5, Y1, Y2>>));
+
+ using L3 = std::tuple<X1, X2, X3, X4, X5, X1, X2, X3, X4, X5, X1, X2, X3, X4, X5, X1, X2, X3, X4, X5>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L3, 8>, L3>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L3, mp_size_t<9>>, L3>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert_c<L3, 8, Y1, Y2>, std::tuple<X1, X2, X3, X4, X5, X1, X2, X3, Y1, Y2, X4, X5, X1, X2, X3, X4, X5, X1, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_insert<L3, mp_size_t<9>, Y1, Y2>, std::tuple<X1, X2, X3, X4, X5, X1, X2, X3, X4, Y1, Y2, X5, X1, X2, X3, X4, X5, X1, X2, X3, X4, X5>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_invoke.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,63 @@
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/utility.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+using boost::mp11::mp_invoke;
+using boost::mp11::mp_size_t;
+
+struct Q1
+{
+ template<class...> using fn = void;
+};
+
+struct Q2
+{
+ template<class...> class fn;
+};
+
+struct Q3
+{
+ template<class... T> using fn = mp_size_t<sizeof...(T)>;
+};
+
+struct Q4
+{
+ template<class T1, class... T> using fn = T1;
+};
+
+struct Q5
+{
+ template<class T1, class T2> using fn = T2;
+};
+
+int main()
+{
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q1>, void>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q1, int>, void>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q1, int[], char[]>, void>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q2>, Q2::fn<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q2, int>, Q2::fn<int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q2, int[], char[]>, Q2::fn<int[], char[]>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q3>, mp_size_t<0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q3, int>, mp_size_t<1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q3, int[], char[]>, mp_size_t<2>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q4, int>, int>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q4, int[], char[]>, int[]>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q5, int, float>, float>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_invoke_sf.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,44 @@
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/utility.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+using boost::mp11::mp_invoke;
+using boost::mp11::mp_quote;
+using boost::mp11::mp_quote_trait;
+using boost::mp11::mp_valid;
+using boost::mp11::mp_identity;
+using boost::mp11::mp_identity_t;
+
+int main()
+{
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_invoke>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_invoke, void>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_invoke, void, void>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_invoke, void, void, void>));
+
+ using Qi = mp_quote<mp_identity_t>;
+
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_invoke, Qi>));
+ BOOST_TEST_TRAIT_TRUE((mp_valid<mp_invoke, Qi, void>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_invoke, Qi, void, void>));
+
+ using Qt = mp_quote_trait<mp_identity>;
+
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
+#else
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_invoke, Qt>));
+#endif
+ BOOST_TEST_TRAIT_TRUE((mp_valid<mp_invoke, Qt, void>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_invoke, Qt, void, void>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_iota.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,42 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_iota;
+ using boost::mp11::mp_iota_c;
+ using boost::mp11::mp_int;
+ using boost::mp11::mp_size_t;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_iota_c<0>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_iota_c<1>, mp_list<mp_size_t<0>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_iota_c<2>, mp_list<mp_size_t<0>, mp_size_t<1>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_iota_c<3>, mp_list<mp_size_t<0>, mp_size_t<1>, mp_size_t<2>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_iota_c<4>, mp_list<mp_size_t<0>, mp_size_t<1>, mp_size_t<2>, mp_size_t<3>>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_iota<mp_size_t<0>>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_iota<mp_size_t<1>>, mp_list<mp_size_t<0>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_iota<mp_size_t<2>>, mp_list<mp_size_t<0>, mp_size_t<1>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_iota<mp_size_t<3>>, mp_list<mp_size_t<0>, mp_size_t<1>, mp_size_t<2>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_iota<mp_size_t<4>>, mp_list<mp_size_t<0>, mp_size_t<1>, mp_size_t<2>, mp_size_t<3>>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_iota<mp_int<0>>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_iota<mp_int<1>>, mp_list<mp_int<0>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_iota<mp_int<2>>, mp_list<mp_int<0>, mp_int<1>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_iota<mp_int<3>>, mp_list<mp_int<0>, mp_int<1>, mp_int<2>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_iota<mp_int<4>>, mp_list<mp_int<0>, mp_int<1>, mp_int<2>, mp_int<3>>>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_is_map.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,59 @@
+
+// Copyright 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/map.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+int main()
+{
+ using boost::mp11::mp_is_map;
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_true;
+ using boost::mp11::mp_false;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<void>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<mp_list<>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<std::tuple<>>, mp_true>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<mp_list<void>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<std::tuple<void>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<mp_list<mp_list<>>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<std::tuple<std::tuple<>>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<mp_list<mp_list<int>>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<std::tuple<std::tuple<int>>>, mp_true>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<mp_list<std::pair<int, int const>>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<std::tuple<std::pair<int, int const>>>, mp_true>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<mp_list<std::pair<int, int const>, std::pair<long, long const>>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<std::tuple<std::pair<int, int const>, std::pair<long, long const>>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<std::pair<std::pair<int, int const>, std::pair<long, long const>>>, mp_true>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<mp_list<std::pair<int, int const>, std::pair<int, long const>>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<std::tuple<std::pair<int, int const>, std::pair<int, long const>>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<std::pair<std::pair<int, int const>, std::pair<int, long const>>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<mp_list<mp_list<int>, mp_list<long, long>, mp_list<long long, long long, long long>>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<std::tuple<mp_list<int>, mp_list<long, long>, mp_list<long long, long long, long long>>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<std::tuple<std::tuple<int>, std::pair<long, long>, std::tuple<long long, long long, long long>>>, mp_true>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<mp_list<mp_list<int>, mp_list<long, long>, mp_list<int, long long, long long>>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<std::tuple<mp_list<int>, mp_list<long, long>, mp_list<int, long long, long long>>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_map<std::tuple<std::tuple<int>, std::pair<long, long>, std::tuple<int, long long, long long>>>, mp_false>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_is_set.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,73 @@
+
+// Copyright 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/set.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/utility.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_is_set;
+ using boost::mp11::mp_true;
+ using boost::mp11::mp_false;
+
+ {
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<void>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<int>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<char[]>, mp_false>));
+ }
+
+ {
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<mp_list<>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<mp_list<void>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<mp_list<void, void>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<mp_list<void, void, void>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<mp_list<void, void, void, void>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<mp_list<void, int>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<mp_list<void, int, void>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<mp_list<void, int, int>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<mp_list<void, int, char[]>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<mp_list<void, int, char[], void>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<mp_list<void, int, char[], int>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<mp_list<void, int, char[], char[]>>, mp_false>));
+ }
+
+ {
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<std::tuple<>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<std::tuple<void>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<std::tuple<void, void>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<std::tuple<void, void, void>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<std::tuple<void, void, void, void>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<std::tuple<void, int>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<std::tuple<void, int, void>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<std::tuple<void, int, int>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<std::tuple<void, int, char[]>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<std::tuple<void, int, char[], void>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<std::tuple<void, int, char[], int>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<std::tuple<void, int, char[], char[]>>, mp_false>));
+ }
+
+ {
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<std::pair<void, void>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<std::pair<void, int>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<std::pair<int, void>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_is_set<std::pair<int, int>>, mp_false>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_map_contains.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,51 @@
+
+// Copyright 2016 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/map.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+int main()
+{
+ using boost::mp11::mp_map_contains;
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_true;
+ using boost::mp11::mp_false;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_contains<mp_list<>, char>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_contains<std::tuple<>, int>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_contains<mp_list<std::pair<int, int const>, std::pair<long, long const>>, char>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_contains<mp_list<std::pair<int, int const>, std::pair<long, long const>>, int>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_contains<mp_list<std::pair<int, int const>, std::pair<long, long const>>, long>, mp_true>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_contains<std::tuple<std::pair<int, int const>, std::pair<long, long const>>, char>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_contains<std::tuple<std::pair<int, int const>, std::pair<long, long const>>, int>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_contains<std::tuple<std::pair<int, int const>, std::pair<long, long const>>, long>, mp_true>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_contains<std::pair<std::pair<int, int const>, std::pair<long, long const>>, char>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_contains<std::pair<std::pair<int, int const>, std::pair<long, long const>>, int>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_contains<std::pair<std::pair<int, int const>, std::pair<long, long const>>, long>, mp_true>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_contains<mp_list<mp_list<int>, mp_list<long, long>, mp_list<long long, long long, long long>>, char>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_contains<mp_list<mp_list<int>, mp_list<long, long>, mp_list<long long, long long, long long>>, int>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_contains<mp_list<mp_list<int>, mp_list<long, long>, mp_list<long long, long long, long long>>, long>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_contains<mp_list<mp_list<int>, mp_list<long, long>, mp_list<long long, long long, long long>>, long long>, mp_true>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_contains<std::tuple<mp_list<int>, std::pair<long, long>, std::tuple<long long, long long, long long>>, char>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_contains<std::tuple<mp_list<int>, std::pair<long, long>, std::tuple<long long, long long, long long>>, int>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_contains<std::tuple<mp_list<int>, std::pair<long, long>, std::tuple<long long, long long, long long>>, long>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_contains<std::tuple<mp_list<int>, std::pair<long, long>, std::tuple<long long, long long, long long>>, long long>, mp_true>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_map_erase.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,60 @@
+
+// Copyright 2016, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/map.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+int main()
+{
+ using boost::mp11::mp_map_erase;
+ using boost::mp11::mp_list;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_erase<mp_list<>, void>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_erase<std::tuple<>, int>, std::tuple<>>));
+
+ {
+ using M = mp_list<std::pair<int, int const>, std::pair<long, long const>>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_erase<M, char>, M>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_erase<M, int>, mp_list<std::pair<long, long const>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_erase<M, long>, mp_list<std::pair<int, int const>>>));
+ }
+
+ {
+ using M = std::tuple<std::pair<int, int const>, std::pair<long, long const>>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_erase<M, char>, M>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_erase<M, int>, std::tuple<std::pair<long, long const>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_erase<M, long>, std::tuple<std::pair<int, int const>>>));
+ }
+
+ {
+ using M = mp_list<mp_list<int>, mp_list<long, long>, mp_list<long long, long long, long long>>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_erase<M, char>, M>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_erase<M, int>, mp_list<mp_list<long, long>, mp_list<long long, long long, long long>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_erase<M, long>, mp_list<mp_list<int>, mp_list<long long, long long, long long>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_erase<M, long long>, mp_list<mp_list<int>, mp_list<long, long>>>));
+ }
+
+ {
+ using M = std::tuple<mp_list<int>, std::pair<long, long>, std::tuple<long long, long long, long long>>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_erase<M, char>, M>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_erase<M, int>, std::tuple<std::pair<long, long>, std::tuple<long long, long long, long long>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_erase<M, long>, std::tuple<mp_list<int>, std::tuple<long long, long long, long long>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_erase<M, long long>, std::tuple<mp_list<int>, std::pair<long, long>>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_map_find.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,48 @@
+
+// Copyright 2016 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/map.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+int main()
+{
+ using boost::mp11::mp_map_find;
+ using boost::mp11::mp_list;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_find<mp_list<>, char>, void>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_find<std::tuple<>, int>, void>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_find<mp_list<std::pair<int, int const>, std::pair<long, long const>>, char>, void>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_find<mp_list<std::pair<int, int const>, std::pair<long, long const>>, int>, std::pair<int, int const>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_find<mp_list<std::pair<int, int const>, std::pair<long, long const>>, long>, std::pair<long, long const>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_find<std::tuple<std::pair<int, int const>, std::pair<long, long const>>, char>, void>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_find<std::tuple<std::pair<int, int const>, std::pair<long, long const>>, int>, std::pair<int, int const>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_find<std::tuple<std::pair<int, int const>, std::pair<long, long const>>, long>, std::pair<long, long const>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_find<std::pair<std::pair<int, int const>, std::pair<long, long const>>, char>, void>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_find<std::pair<std::pair<int, int const>, std::pair<long, long const>>, int>, std::pair<int, int const>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_find<std::pair<std::pair<int, int const>, std::pair<long, long const>>, long>, std::pair<long, long const>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_find<mp_list<mp_list<int>, mp_list<long, long>, mp_list<long long, long long, long long>>, char>, void>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_find<mp_list<mp_list<int>, mp_list<long, long>, mp_list<long long, long long, long long>>, int>, mp_list<int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_find<mp_list<mp_list<int>, mp_list<long, long>, mp_list<long long, long long, long long>>, long>, mp_list<long, long>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_find<mp_list<mp_list<int>, mp_list<long, long>, mp_list<long long, long long, long long>>, long long>, mp_list<long long, long long, long long>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_find<std::tuple<mp_list<int>, std::pair<long, long>, std::tuple<long long, long long, long long>>, char>, void>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_find<std::tuple<mp_list<int>, std::pair<long, long>, std::tuple<long long, long long, long long>>, int>, mp_list<int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_find<std::tuple<mp_list<int>, std::pair<long, long>, std::tuple<long long, long long, long long>>, long>, std::pair<long, long>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_find<std::tuple<mp_list<int>, std::pair<long, long>, std::tuple<long long, long long, long long>>, long long>, std::tuple<long long, long long, long long>>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_map_insert.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,66 @@
+
+// Copyright 2016 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/map.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+int main()
+{
+ using boost::mp11::mp_map_insert;
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_push_back;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<mp_list<>, mp_list<void>>, mp_list<mp_list<void>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<std::tuple<>, std::tuple<int>>, std::tuple<std::tuple<int>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<std::tuple<>, std::pair<int, float>>, std::tuple<std::pair<int, float>>>));
+
+ {
+ using M = mp_list<std::pair<int, int const>, std::pair<long, long const>>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<M, mp_list<char>>, mp_push_back<M, mp_list<char>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<M, std::pair<char, char const>>, mp_push_back<M, std::pair<char, char const>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<M, mp_list<int>>, M>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<M, std::pair<long, float>>, M>));
+ }
+
+ {
+ using M = std::tuple<std::pair<int, int const>, std::pair<long, long const>>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<M, mp_list<char>>, mp_push_back<M, mp_list<char>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<M, std::pair<char, char const>>, mp_push_back<M, std::pair<char, char const>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<M, mp_list<int>>, M>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<M, std::pair<long, float>>, M>));
+ }
+
+ {
+ using M = mp_list<mp_list<int>, mp_list<long, long>, mp_list<long long, long long, long long>>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<M, mp_list<char>>, mp_push_back<M, mp_list<char>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<M, std::pair<char, char const>>, mp_push_back<M, std::pair<char, char const>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<M, std::tuple<int>>, M>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<M, std::pair<long, float>>, M>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<M, mp_list<long long, float, double>>, M>));
+ }
+
+ {
+ using M = std::tuple<mp_list<int>, std::pair<long, long>, std::tuple<long long, long long, long long>>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<M, mp_list<char>>, mp_push_back<M, mp_list<char>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<M, std::pair<char, char const>>, mp_push_back<M, std::pair<char, char const>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<M, std::tuple<int>>, M>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<M, std::pair<long, float>>, M>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_insert<M, mp_list<long long, float, double>>, M>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_map_keys.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,37 @@
+
+// Copyright 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/map.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+int main()
+{
+ using boost::mp11::mp_map_keys;
+ using boost::mp11::mp_list;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_keys<mp_list<>>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_keys<std::tuple<>>, std::tuple<>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_keys<mp_list<std::pair<int, int const>>>, mp_list<int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_keys<std::tuple<std::pair<int, int const>>>, std::tuple<int>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_keys<mp_list<std::pair<int, int const>, std::pair<long, long const>>>, mp_list<int, long>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_keys<std::tuple<std::pair<int, int const>, std::pair<long, long const>>>, std::tuple<int, long>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_keys<std::pair<std::pair<int, int const>, std::pair<long, long const>>>, std::pair<int, long>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_keys<mp_list<mp_list<int>, mp_list<long, long>, mp_list<long long, long long, long long>>>, mp_list<int, long, long long>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_keys<std::tuple<mp_list<int>, mp_list<long, long>, mp_list<long long, long long, long long>>>, std::tuple<int, long, long long>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_keys<std::tuple<std::tuple<int>, std::pair<long, long>, std::tuple<long long, long long, long long>>>, std::tuple<int, long, long long>>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_map_replace.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,66 @@
+
+// Copyright 2016 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/map.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+int main()
+{
+ using boost::mp11::mp_map_replace;
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_push_back;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<mp_list<>, mp_list<void>>, mp_list<mp_list<void>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<std::tuple<>, std::tuple<int>>, std::tuple<std::tuple<int>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<std::tuple<>, std::pair<int, float>>, std::tuple<std::pair<int, float>>>));
+
+ {
+ using M = mp_list<std::pair<int, int const>, std::pair<long, long const>>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<M, mp_list<char>>, mp_push_back<M, mp_list<char>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<M, std::pair<char, char const>>, mp_push_back<M, std::pair<char, char const>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<M, mp_list<int>>, mp_list<mp_list<int>, std::pair<long, long const>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<M, std::pair<long, float>>, mp_list<std::pair<int, int const>, std::pair<long, float>>>));
+ }
+
+ {
+ using M = std::tuple<std::pair<int, int const>, std::pair<long, long const>>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<M, mp_list<char>>, mp_push_back<M, mp_list<char>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<M, std::pair<char, char const>>, mp_push_back<M, std::pair<char, char const>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<M, mp_list<int>>, std::tuple<mp_list<int>, std::pair<long, long const>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<M, std::pair<long, float>>, std::tuple<std::pair<int, int const>, std::pair<long, float>>>));
+ }
+
+ {
+ using M = mp_list<mp_list<int>, mp_list<long, long>, mp_list<long long, long long, long long>>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<M, mp_list<char>>, mp_push_back<M, mp_list<char>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<M, std::pair<char, char const>>, mp_push_back<M, std::pair<char, char const>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<M, std::tuple<int>>, mp_list<std::tuple<int>, mp_list<long, long>, mp_list<long long, long long, long long>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<M, std::pair<long, float>>, mp_list<mp_list<int>, std::pair<long, float>, mp_list<long long, long long, long long>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<M, mp_list<long long, float, double>>, mp_list<mp_list<int>, mp_list<long, long>, mp_list<long long, float, double>>>));
+ }
+
+ {
+ using M = std::tuple<mp_list<int>, std::pair<long, long>, std::tuple<long long, long long, long long>>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<M, mp_list<char>>, mp_push_back<M, mp_list<char>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<M, std::pair<char, char const>>, mp_push_back<M, std::pair<char, char const>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<M, std::tuple<int>>, std::tuple<std::tuple<int>, std::pair<long, long>, std::tuple<long long, long long, long long>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<M, std::pair<long, float>>, std::tuple<mp_list<int>, std::pair<long, float>, std::tuple<long long, long long, long long>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_map_replace<M, mp_list<long long, float, double>>, std::tuple<mp_list<int>, std::pair<long, long>, mp_list<long long, float, double>>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_map_update.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,48 @@
+
+// Copyright 2016, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/map.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+using boost::mp11::mp_int;
+
+template<class T, class U> using inc = mp_int<U::value + 1>;
+
+int main()
+{
+ using boost::mp11::mp_map_update;
+ using boost::mp11::mp_list;
+
+ using M1 = mp_list<>;
+
+ using M2 = mp_map_update< M1, std::pair<char, mp_int<0>>, inc >;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<M2, mp_list<std::pair<char, mp_int<0>>>>));
+
+ using M3 = mp_map_update< M2, std::pair<char, mp_int<0>>, inc >;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<M3, mp_list<std::pair<char, mp_int<1>>>>));
+
+ using M4 = mp_map_update< M3, std::pair<int, mp_int<0>>, inc >;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<M4, mp_list<std::pair<char, mp_int<1>>, std::pair<int, mp_int<0>>>>));
+
+ using M5 = mp_map_update< M4, std::pair<long, mp_int<0>>, inc >;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<M5, mp_list<std::pair<char, mp_int<1>>, std::pair<int, mp_int<0>>, std::pair<long, mp_int<0>>>>));
+
+ using M6 = mp_map_update< M5, std::pair<long, mp_int<0>>, inc >;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<M6, mp_list<std::pair<char, mp_int<1>>, std::pair<int, mp_int<0>>, std::pair<long, mp_int<1>>>>));
+
+ using M7 = mp_map_update< M6, std::pair<char, mp_int<0>>, inc >;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<M7, mp_list<std::pair<char, mp_int<2>>, std::pair<int, mp_int<0>>, std::pair<long, mp_int<1>>>>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_none_of.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,72 @@
+
+// Copyright 2015, 2016 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_none_of;
+ using boost::mp11::mp_true;
+ using boost::mp11::mp_false;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_none_of<L1, std::is_const>, mp_true>));
+
+ using L2 = mp_list<X1, X1 const, X1, X1, X1>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_none_of<L2, std::is_volatile>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_none_of<L2, std::is_const>, mp_false>));
+
+ using L3 = mp_list<X1 const, X1 const, X1, X1 const, X1>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_none_of<L3, std::is_volatile>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_none_of<L3, std::is_const>, mp_false>));
+ }
+
+ {
+ using L1 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_none_of<L1, std::is_const>, mp_true>));
+
+ using L2 = std::tuple<X1, X1 const, X1, X1, X1>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_none_of<L2, std::is_volatile>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_none_of<L2, std::is_const>, mp_false>));
+
+ using L3 = std::tuple<X1 const, X1 const, X1, X1 const, X1>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_none_of<L3, std::is_volatile>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_none_of<L3, std::is_const>, mp_false>));
+ }
+
+ {
+ using L2 = std::pair<X1 const, X1>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_none_of<L2, std::is_volatile>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_none_of<L2, std::is_const>, mp_false>));
+
+ using L3 = std::pair<X1 const, X1 const>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_none_of<L3, std::is_volatile>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_none_of<L3, std::is_const>, mp_false>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_or.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,73 @@
+
+// Copyright 2015-2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/function.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+int main()
+{
+ using boost::mp11::mp_or;
+ using boost::mp11::mp_true;
+ using boost::mp11::mp_false;
+ using boost::mp11::mp_int;
+ using boost::mp11::mp_size_t;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_true>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_false>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<-7>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<7>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_true, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_false, mp_true>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_false, mp_false>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>, mp_int<0>>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>, mp_int<5>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<-4>, void>, mp_true>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<7>, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>, mp_size_t<4>>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>, mp_size_t<0>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_true, void, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_false, mp_true, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_false, mp_false, mp_true>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_false, mp_false, mp_false>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_true, void, void, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_false, mp_true, void, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_false, mp_false, mp_true, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_false, mp_false, mp_false, mp_true>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_false, mp_false, mp_false, mp_false>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<1>, void, void, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>, mp_int<2>, void, void, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>, mp_int<0>, mp_int<3>, void, void, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>, mp_int<0>, mp_int<0>, mp_int<4>, void, void, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>, mp_int<0>, mp_int<0>, mp_int<0>, mp_int<0>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<1>, void, void, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>, mp_size_t<2>, void, void, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>, mp_size_t<0>, mp_size_t<3>, void, void, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>, mp_size_t<0>, mp_size_t<0>, mp_size_t<4>, void, void, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>, mp_size_t<0>, mp_size_t<0>, mp_size_t<0>, mp_size_t<0>>, mp_false>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>, mp_int<0>, mp_false, mp_size_t<141>, void, void, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>, mp_int<0>, mp_false>, mp_false>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_partition.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,50 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_partition;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_partition<L1, std::is_const>, mp_list<L1, L1>>));
+
+ using L2 = mp_list<X1, X1 const, X1*, X2 const, X2*, X3*>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_partition<L2, std::is_volatile>, mp_list<L1, L2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_partition<L2, std::is_const>, mp_list<mp_list<X1 const, X2 const>, mp_list<X1, X1*, X2*, X3*>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_partition<L2, std::is_pointer>, mp_list<mp_list<X1*, X2*, X3*>, mp_list<X1, X1 const, X2 const>>>));
+ }
+
+ {
+ using L1 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_partition<L1, std::is_const>, std::tuple<L1, L1>>));
+
+ using L2 = std::tuple<X1, X1 const, X1*, X2 const, X2*, X3*>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_partition<L2, std::is_volatile>, std::tuple<L1, L2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_partition<L2, std::is_const>, std::tuple<std::tuple<X1 const, X2 const>, std::tuple<X1, X1*, X2*, X3*>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_partition<L2, std::is_pointer>, std::tuple<std::tuple<X1*, X2*, X3*>, std::tuple<X1, X1 const, X2 const>>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_plus.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,32 @@
+
+// Copyright 2015-2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/function.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+template<class T, T N> using integral = std::integral_constant<T, N>;
+
+int main()
+{
+ using boost::mp11::mp_plus;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_plus<>, integral<int, 0>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_plus<integral<char, 1>>, integral<int, 1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_plus<integral<short, 2>>, integral<int, 2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_plus<integral<int, 3>>, integral<int, 3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_plus<integral<unsigned, 4>>, integral<unsigned, 4>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_plus<integral<char, 1>, integral<char, 2>>, integral<int, 3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_plus<integral<short, 1>, integral<short, 2>, integral<short, 3>>, integral<int, 6>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_plus<integral<int, 1>, integral<int, 2>, integral<int, 3>, integral<long, 4>>, integral<long, 10>>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_pop_front.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,39 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/core/lightweight_test_trait.hpp>
+#include <boost/mp11/list.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_pop_front;
+ using boost::mp11::mp_rest;
+
+ using L1 = mp_list<void>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_pop_front<L1>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rest<L1>, mp_list<>>));
+
+ using L2 = mp_list<int[], void(), float>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_pop_front<L2>, mp_list<void(), float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rest<L2>, mp_list<void(), float>>));
+
+ using L3 = std::tuple<int>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_pop_front<L3>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rest<L3>, std::tuple<>>));
+
+ using L4 = std::tuple<char, double>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_pop_front<L4>, std::tuple<double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rest<L4>, std::tuple<double>>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_product.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,68 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/utility.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+
+struct Y1 {};
+
+struct Z1 {};
+struct Z2 {};
+
+template<class T1, class T2, class T3> struct F {};
+
+template<class T> struct F1 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_product;
+ using boost::mp11::mp_product_q;
+ using boost::mp11::mp_quote;
+
+ {
+ using L1 = std::tuple<X1, X2, X3>;
+ using L2 = mp_list<Y1>;
+ using L3 = std::pair<Z1, Z2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_product<F, L1, L2, L3>, std::tuple<F<X1, Y1, Z1>, F<X1, Y1, Z2>, F<X2, Y1, Z1>, F<X2, Y1, Z2>, F<X3, Y1, Z1>, F<X3, Y1, Z2>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_product_q<mp_quote<F>, L1, L2, L3>, std::tuple<F<X1, Y1, Z1>, F<X1, Y1, Z2>, F<X2, Y1, Z1>, F<X2, Y1, Z2>, F<X3, Y1, Z1>, F<X3, Y1, Z2>>>));
+ }
+
+ {
+ using L1 = std::tuple<X1, X2, X3>;
+ using L2 = mp_list<>;
+ using L3 = std::pair<Z1, Z2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_product<F, L1, L2, L3>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_product_q<mp_quote<F>, L1, L2, L3>, std::tuple<>>));
+ }
+
+ {
+ using L1 = std::tuple<X1, X2, X3>;
+ using L2 = mp_list<X1, X2, X3>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_product<F1, L1>, std::tuple<F1<X1>, F1<X2>, F1<X3>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_product_q<mp_quote<F1>, L1>, std::tuple<F1<X1>, F1<X2>, F1<X3>>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_product<F1, L2>, mp_list<F1<X1>, F1<X2>, F1<X3>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_product_q<mp_quote<F1>, L2>, mp_list<F1<X1>, F1<X2>, F1<X3>>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_push_back.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,52 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/core/lightweight_test_trait.hpp>
+#include <boost/mp11/list.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_push_back;
+
+ using L1 = mp_list<>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_back<L1>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_back<L1, char[1]>, mp_list<char[1]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_back<L1, char[1], char[2]>, mp_list<char[1], char[2]>>));
+
+ using L2 = mp_list<void>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_back<L2>, mp_list<void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_back<L2, char[1]>, mp_list<void, char[1]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_back<L2, char[1], char[2]>, mp_list<void, char[1], char[2]>>));
+
+ using L3 = mp_list<int[], void, float>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_back<L3>, mp_list<int[], void, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_back<L3, char[1]>, mp_list<int[], void, float, char[1]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_back<L3, char[1], char[2]>, mp_list<int[], void, float, char[1], char[2]>>));
+
+ using L4 = std::tuple<>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_back<L4>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_back<L4, char>, std::tuple<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_back<L4, char, wchar_t>, std::tuple<char, wchar_t>>));
+
+ using L5 = std::tuple<int>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_back<L5>, std::tuple<int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_back<L5, char>, std::tuple<int, char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_back<L5, char, wchar_t>, std::tuple<int, char, wchar_t>>));
+
+ using L6 = std::tuple<int, int>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_back<L6>, std::tuple<int, int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_back<L6, char>, std::tuple<int, int, char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_back<L6, char, wchar_t>, std::tuple<int, int, char, wchar_t>>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_push_front.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,52 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/core/lightweight_test_trait.hpp>
+#include <boost/mp11/list.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_push_front;
+
+ using L1 = mp_list<>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_front<L1>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_front<L1, char[1]>, mp_list<char[1]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_front<L1, char[1], char[2]>, mp_list<char[1], char[2]>>));
+
+ using L2 = mp_list<void>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_front<L2>, mp_list<void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_front<L2, char[1]>, mp_list<char[1], void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_front<L2, char[1], char[2]>, mp_list<char[1], char[2], void>>));
+
+ using L3 = mp_list<int[], void, float>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_front<L3>, mp_list<int[], void, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_front<L3, char[1]>, mp_list<char[1], int[], void, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_front<L3, char[1], char[2]>, mp_list<char[1], char[2], int[], void, float>>));
+
+ using L4 = std::tuple<>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_front<L4>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_front<L4, char>, std::tuple<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_front<L4, char, wchar_t>, std::tuple<char, wchar_t>>));
+
+ using L5 = std::tuple<int>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_front<L5>, std::tuple<int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_front<L5, char>, std::tuple<char, int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_front<L5, char, wchar_t>, std::tuple<char, wchar_t, int>>));
+
+ using L6 = std::tuple<int, int>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_front<L6>, std::tuple<int, int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_front<L6, char>, std::tuple<char, int, int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_push_front<L6, char, wchar_t>, std::tuple<char, wchar_t, int, int>>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_quote.cpp 2017-08-24 15:13:49.000000000 -0700
@@ -0,0 +1,69 @@
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/utility.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+using boost::mp11::mp_invoke;
+
+template<class...> struct X {};
+
+template<template<class...> class F, class... T> using Y = X<F<T>...>;
+
+template<class Q, class... T> using Z = X<mp_invoke<Q, T>...>;
+
+template<class T, class U> struct P {};
+
+template<class T, class U> using first = T;
+
+int main()
+{
+ using boost::mp11::mp_identity_t;
+ using boost::mp11::mp_quote;
+
+ {
+ using Q = mp_quote<mp_identity_t>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q, void>, void>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q, int[]>, int[]>));
+ }
+
+ {
+ using Q = mp_quote<mp_identity_t>;
+
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
+#else
+ using R1 = Y<Q::fn, void, char, int>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<R1, X<void, char, int>>));
+#endif
+
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1920 && BOOST_MSVC >= 1900 )
+#else
+ using R2 = Z<Q, void, char, int>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<R2, X<void, char, int>>));
+#endif
+ }
+
+ {
+ using Q = mp_quote<P>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q, void, void>, P<void, void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q, char[], int[]>, P<char[], int[]>>));
+ }
+
+ {
+ using Q = mp_quote<first>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q, void, int>, void>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q, char[], int[]>, char[]>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_quote_trait.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,57 @@
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/utility.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+int main()
+{
+ using boost::mp11::mp_identity;
+ using boost::mp11::mp_quote_trait;
+ using boost::mp11::mp_invoke;
+
+ {
+ using Q = mp_quote_trait<mp_identity>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<Q::fn<void>, void>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<Q::fn<int[]>, int[]>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q, void>, void>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q, int[]>, int[]>));
+ }
+
+ {
+ using Q = mp_quote_trait<std::add_pointer>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<Q::fn<void>, void*>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<Q::fn<int[]>, int(*)[]>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q, void>, void*>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q, int[]>, int(*)[]>));
+ }
+
+ {
+ using Q = mp_quote_trait<std::add_const>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<Q::fn<void>, void const>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<Q::fn<int[]>, int const[]>));
+
+#if !BOOST_WORKAROUND( BOOST_GCC, < 40900 )
+
+ // g++ 4.7, 4.8 have difficulties with preserving top-level const
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q, void>, void const>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q, int[]>, int const[]>));
+
+#endif
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_remove.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,52 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_remove;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_remove<L1, void>, L1>));
+
+ using L2 = mp_list<X1, X2, X3, X2, X3, X3>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_remove<L2, void>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_remove<L2, X1>, mp_list<X2, X3, X2, X3, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_remove<L2, X2>, mp_list<X1, X3, X3, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_remove<L2, X3>, mp_list<X1, X2, X2>>));
+ }
+
+ {
+ using L1 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_remove<L1, void>, L1>));
+
+ using L2 = std::tuple<X1, X2, X3, X2, X3, X3>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_remove<L2, void>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_remove<L2, X1>, std::tuple<X2, X3, X2, X3, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_remove<L2, X2>, std::tuple<X1, X3, X3, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_remove<L2, X3>, std::tuple<X1, X2, X2>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_remove_if.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,67 @@
+
+// Copyright 2015-2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+
+using boost::mp11::mp_bool;
+
+template<class N> using is_odd = mp_bool<N::value % 2 != 0>;
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_remove_if;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_remove_if<L1, std::is_const>, L1>));
+
+ using L2 = mp_list<X1, X1 const, X1*, X2 const, X2*, X3*>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_remove_if<L2, std::is_volatile>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_remove_if<L2, std::is_const>, mp_list<X1, X1*, X2*, X3*>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_remove_if<L2, std::is_pointer>, mp_list<X1, X1 const, X2 const>>));
+ }
+
+ {
+ using L1 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_remove_if<L1, std::is_const>, L1>));
+
+ using L2 = std::tuple<X1, X1 const, X1*, X2 const, X2*, X3*>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_remove_if<L2, std::is_volatile>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_remove_if<L2, std::is_const>, std::tuple<X1, X1*, X2*, X3*>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_remove_if<L2, std::is_pointer>, std::tuple<X1, X1 const, X2 const>>));
+ }
+
+ using boost::mp11::mp_iota_c;
+ using boost::mp11::mp_size_t;
+
+ {
+ int const N = 12;
+ using L1 = mp_iota_c<N>;
+
+ using R1 = mp_remove_if<L1, is_odd>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<R1, mp_list<mp_size_t<0>, mp_size_t<2>, mp_size_t<4>, mp_size_t<6>, mp_size_t<8>, mp_size_t<10>>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_rename.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,146 @@
+
+// Copyright 2015-2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/core/lightweight_test_trait.hpp>
+#include <boost/mp11/list.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+template<class... T> struct X {};
+template<class... T> using Y = X<T...>;
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_rename;
+ using boost::mp11::mp_apply;
+
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L1, mp_list>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L1, std::tuple>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L1, X>, X<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L1, Y>, Y<>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<mp_list, L1>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<std::tuple, L1>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<X, L1>, X<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<Y, L1>, Y<>>));
+
+ using L2 = mp_list<char>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L2, mp_list>, mp_list<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L2, std::tuple>, std::tuple<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L2, X>, X<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L2, Y>, Y<char>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<mp_list, L2>, mp_list<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<std::tuple, L2>, std::tuple<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<X, L2>, X<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<Y, L2>, Y<char>>));
+
+ using L3 = mp_list<char, double>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L3, mp_list>, mp_list<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L3, std::tuple>, std::tuple<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L3, X>, X<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L3, Y>, Y<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L3, std::pair>, std::pair<char, double>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<mp_list, L3>, mp_list<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<std::tuple, L3>, std::tuple<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<X, L3>, X<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<Y, L3>, Y<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<std::pair, L3>, std::pair<char, double>>));
+
+ using L4 = mp_list<int, char, float>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L4, mp_list>, mp_list<int, char, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L4, std::tuple>, std::tuple<int, char, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L4, X>, X<int, char, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L4, Y>, Y<int, char, float>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<mp_list, L4>, mp_list<int, char, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<std::tuple, L4>, std::tuple<int, char, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<X, L4>, X<int, char, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<Y, L4>, Y<int, char, float>>));
+
+ //
+
+ using L5 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L5, mp_list>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L5, std::tuple>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L5, X>, X<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L5, Y>, Y<>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<mp_list, L5>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<std::tuple, L5>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<X, L5>, X<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<Y, L5>, Y<>>));
+
+ using L6 = std::tuple<char>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L6, mp_list>, mp_list<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L6, std::tuple>, std::tuple<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L6, X>, X<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L6, Y>, Y<char>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<mp_list, L6>, mp_list<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<std::tuple, L6>, std::tuple<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<X, L6>, X<char>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<Y, L6>, Y<char>>));
+
+ using L7 = std::tuple<char, double>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L7, mp_list>, mp_list<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L7, std::tuple>, std::tuple<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L7, X>, X<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L7, Y>, Y<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L7, std::pair>, std::pair<char, double>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<mp_list, L7>, mp_list<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<std::tuple, L7>, std::tuple<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<X, L7>, X<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<Y, L7>, Y<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<std::pair, L7>, std::pair<char, double>>));
+
+ using L8 = std::tuple<int, char, float>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L8, mp_list>, mp_list<int, char, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L8, std::tuple>, std::tuple<int, char, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L8, X>, X<int, char, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L8, Y>, Y<int, char, float>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<mp_list, L8>, mp_list<int, char, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<std::tuple, L8>, std::tuple<int, char, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<X, L8>, X<int, char, float>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<Y, L8>, Y<int, char, float>>));
+
+ //
+
+ using L9 = std::pair<char, double>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L9, mp_list>, mp_list<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L9, std::tuple>, std::tuple<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L9, X>, X<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L9, Y>, Y<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_rename<L9, std::pair>, std::pair<char, double>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<mp_list, L9>, mp_list<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<std::tuple, L9>, std::tuple<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<X, L9>, X<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<Y, L9>, Y<char, double>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_apply<std::pair, L9>, std::pair<char, double>>));
+
+ //
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_repeat.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,132 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_repeat;
+ using boost::mp11::mp_repeat_c;
+ using boost::mp11::mp_true;
+ using boost::mp11::mp_false;
+ using boost::mp11::mp_int;
+ using boost::mp11::mp_size_t;
+
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L1, 0>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L1, 1>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L1, 2>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L1, 3>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L1, 31>, mp_list<>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L1, mp_false>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L1, mp_true>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L1, mp_int<2>>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L1, mp_int<3>>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L1, mp_size_t<31>>, mp_list<>>));
+
+ using L2 = mp_list<X1>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L2, 0>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L2, 1>, mp_list<X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L2, 2>, mp_list<X1, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L2, 3>, mp_list<X1, X1, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L2, 4>, mp_list<X1, X1, X1, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L2, 5>, mp_list<X1, X1, X1, X1, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L2, 6>, mp_list<X1, X1, X1, X1, X1, X1>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L2, mp_false>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L2, mp_true>, mp_list<X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L2, mp_int<2>>, mp_list<X1, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L2, mp_int<3>>, mp_list<X1, X1, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L2, mp_int<4>>, mp_list<X1, X1, X1, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L2, mp_size_t<5>>, mp_list<X1, X1, X1, X1, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L2, mp_size_t<6>>, mp_list<X1, X1, X1, X1, X1, X1>>));
+
+ using L3 = mp_list<X1, X2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L3, 0>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L3, 1>, mp_list<X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L3, 2>, mp_list<X1, X2, X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L3, 3>, mp_list<X1, X2, X1, X2, X1, X2>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L3, mp_false>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L3, mp_true>, mp_list<X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L3, mp_int<2>>, mp_list<X1, X2, X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L3, mp_size_t<3>>, mp_list<X1, X2, X1, X2, X1, X2>>));
+
+ //
+
+ using L4 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L4, 0>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L4, 1>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L4, 2>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L4, 3>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L4, 31>, std::tuple<>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L4, mp_false>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L4, mp_true>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L4, mp_int<2>>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L4, mp_int<3>>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L4, mp_size_t<31>>, std::tuple<>>));
+
+ using L5 = std::tuple<X1>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L5, 0>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L5, 1>, std::tuple<X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L5, 2>, std::tuple<X1, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L5, 3>, std::tuple<X1, X1, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L5, 4>, std::tuple<X1, X1, X1, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L5, 5>, std::tuple<X1, X1, X1, X1, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L5, 6>, std::tuple<X1, X1, X1, X1, X1, X1>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L5, mp_false>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L5, mp_true>, std::tuple<X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L5, mp_int<2>>, std::tuple<X1, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L5, mp_int<3>>, std::tuple<X1, X1, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L5, mp_int<4>>, std::tuple<X1, X1, X1, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L5, mp_size_t<5>>, std::tuple<X1, X1, X1, X1, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L5, mp_size_t<6>>, std::tuple<X1, X1, X1, X1, X1, X1>>));
+
+ using L6 = std::tuple<X1, X2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L6, 0>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L6, 1>, std::tuple<X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L6, 2>, std::tuple<X1, X2, X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L6, 3>, std::tuple<X1, X2, X1, X2, X1, X2>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L6, mp_false>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L6, mp_true>, std::tuple<X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L6, mp_int<2>>, std::tuple<X1, X2, X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L6, mp_size_t<3>>, std::tuple<X1, X2, X1, X2, X1, X2>>));
+
+ //
+
+ using L7 = std::pair<X1, X2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat_c<L7, 1>, std::pair<X1, X2>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_repeat<L7, mp_true>, std::pair<X1, X2>>));
+
+ //
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_replace.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,61 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_replace;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace<L1, void, int[]>, L1>));
+
+ using L2 = mp_list<X1, X2, X3, X2, X3, X3>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace<L2, void, int[]>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace<L2, X1, int[]>, mp_list<int[], X2, X3, X2, X3, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace<L2, X2, int[]>, mp_list<X1, int[], X3, int[], X3, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace<L2, X3, int[]>, mp_list<X1, X2, int[], X2, int[], int[]>>));
+ }
+
+ {
+ using L1 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace<L1, void, int[]>, L1>));
+
+ using L2 = std::tuple<X1, X2, X3, X2, X3, X3>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace<L2, void, int[]>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace<L2, X1, int[]>, std::tuple<int[], X2, X3, X2, X3, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace<L2, X2, int[]>, std::tuple<X1, int[], X3, int[], X3, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace<L2, X3, int[]>, std::tuple<X1, X2, int[], X2, int[], int[]>>));
+ }
+
+ {
+ using L2 = std::pair<X1, X2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace<L2, void, int[]>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace<L2, X1, int[]>, std::pair<int[], X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace<L2, X2, int[]>, std::pair<X1, int[]>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_replace_at.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,60 @@
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+struct X4 {};
+struct X5 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_replace_at;
+ using boost::mp11::mp_int;
+ using boost::mp11::mp_true;
+ using boost::mp11::mp_false;
+
+ {
+ using L = mp_list<X1, X2, X3, X4, X5>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at<L, mp_int<0>, void>, mp_list<void, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at<L, mp_int<1>, void>, mp_list<X1, void, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at<L, mp_int<2>, void>, mp_list<X1, X2, void, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at<L, mp_int<3>, void>, mp_list<X1, X2, X3, void, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at<L, mp_int<4>, void>, mp_list<X1, X2, X3, X4, void>>));
+ }
+
+ {
+ using L = std::tuple<X1, X2, X3, X4, X5>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at<L, mp_int<0>, void>, std::tuple<void, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at<L, mp_int<1>, void>, std::tuple<X1, void, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at<L, mp_int<2>, void>, std::tuple<X1, X2, void, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at<L, mp_int<3>, void>, std::tuple<X1, X2, X3, void, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at<L, mp_int<4>, void>, std::tuple<X1, X2, X3, X4, void>>));
+ }
+
+ {
+ using L = std::pair<X1, X2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at<L, mp_false, void>, std::pair<void, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at<L, mp_true, void>, std::pair<X1, void>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_replace_at_c.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,56 @@
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+struct X4 {};
+struct X5 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_replace_at_c;
+
+ {
+ using L = mp_list<X1, X2, X3, X4, X5>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at_c<L, 0, void>, mp_list<void, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at_c<L, 1, void>, mp_list<X1, void, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at_c<L, 2, void>, mp_list<X1, X2, void, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at_c<L, 3, void>, mp_list<X1, X2, X3, void, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at_c<L, 4, void>, mp_list<X1, X2, X3, X4, void>>));
+ }
+
+ {
+ using L = std::tuple<X1, X2, X3, X4, X5>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at_c<L, 0, void>, std::tuple<void, X2, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at_c<L, 1, void>, std::tuple<X1, void, X3, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at_c<L, 2, void>, std::tuple<X1, X2, void, X4, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at_c<L, 3, void>, std::tuple<X1, X2, X3, void, X5>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at_c<L, 4, void>, std::tuple<X1, X2, X3, X4, void>>));
+ }
+
+ {
+ using L = std::pair<X1, X2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at_c<L, 0, void>, std::pair<void, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_at_c<L, 1, void>, std::pair<X1, void>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_replace_front.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,80 @@
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+struct X4 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_replace_front;
+ using boost::mp11::mp_replace_first;
+
+ {
+ using L1 = mp_list<X1>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_front<L1, void>, mp_list<void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_first<L1, void>, mp_list<void>>));
+
+ using L2 = mp_list<X1, X2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_front<L2, void>, mp_list<void, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_first<L2, void>, mp_list<void, X2>>));
+
+ using L3 = mp_list<X1, X2, X3>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_front<L3, void>, mp_list<void, X2, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_first<L3, void>, mp_list<void, X2, X3>>));
+
+ using L4 = mp_list<X1, X2, X3, X4>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_front<L4, void>, mp_list<void, X2, X3, X4>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_first<L4, void>, mp_list<void, X2, X3, X4>>));
+ }
+
+ {
+ using L1 = std::tuple<X1>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_front<L1, void>, std::tuple<void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_first<L1, void>, std::tuple<void>>));
+
+ using L2 = std::tuple<X1, X2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_front<L2, void>, std::tuple<void, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_first<L2, void>, std::tuple<void, X2>>));
+
+ using L3 = std::tuple<X1, X2, X3>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_front<L3, void>, std::tuple<void, X2, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_first<L3, void>, std::tuple<void, X2, X3>>));
+
+ using L4 = std::tuple<X1, X2, X3, X4>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_front<L4, void>, std::tuple<void, X2, X3, X4>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_first<L4, void>, std::tuple<void, X2, X3, X4>>));
+ }
+
+ {
+ using L2 = std::pair<X1, X2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_front<L2, void>, std::pair<void, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_first<L2, void>, std::pair<void, X2>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_replace_if.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,57 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_replace_if;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_if<L1, std::is_const, void>, L1>));
+
+ using L2 = mp_list<X1, X1 const, X1*, X1 const, X1*, X1*>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_if<L2, std::is_volatile, void>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_if<L2, std::is_const, void>, mp_list<X1, void, X1*, void, X1*, X1*>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_if<L2, std::is_pointer, void>, mp_list<X1, X1 const, void, X1 const, void, void>>));
+ }
+
+ {
+ using L1 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_if<L1, std::is_const, void>, L1>));
+
+ using L2 = std::tuple<X1, X1 const, X1*, X1 const, X1*, X1*>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_if<L2, std::is_volatile, void>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_if<L2, std::is_const, void>, std::tuple<X1, void, X1*, void, X1*, X1*>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_if<L2, std::is_pointer, void>, std::tuple<X1, X1 const, void, X1 const, void, void>>));
+ }
+
+ {
+ using L2 = std::pair<X1 const, X1*>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_if<L2, std::is_volatile, void>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_if<L2, std::is_const, void>, std::pair<void, X1*>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_if<L2, std::is_pointer, void>, std::pair<X1 const, void>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_replace_second.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,62 @@
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+struct X4 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_replace_second;
+
+ {
+ using L2 = mp_list<X1, X2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_second<L2, void>, mp_list<X1, void>>));
+
+ using L3 = mp_list<X1, X2, X3>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_second<L3, void>, mp_list<X1, void, X3>>));
+
+ using L4 = mp_list<X1, X2, X3, X4>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_second<L4, void>, mp_list<X1, void, X3, X4>>));
+ }
+
+ {
+ using L2 = std::tuple<X1, X2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_second<L2, void>, std::tuple<X1, void>>));
+
+ using L3 = std::tuple<X1, X2, X3>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_second<L3, void>, std::tuple<X1, void, X3>>));
+
+ using L4 = std::tuple<X1, X2, X3, X4>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_second<L4, void>, std::tuple<X1, void, X3, X4>>));
+ }
+
+ {
+ using L2 = std::pair<X1, X2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_second<L2, void>, std::pair<X1, void>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_replace_third.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,48 @@
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+struct X4 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_replace_third;
+
+ {
+ using L3 = mp_list<X1, X2, X3>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_third<L3, void>, mp_list<X1, X2, void>>));
+
+ using L4 = mp_list<X1, X2, X3, X4>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_third<L4, void>, mp_list<X1, X2, void, X4>>));
+ }
+
+ {
+ using L3 = std::tuple<X1, X2, X3>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_third<L3, void>, std::tuple<X1, X2, void>>));
+
+ using L4 = std::tuple<X1, X2, X3, X4>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_replace_third<L4, void>, std::tuple<X1, X2, void, X4>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_reverse.cpp 2017-08-28 02:56:56.000000000 -0700
@@ -0,0 +1,96 @@
+
+// Copyright 2015-2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+#include <type_traits>
+#include <tuple>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+struct X4 {};
+struct X5 {};
+struct X6 {};
+struct X7 {};
+struct X8 {};
+struct X9 {};
+struct X10 {};
+struct X11 {};
+struct X12 {};
+
+using boost::mp11::mp_plus;
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_reverse;
+
+ {
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<mp_list<>>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<mp_list<X1>>, mp_list<X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<mp_list<X1, X2>>, mp_list<X2, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<mp_list<X1, X2, X3>>, mp_list<X3, X2, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<mp_list<X1, X2, X3, X4>>, mp_list<X4, X3, X2, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<mp_list<X1, X2, X3, X4, X5>>, mp_list<X5, X4, X3, X2, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<mp_list<X1, X2, X3, X4, X5, X6>>, mp_list<X6, X5, X4, X3, X2, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<mp_list<X1, X2, X3, X4, X5, X6, X7>>, mp_list<X7, X6, X5, X4, X3, X2, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<mp_list<X1, X2, X3, X4, X5, X6, X7, X8>>, mp_list<X8, X7, X6, X5, X4, X3, X2, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<mp_list<X1, X2, X3, X4, X5, X6, X7, X8, X9>>, mp_list<X9, X8, X7, X6, X5, X4, X3, X2, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<mp_list<X1, X2, X3, X4, X5, X6, X7, X8, X9, X10>>, mp_list<X10, X9, X8, X7, X6, X5, X4, X3, X2, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<mp_list<X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11>>, mp_list<X11, X10, X9, X8, X7, X6, X5, X4, X3, X2, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<mp_list<X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12>>, mp_list<X12, X11, X10, X9, X8, X7, X6, X5, X4, X3, X2, X1>>));
+ }
+
+ {
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<std::tuple<>>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<std::tuple<X1>>, std::tuple<X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<std::tuple<X1, X2>>, std::tuple<X2, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<std::tuple<X1, X2, X3>>, std::tuple<X3, X2, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<std::tuple<X1, X2, X3, X4>>, std::tuple<X4, X3, X2, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<std::tuple<X1, X2, X3, X4, X5>>, std::tuple<X5, X4, X3, X2, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<std::tuple<X1, X2, X3, X4, X5, X6>>, std::tuple<X6, X5, X4, X3, X2, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<std::tuple<X1, X2, X3, X4, X5, X6, X7>>, std::tuple<X7, X6, X5, X4, X3, X2, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<std::tuple<X1, X2, X3, X4, X5, X6, X7, X8>>, std::tuple<X8, X7, X6, X5, X4, X3, X2, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<std::tuple<X1, X2, X3, X4, X5, X6, X7, X8, X9>>, std::tuple<X9, X8, X7, X6, X5, X4, X3, X2, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<std::tuple<X1, X2, X3, X4, X5, X6, X7, X8, X9, X10>>, std::tuple<X10, X9, X8, X7, X6, X5, X4, X3, X2, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<std::tuple<X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11>>, std::tuple<X11, X10, X9, X8, X7, X6, X5, X4, X3, X2, X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<std::tuple<X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12>>, std::tuple<X12, X11, X10, X9, X8, X7, X6, X5, X4, X3, X2, X1>>));
+ }
+
+ {
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse<std::pair<X1, X2>>, std::pair<X2, X1>>));
+ }
+
+ using boost::mp11::mp_iota_c;
+ using boost::mp11::mp_size_t;
+ using boost::mp11::mp_transform;
+ using boost::mp11::mp_fill;
+
+ {
+ int const N = 37;
+
+ using L = mp_iota_c<N>;
+
+ using R1 = mp_reverse<L>;
+ using R2 = mp_reverse<R1>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<R2, L>));
+
+ using R3 = mp_transform<mp_plus, R1, R2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<R3, mp_fill<L, mp_size_t<N-1>>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_reverse_fold.cpp 2017-08-28 02:56:56.000000000 -0700
@@ -0,0 +1,83 @@
+
+// Copyright 2015-2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+#include <type_traits>
+#include <tuple>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+struct X4 {};
+
+template<class T1, class T2> struct F {};
+
+using boost::mp11::mp_push_back;
+using boost::mp11::mp_push_front;
+
+template<class T, class L> using rev_push_back = mp_push_back<L, T>;
+template<class T, class L> using rev_push_front = mp_push_front<L, T>;
+
+using boost::mp11::mp_plus;
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_reverse_fold;
+
+ {
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse_fold<mp_list<>, void, F>, void>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse_fold<mp_list<X1>, void, F>, F<X1, void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse_fold<mp_list<X1, X2>, void, F>, F<X1, F<X2, void>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse_fold<mp_list<X1, X2, X3>, void, F>, F<X1, F<X2, F<X3, void>>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse_fold<mp_list<X1, X2, X3, X4>, void, F>, F<X1, F<X2, F<X3, F<X4, void>>>>>));
+ }
+
+ {
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse_fold<std::tuple<>, void, F>, void>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse_fold<std::tuple<X1>, void, F>, F<X1, void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse_fold<std::tuple<X1, X2>, void, F>, F<X1, F<X2, void>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse_fold<std::tuple<X1, X2, X3>, void, F>, F<X1, F<X2, F<X3, void>>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse_fold<std::tuple<X1, X2, X3, X4>, void, F>, F<X1, F<X2, F<X3, F<X4, void>>>>>));
+ }
+
+ {
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse_fold<std::tuple<X1, X2, X3, X4>, mp_list<>, rev_push_back>, mp_list<X4, X3, X2, X1>>));
+ }
+
+ {
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_reverse_fold<std::tuple<X1, X2, X3, X4>, mp_list<>, rev_push_front>, mp_list<X1, X2, X3, X4>>));
+ }
+
+ using boost::mp11::mp_iota_c;
+ using boost::mp11::mp_reverse;
+ using boost::mp11::mp_size_t;
+
+ {
+ int const N = 37;
+
+ using L = mp_iota_c<N>;
+
+ using R1 = mp_reverse_fold<L, mp_list<>, rev_push_front>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<R1, L>));
+
+ using R2 = mp_reverse_fold<L, mp_list<>, rev_push_back>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<R2, mp_reverse<L>>));
+
+ using R3 = mp_reverse_fold<L, mp_size_t<0>, mp_plus>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<R3, mp_size_t<N*(N-1)/2>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_same.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,33 @@
+
+// Copyright 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/function.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+int main()
+{
+ using boost::mp11::mp_same;
+ using boost::mp11::mp_true;
+ using boost::mp11::mp_false;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_same<>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_same<void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_same<void, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_same<void, void, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_same<void, void, void, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_same<void, void, void, void, void>, mp_true>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_same<void, int>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_same<void, void, int>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_same<void, void, void, int>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_same<void, void, void, void, int>, mp_false>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_second.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,34 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/core/lightweight_test_trait.hpp>
+#include <boost/mp11/list.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_second;
+
+ using L1 = mp_list<void, char[]>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_second<L1>, char[]>));
+
+ using L2 = mp_list<int[], void, float>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_second<L2>, void>));
+
+ using L3 = std::tuple<int, float>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_second<L3>, float>));
+
+ using L4 = std::pair<char, double>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_second<L4>, double>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_set_contains.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,83 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/set.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_set_contains;
+ using boost::mp11::mp_true;
+ using boost::mp11::mp_false;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L1, void>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L1, int>, mp_false>));
+
+ using L2 = mp_list<void>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L2, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L2, int>, mp_false>));
+
+ using L3 = mp_list<void, int>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L3, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L3, int>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L3, void const>, mp_false>));
+
+ using L4 = mp_list<void, int, char[]>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L4, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L4, int>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L4, char[]>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L4, void const>, mp_false>));
+ }
+
+ {
+ using L1 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L1, void>, mp_false>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L1, int>, mp_false>));
+
+ using L2 = std::tuple<void>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L2, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L2, int>, mp_false>));
+
+ using L3 = std::tuple<void, int>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L3, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L3, int>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L3, void const>, mp_false>));
+
+ using L4 = std::tuple<void, int, char[]>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L4, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L4, int>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L4, char[]>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L4, void const>, mp_false>));
+ }
+
+ {
+ using L3 = std::pair<void, int>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L3, void>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L3, int>, mp_true>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_contains<L3, void const>, mp_false>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_set_push_back.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,122 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/set.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_set_push_back;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L1>, L1>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L1, void>, mp_list<void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L1, int>, mp_list<int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L1, void, int>, mp_list<void, int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L1, void, int, char[]>, mp_list<void, int, char[]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L1, void, int, void, int, void, int>, mp_list<void, int>>));
+ }
+
+ {
+ using L2 = mp_list<void>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L2>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L2, void>, L2>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L2, int>, mp_list<void, int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L2, int, void>, mp_list<void, int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L2, int, int, int, void, void, void>, mp_list<void, int>>));
+ }
+
+ {
+ using L3 = mp_list<void, int>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L3>, L3>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L3, void>, L3>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L3, int>, L3>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L3, int, int, int, void, void, void>, L3>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L3, void const>, mp_list<void, int, void const>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L3, int, char[], int, char[], void, char[], void, char[]>, mp_list<void, int, char[]>>));
+ }
+
+ {
+ using L4 = mp_list<void, int, char[]>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L4>, L4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L4, void>, L4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L4, int>, L4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L4, char[]>, L4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L4, void, int, char[], void, int, char[]>, L4>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L4, void const>, mp_list<void, int, char[], void const>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L4, void const, int const, char const[]>, mp_list<void, int, char[], void const, int const, char const[]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L4, void, void const, int, int const, char[], char const[]>, mp_list<void, int, char[], void const, int const, char const[]>>));
+ }
+
+ //
+
+ {
+ using L1 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L1>, L1>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L1, void>, std::tuple<void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L1, int>, std::tuple<int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L1, void, int>, std::tuple<void, int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L1, void, int, char[]>, std::tuple<void, int, char[]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L1, void, int, void, int, void, int>, std::tuple<void, int>>));
+ }
+
+ {
+ using L2 = std::tuple<void>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L2>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L2, void>, L2>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L2, int>, std::tuple<void, int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L2, int, void>, std::tuple<void, int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L2, int, int, int, void, void, void>, std::tuple<void, int>>));
+ }
+
+ {
+ using L3 = std::tuple<void, int>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L3>, L3>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L3, void>, L3>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L3, int>, L3>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L3, int, int, int, void, void, void>, L3>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L3, void const>, std::tuple<void, int, void const>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L3, int, char[], int, char[], void, char[], void, char[]>, std::tuple<void, int, char[]>>));
+ }
+
+ {
+ using L4 = std::tuple<void, int, char[]>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L4>, L4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L4, void>, L4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L4, int>, L4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L4, char[]>, L4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L4, void, int, char[], void, int, char[]>, L4>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L4, void const>, std::tuple<void, int, char[], void const>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L4, void const, int const, char const[]>, std::tuple<void, int, char[], void const, int const, char const[]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_back<L4, void, void const, int, int const, char[], char const[]>, std::tuple<void, int, char[], void const, int const, char const[]>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_set_push_front.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,124 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/set.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_set_push_front;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L1>, L1>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L1, void>, mp_list<void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L1, int>, mp_list<int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L1, void, int>, mp_list<void, int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L1, void, int, char[]>, mp_list<void, int, char[]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L1, void, int, void, int, void, int>, mp_list<void, int>>));
+ }
+
+ {
+ using L2 = mp_list<void>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L2>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L2, void>, L2>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L2, int>, mp_list<int, void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L2, void, int>, mp_list<int, void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L2, void, void, void, int, int, int>, mp_list<int, void>>));
+ }
+
+ {
+ using L3 = mp_list<void, int>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L3>, L3>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L3, void>, L3>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L3, int>, L3>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L3, int, int, int, void, void, void>, L3>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L3, void const>, mp_list<void const, void, int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L3, void const, int const>, mp_list<void const, int const, void, int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L3, int, char[], int, char[], void, char[], void, char[]>, mp_list<char[], void, int>>));
+ }
+
+ {
+ using L4 = mp_list<void, int, char[]>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L4>, L4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L4, void>, L4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L4, int>, L4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L4, char[]>, L4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L4, void, int, char[], void, int, char[]>, L4>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L4, void const>, mp_list<void const, void, int, char[]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L4, void const, int const, char const[]>, mp_list<void const, int const, char const[], void, int, char[]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L4, void, void const, int, int const, char[], char const[]>, mp_list<void const, int const, char const[], void, int, char[]>>));
+ }
+
+ //
+
+ {
+ using L1 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L1>, L1>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L1, void>, std::tuple<void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L1, int>, std::tuple<int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L1, void, int>, std::tuple<void, int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L1, void, int, char[]>, std::tuple<void, int, char[]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L1, void, int, void, int, void, int>, std::tuple<void, int>>));
+ }
+
+ {
+ using L2 = std::tuple<void>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L2>, L2>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L2, void>, L2>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L2, int>, std::tuple<int, void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L2, void, int>, std::tuple<int, void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L2, void, void, void, int, int, int>, std::tuple<int, void>>));
+ }
+
+ {
+ using L3 = std::tuple<void, int>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L3>, L3>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L3, void>, L3>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L3, int>, L3>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L3, int, int, int, void, void, void>, L3>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L3, void const>, std::tuple<void const, void, int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L3, void const, int const>, std::tuple<void const, int const, void, int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L3, int, char[], int, char[], void, char[], void, char[]>, std::tuple<char[], void, int>>));
+ }
+
+ {
+ using L4 = std::tuple<void, int, char[]>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L4>, L4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L4, void>, L4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L4, int>, L4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L4, char[]>, L4>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L4, void, int, char[], void, int, char[]>, L4>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L4, void const>, std::tuple<void const, void, int, char[]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L4, void const, int const, char const[]>, std::tuple<void const, int const, char const[], void, int, char[]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_set_push_front<L4, void, void const, int, int const, char[], char const[]>, std::tuple<void const, int const, char const[], void, int, char[]>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_size.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,48 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/core/lightweight_test_trait.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_size;
+ using boost::mp11::mp_size_t;
+
+ using L1 = mp_list<>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_size<L1>, mp_size_t<0>>));
+
+ using L2 = mp_list<void>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_size<L2>, mp_size_t<1>>));
+
+ using L3 = mp_list<int[], void, float>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_size<L3>, mp_size_t<3>>));
+
+ using L4 = std::tuple<>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_size<L4>, mp_size_t<0>>));
+
+ using L5 = std::tuple<int>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_size<L5>, mp_size_t<1>>));
+
+ using L6 = std::tuple<int, int>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_size<L6>, mp_size_t<2>>));
+
+ using L7 = std::pair<char, double>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_size<L7>, mp_size_t<2>>));
+
+ using L8 = std::add_const<void()>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_size<L8>, mp_size_t<1>>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_sort.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,55 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+
+using boost::mp11::mp_bool;
+
+template<class T, class U> using sizeof_less = mp_bool<(sizeof(T) < sizeof(U))>;
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_sort;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_sort<L1, sizeof_less>, L1>));
+
+ using L2 = mp_list<char[2], char[4], char[3], char[1]>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_sort<L2, sizeof_less>, mp_list<char[1], char[2], char[3], char[4]>>));
+
+ using L3 = mp_list<char[2], char[4], char[2], char[3], char[1], char[2], char[1]>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_sort<L3, sizeof_less>, mp_list<char[1], char[1], char[2], char[2], char[2], char[3], char[4]>>));
+ }
+
+ {
+ using L1 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_sort<L1, sizeof_less>, L1>));
+
+ using L2 = std::tuple<char[2], char[4], char[3], char[1]>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_sort<L2, sizeof_less>, std::tuple<char[1], char[2], char[3], char[4]>>));
+
+ using L3 = std::tuple<char[2], char[4], char[2], char[3], char[1], char[2], char[1]>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_sort<L3, sizeof_less>, std::tuple<char[1], char[1], char[2], char[2], char[2], char[3], char[4]>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_take.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,95 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+struct X4 {};
+struct X5 {};
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_take;
+ using boost::mp11::mp_take_c;
+ using boost::mp11::mp_size_t;
+
+ {
+ using L1 = mp_list<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take_c<L1, 0>, L1>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L1, mp_size_t<0>>, L1>));
+
+ using L2 = mp_list<X1, X2, X3, X4, X5>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take_c<L2, 0>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take_c<L2, 1>, mp_list<X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take_c<L2, 2>, mp_list<X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take_c<L2, 3>, mp_list<X1, X2, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take_c<L2, 4>, mp_list<X1, X2, X3, X4>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take_c<L2, 5>, mp_list<X1, X2, X3, X4, X5>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<0>>, mp_list<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<1>>, mp_list<X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<2>>, mp_list<X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<3>>, mp_list<X1, X2, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<4>>, mp_list<X1, X2, X3, X4>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<5>>, mp_list<X1, X2, X3, X4, X5>>));
+
+ using L3 = mp_list<X1, X2, X3, X4, X5, X1, X2, X3, X4, X5, X1, X2, X3, X4, X5, X1, X2, X3, X4, X5>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take_c<L3, 8>, mp_list<X1, X2, X3, X4, X5, X1, X2, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L3, mp_size_t<9>>, mp_list<X1, X2, X3, X4, X5, X1, X2, X3, X4>>));
+ }
+
+ {
+ using L1 = std::tuple<>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take_c<L1, 0>, L1>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L1, mp_size_t<0>>, L1>));
+
+ using L2 = std::tuple<X1, X2, X3, X4, X5>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take_c<L2, 0>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take_c<L2, 1>, std::tuple<X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take_c<L2, 2>, std::tuple<X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take_c<L2, 3>, std::tuple<X1, X2, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take_c<L2, 4>, std::tuple<X1, X2, X3, X4>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take_c<L2, 5>, std::tuple<X1, X2, X3, X4, X5>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<0>>, std::tuple<>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<1>>, std::tuple<X1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<2>>, std::tuple<X1, X2>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<3>>, std::tuple<X1, X2, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<4>>, std::tuple<X1, X2, X3, X4>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<5>>, std::tuple<X1, X2, X3, X4, X5>>));
+
+ using L3 = std::tuple<X1, X2, X3, X4, X5, X1, X2, X3, X4, X5, X1, X2, X3, X4, X5, X1, X2, X3, X4, X5>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take_c<L3, 8>, std::tuple<X1, X2, X3, X4, X5, X1, X2, X3>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L3, mp_size_t<9>>, std::tuple<X1, X2, X3, X4, X5, X1, X2, X3, X4>>));
+ }
+
+ {
+ using L1 = std::pair<X1, X2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take_c<L1, 2>, L1>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L1, mp_size_t<2>>, L1>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_third.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,28 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/core/lightweight_test_trait.hpp>
+#include <boost/mp11/list.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_third;
+
+ using L1 = mp_list<int[], void, float[]>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_third<L1>, float[]>));
+
+ using L2 = std::tuple<int, float, char>;
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_third<L2>, char>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_transform.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,105 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+struct X4 {};
+
+struct Y1 {};
+struct Y2 {};
+struct Y3 {};
+struct Y4 {};
+
+struct Z1 {};
+struct Z2 {};
+struct Z3 {};
+struct Z4 {};
+
+struct U1 {};
+struct U2 {};
+
+struct V1 {};
+struct V2 {};
+
+struct W1 {};
+struct W2 {};
+
+template<class T> using add_pointer = typename std::add_pointer<T>::type;
+template<class T, class U> using is_same = typename std::is_same<T, U>::type;
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_transform;
+
+ using L1 = mp_list<X1, X2, X3, X4>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<mp_list, L1>, mp_list<mp_list<X1>, mp_list<X2>, mp_list<X3>, mp_list<X4>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<std::tuple, L1>, mp_list<std::tuple<X1>, std::tuple<X2>, std::tuple<X3>, std::tuple<X4>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<std::add_pointer, L1>, mp_list<std::add_pointer<X1>, std::add_pointer<X2>, std::add_pointer<X3>, std::add_pointer<X4>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<add_pointer, L1>, mp_list<X1*, X2*, X3*, X4*>>));
+
+ using L2 = std::tuple<Y1, Y2, Y3, Y4>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<mp_list, L1, L2>, mp_list<mp_list<X1, Y1>, mp_list<X2, Y2>, mp_list<X3, Y3>, mp_list<X4, Y4>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<std::tuple, L1, L2>, mp_list<std::tuple<X1, Y1>, std::tuple<X2, Y2>, std::tuple<X3, Y3>, std::tuple<X4, Y4>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<std::pair, L1, L2>, mp_list<std::pair<X1, Y1>, std::pair<X2, Y2>, std::pair<X3, Y3>, std::pair<X4, Y4>>>));
+
+ using L3 = mp_list<Z1, Z2, Z3, Z4>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<mp_list, L1, L2, L3>, mp_list<mp_list<X1, Y1, Z1>, mp_list<X2, Y2, Z2>, mp_list<X3, Y3, Z3>, mp_list<X4, Y4, Z4>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<std::tuple, L1, L2, L3>, mp_list<std::tuple<X1, Y1, Z1>, std::tuple<X2, Y2, Z2>, std::tuple<X3, Y3, Z3>, std::tuple<X4, Y4, Z4>>>));
+
+ //
+
+ using L4 = std::tuple<X1, Y2, X3, Y4>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<is_same, L1, L1>, mp_list<std::true_type, std::true_type, std::true_type, std::true_type>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<is_same, L1, L2>, mp_list<std::false_type, std::false_type, std::false_type, std::false_type>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<is_same, L1, L4>, mp_list<std::true_type, std::false_type, std::true_type, std::false_type>>));
+
+ //
+
+ using L5 = std::pair<X1, X2>;
+ using L6 = std::pair<Y1, Y2>;
+ using L7 = std::pair<X1, Y2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<mp_list, L5>, std::pair<mp_list<X1>, mp_list<X2>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<mp_list, L5, L6>, std::pair<mp_list<X1, Y1>, mp_list<X2, Y2>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<mp_list, L5, L6, L7>, std::pair<mp_list<X1, Y1, X1>, mp_list<X2, Y2, Y2>>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<add_pointer, L5>, std::pair<X1*, X2*>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<is_same, L5, L5>, std::pair<std::true_type, std::true_type>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<is_same, L5, L6>, std::pair<std::false_type, std::false_type>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<is_same, L5, L7>, std::pair<std::true_type, std::false_type>>));
+
+ //
+
+ using L8 = std::pair<Z1, Z2>;
+ using L9 = std::pair<U1, U2>;
+ using L10 = std::pair<V1, V2>;
+ using L11 = std::pair<W1, W2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<std::tuple, L5, L6, L8, L9>, std::pair<std::tuple<X1, Y1, Z1, U1>, std::tuple<X2, Y2, Z2, U2>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<std::tuple, L5, L6, L8, L9, L10>, std::pair<std::tuple<X1, Y1, Z1, U1, V1>, std::tuple<X2, Y2, Z2, U2, V2>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform<std::tuple, L5, L6, L8, L9, L10, L11>, std::pair<std::tuple<X1, Y1, Z1, U1, V1, W1>, std::tuple<X2, Y2, Z2, U2, V2, W2>>>));
+
+ //
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_transform_if.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,74 @@
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+struct X4 {};
+
+using boost::mp11::mp_not;
+
+template<class T> using add_pointer = T*;
+template<class T, class...> using is_not_ref = mp_not<std::is_reference<T>>;
+template<class T1, class T2> using second = T2;
+template<class T1, class T2, class T3> using third = T3;
+template<class T1, class T2, class T3, class T4> using fourth = T4;
+template<class T1, class T2, class T3, class T4, class T5> using fifth = T5;
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_transform_if;
+ using boost::mp11::mp_size_t;
+ using boost::mp11::mp_size;
+ using boost::mp11::mp_fill;
+ using boost::mp11::mp_iota;
+
+ using L1 = mp_list<X1, X2&, X3 const, X4 const&>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if<is_not_ref, add_pointer, L1>, mp_list<X1*, X2&, X3 const*, X4 const&>>));
+
+ using L2 = std::tuple<X1, X2&, X3 const, X4 const&>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if<is_not_ref, add_pointer, L2>, std::tuple<X1*, X2&, X3 const*, X4 const&>>));
+
+ using L3 = std::pair<X1 const, X2&>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if<is_not_ref, add_pointer, L3>, std::pair<X1 const*, X2&>>));
+
+ //
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if<is_not_ref, second, L1, mp_fill<L1, void>>, mp_list<void, X2&, void, X4 const&>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if<is_not_ref, second, L2, mp_fill<L2, void>>, std::tuple<void, X2&, void, X4 const&>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if<is_not_ref, second, L3, mp_fill<L3, void>>, std::pair<void, X2&>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if<is_not_ref, third, L1, L1, mp_iota<mp_size<L1>>>, mp_list<mp_size_t<0>, X2&, mp_size_t<2>, X4 const&>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if<is_not_ref, third, L2, L2, mp_iota<mp_size<L2>>>, std::tuple<mp_size_t<0>, X2&, mp_size_t<2>, X4 const&>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if<is_not_ref, third, L3, L3, mp_iota<mp_size<L3>>>, std::pair<mp_size_t<0>, X2&>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if<is_not_ref, fourth, L1, L1, L1, mp_iota<mp_size<L1>>>, mp_list<mp_size_t<0>, X2&, mp_size_t<2>, X4 const&>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if<is_not_ref, fourth, L2, L2, L2, mp_iota<mp_size<L2>>>, std::tuple<mp_size_t<0>, X2&, mp_size_t<2>, X4 const&>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if<is_not_ref, fourth, L3, L3, L3, mp_iota<mp_size<L3>>>, std::pair<mp_size_t<0>, X2&>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if<is_not_ref, fifth, L1, L1, L1, L1, mp_iota<mp_size<L1>>>, mp_list<mp_size_t<0>, X2&, mp_size_t<2>, X4 const&>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if<is_not_ref, fifth, L2, L2, L2, L2, mp_iota<mp_size<L2>>>, std::tuple<mp_size_t<0>, X2&, mp_size_t<2>, X4 const&>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if<is_not_ref, fifth, L3, L3, L3, L3, mp_iota<mp_size<L3>>>, std::pair<mp_size_t<0>, X2&>>));
+
+ //
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_transform_if_q.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,87 @@
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/integral.hpp>
+#include <boost/mp11/utility.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+struct X4 {};
+
+using boost::mp11::mp_not;
+using boost::mp11::mp_quote;
+
+template<class T> using add_pointer = T*;
+using Q_add_pointer = mp_quote<add_pointer>;
+
+template<class T, class...> using is_not_ref = mp_not<std::is_reference<T>>;
+using Q_is_not_ref = mp_quote<is_not_ref>;
+
+template<class T1, class T2> using second = T2;
+using Q_second = mp_quote<second>;
+
+template<class T1, class T2, class T3> using third = T3;
+using Q_third = mp_quote<third>;
+
+template<class T1, class T2, class T3, class T4> using fourth = T4;
+using Q_fourth = mp_quote<fourth>;
+
+template<class T1, class T2, class T3, class T4, class T5> using fifth = T5;
+using Q_fifth = mp_quote<fifth>;
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_transform_if_q;
+ using boost::mp11::mp_size_t;
+ using boost::mp11::mp_size;
+ using boost::mp11::mp_fill;
+ using boost::mp11::mp_iota;
+
+ using L1 = mp_list<X1, X2&, X3 const, X4 const&>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if_q<Q_is_not_ref, Q_add_pointer, L1>, mp_list<X1*, X2&, X3 const*, X4 const&>>));
+
+ using L2 = std::tuple<X1, X2&, X3 const, X4 const&>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if_q<Q_is_not_ref, Q_add_pointer, L2>, std::tuple<X1*, X2&, X3 const*, X4 const&>>));
+
+ using L3 = std::pair<X1 const, X2&>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if_q<Q_is_not_ref, Q_add_pointer, L3>, std::pair<X1 const*, X2&>>));
+
+ //
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if_q<Q_is_not_ref, Q_second, L1, mp_fill<L1, void>>, mp_list<void, X2&, void, X4 const&>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if_q<Q_is_not_ref, Q_second, L2, mp_fill<L2, void>>, std::tuple<void, X2&, void, X4 const&>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if_q<Q_is_not_ref, Q_second, L3, mp_fill<L3, void>>, std::pair<void, X2&>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if_q<Q_is_not_ref, Q_third, L1, L1, mp_iota<mp_size<L1>>>, mp_list<mp_size_t<0>, X2&, mp_size_t<2>, X4 const&>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if_q<Q_is_not_ref, Q_third, L2, L2, mp_iota<mp_size<L2>>>, std::tuple<mp_size_t<0>, X2&, mp_size_t<2>, X4 const&>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if_q<Q_is_not_ref, Q_third, L3, L3, mp_iota<mp_size<L3>>>, std::pair<mp_size_t<0>, X2&>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if_q<Q_is_not_ref, Q_fourth, L1, L1, L1, mp_iota<mp_size<L1>>>, mp_list<mp_size_t<0>, X2&, mp_size_t<2>, X4 const&>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if_q<Q_is_not_ref, Q_fourth, L2, L2, L2, mp_iota<mp_size<L2>>>, std::tuple<mp_size_t<0>, X2&, mp_size_t<2>, X4 const&>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if_q<Q_is_not_ref, Q_fourth, L3, L3, L3, mp_iota<mp_size<L3>>>, std::pair<mp_size_t<0>, X2&>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if_q<Q_is_not_ref, Q_fifth, L1, L1, L1, L1, mp_iota<mp_size<L1>>>, mp_list<mp_size_t<0>, X2&, mp_size_t<2>, X4 const&>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if_q<Q_is_not_ref, Q_fifth, L2, L2, L2, L2, mp_iota<mp_size<L2>>>, std::tuple<mp_size_t<0>, X2&, mp_size_t<2>, X4 const&>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_if_q<Q_is_not_ref, Q_fifth, L3, L3, L3, L3, mp_iota<mp_size<L3>>>, std::pair<mp_size_t<0>, X2&>>));
+
+ //
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_transform_q.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,114 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/utility.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+struct X1 {};
+struct X2 {};
+struct X3 {};
+struct X4 {};
+
+struct Y1 {};
+struct Y2 {};
+struct Y3 {};
+struct Y4 {};
+
+struct Z1 {};
+struct Z2 {};
+struct Z3 {};
+struct Z4 {};
+
+struct U1 {};
+struct U2 {};
+
+struct V1 {};
+struct V2 {};
+
+struct W1 {};
+struct W2 {};
+
+using boost::mp11::mp_quote;
+using boost::mp11::mp_list;
+
+template<class T> using add_pointer = typename std::add_pointer<T>::type;
+using Q_add_pointer = mp_quote<add_pointer>;
+
+template<class T, class U> using is_same = typename std::is_same<T, U>::type;
+using Q_is_same = mp_quote<is_same>;
+
+using Q_mp_list = mp_quote<mp_list>;
+using Q_std_tuple = mp_quote<std::tuple>;
+using Q_std_pair = mp_quote<std::pair>;
+
+int main()
+{
+ using boost::mp11::mp_transform_q;
+
+ using L1 = mp_list<X1, X2, X3, X4>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_mp_list, L1>, mp_list<mp_list<X1>, mp_list<X2>, mp_list<X3>, mp_list<X4>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_std_tuple, L1>, mp_list<std::tuple<X1>, std::tuple<X2>, std::tuple<X3>, std::tuple<X4>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_add_pointer, L1>, mp_list<X1*, X2*, X3*, X4*>>));
+
+ using L2 = std::tuple<Y1, Y2, Y3, Y4>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_mp_list, L1, L2>, mp_list<mp_list<X1, Y1>, mp_list<X2, Y2>, mp_list<X3, Y3>, mp_list<X4, Y4>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_std_tuple, L1, L2>, mp_list<std::tuple<X1, Y1>, std::tuple<X2, Y2>, std::tuple<X3, Y3>, std::tuple<X4, Y4>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_std_pair, L1, L2>, mp_list<std::pair<X1, Y1>, std::pair<X2, Y2>, std::pair<X3, Y3>, std::pair<X4, Y4>>>));
+
+ using L3 = mp_list<Z1, Z2, Z3, Z4>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_mp_list, L1, L2, L3>, mp_list<mp_list<X1, Y1, Z1>, mp_list<X2, Y2, Z2>, mp_list<X3, Y3, Z3>, mp_list<X4, Y4, Z4>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_std_tuple, L1, L2, L3>, mp_list<std::tuple<X1, Y1, Z1>, std::tuple<X2, Y2, Z2>, std::tuple<X3, Y3, Z3>, std::tuple<X4, Y4, Z4>>>));
+
+ //
+
+ using L4 = std::tuple<X1, Y2, X3, Y4>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_is_same, L1, L1>, mp_list<std::true_type, std::true_type, std::true_type, std::true_type>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_is_same, L1, L2>, mp_list<std::false_type, std::false_type, std::false_type, std::false_type>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_is_same, L1, L4>, mp_list<std::true_type, std::false_type, std::true_type, std::false_type>>));
+
+ //
+
+ using L5 = std::pair<X1, X2>;
+ using L6 = std::pair<Y1, Y2>;
+ using L7 = std::pair<X1, Y2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_mp_list, L5>, std::pair<mp_list<X1>, mp_list<X2>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_mp_list, L5, L6>, std::pair<mp_list<X1, Y1>, mp_list<X2, Y2>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_mp_list, L5, L6, L7>, std::pair<mp_list<X1, Y1, X1>, mp_list<X2, Y2, Y2>>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_add_pointer, L5>, std::pair<X1*, X2*>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_is_same, L5, L5>, std::pair<std::true_type, std::true_type>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_is_same, L5, L6>, std::pair<std::false_type, std::false_type>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_is_same, L5, L7>, std::pair<std::true_type, std::false_type>>));
+
+ //
+
+ using L8 = std::pair<Z1, Z2>;
+ using L9 = std::pair<U1, U2>;
+ using L10 = std::pair<V1, V2>;
+ using L11 = std::pair<W1, W2>;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_std_tuple, L5, L6, L8, L9>, std::pair<std::tuple<X1, Y1, Z1, U1>, std::tuple<X2, Y2, Z2, U2>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_std_tuple, L5, L6, L8, L9, L10>, std::pair<std::tuple<X1, Y1, Z1, U1, V1>, std::tuple<X2, Y2, Z2, U2, V2>>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_transform_q<Q_std_tuple, L5, L6, L8, L9, L10, L11>, std::pair<std::tuple<X1, Y1, Z1, U1, V1, W1>, std::tuple<X2, Y2, Z2, U2, V2, W2>>>));
+
+ //
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_transform_sf.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,42 @@
+
+// Copyright 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/utility.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+
+using boost::mp11::mp_transform;
+using boost::mp11::mp_list;
+using boost::mp11::mp_valid;
+
+template<class...> using F = void;
+
+template<class... L> using transform = mp_transform<F, L...>;
+
+int main()
+{
+ BOOST_TEST_TRAIT_FALSE((mp_valid<transform>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<transform, void>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<transform, void, void>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<transform, void, void, void>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<transform, void, void, void, void>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<transform, void, void, void, void, void>));
+
+#if !BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
+ BOOST_TEST_TRAIT_TRUE((mp_valid<transform, mp_list<>>));
+#endif
+
+ BOOST_TEST_TRAIT_FALSE((mp_valid<transform, mp_list<>, mp_list<void>>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<transform, mp_list<>, mp_list<>, mp_list<void>>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<transform, mp_list<>, mp_list<>, mp_list<>, mp_list<void>>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<transform, mp_list<>, mp_list<>, mp_list<>, mp_list<>, mp_list<void>>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_unique.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,54 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+
+int main()
+{
+ using boost::mp11::mp_list;
+ using boost::mp11::mp_unique;
+
+ {
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique<mp_list<>>, mp_list<>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique<mp_list<void>>, mp_list<void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique<mp_list<void, void>>, mp_list<void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique<mp_list<void, void, void>>, mp_list<void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique<mp_list<void, void, void, void>>, mp_list<void>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique<mp_list<void, int>>, mp_list<void, int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique<mp_list<void, void, void, int, int, int>>, mp_list<void, int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique<mp_list<void, int, void, int, int, void, int, int, int>>, mp_list<void, int>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique<mp_list<void, int, char[]>>, mp_list<void, int, char[]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique<mp_list<void, int, char[], void, int, char[], void, int, char[]>>, mp_list<void, int, char[]>>));
+ }
+
+ {
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique<std::tuple<>>, std::tuple<>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique<std::tuple<void>>, std::tuple<void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique<std::tuple<void, void>>, std::tuple<void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique<std::tuple<void, void, void>>, std::tuple<void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique<std::tuple<void, void, void, void>>, std::tuple<void>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique<std::tuple<void, int>>, std::tuple<void, int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique<std::tuple<void, void, void, int, int, int>>, std::tuple<void, int>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique<std::tuple<void, int, void, int, int, void, int, int, int>>, std::tuple<void, int>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique<std::tuple<void, int, char[]>>, std::tuple<void, int, char[]>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique<std::tuple<void, int, char[], void, int, char[], void, int, char[]>>, std::tuple<void, int, char[]>>));
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_valid.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,72 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/utility.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+
+template<class T> struct Xi
+{
+};
+
+template<> struct Xi<void>
+{
+ using type = void;
+};
+
+template<class T> using X = typename Xi<T>::type;
+
+template<class T> using add_pointer = T*;
+template<class T> using add_reference = T&;
+template<class T> using add_extents = T[];
+
+int main()
+{
+ using boost::mp11::mp_valid;
+ using boost::mp11::mp_identity;
+
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_identity>));
+ BOOST_TEST_TRAIT_TRUE((mp_valid<mp_identity, void>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<mp_identity, void, void>));
+
+ BOOST_TEST_TRAIT_FALSE((mp_valid<X>));
+ BOOST_TEST_TRAIT_TRUE((mp_valid<X, void>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<X, int>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<X, void, void>));
+
+ BOOST_TEST_TRAIT_FALSE((mp_valid<add_pointer>));
+ BOOST_TEST_TRAIT_TRUE((mp_valid<add_pointer, void>));
+ BOOST_TEST_TRAIT_TRUE((mp_valid<add_pointer, int>));
+#if !defined( BOOST_MSVC ) || !BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
+ // msvc-12.0 can form pointer to reference
+ BOOST_TEST_TRAIT_FALSE((mp_valid<add_pointer, int&>));
+#endif
+ BOOST_TEST_TRAIT_FALSE((mp_valid<add_pointer, void, void>));
+
+#if !defined( BOOST_GCC ) || !BOOST_WORKAROUND( BOOST_GCC, < 70000 )
+ // g++ up to at least 6.3 doesn't like add_reference for some reason or other
+ BOOST_TEST_TRAIT_FALSE((mp_valid<add_reference>));
+#if !defined( BOOST_MSVC ) || !BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
+ // msvc-12.0 gives an internal error here
+ BOOST_TEST_TRAIT_FALSE((mp_valid<add_reference, void>));
+#endif
+ BOOST_TEST_TRAIT_TRUE((mp_valid<add_reference, int>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<add_reference, int, int>));
+#endif
+
+ BOOST_TEST_TRAIT_FALSE((mp_valid<add_extents>));
+ BOOST_TEST_TRAIT_TRUE((mp_valid<add_extents, int>));
+#if !defined( BOOST_MSVC ) || !BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
+ // msvc-12.0 can form arrays to void or int&
+ BOOST_TEST_TRAIT_FALSE((mp_valid<add_extents, void>));
+ BOOST_TEST_TRAIT_FALSE((mp_valid<add_extents, int&>));
+#endif
+ BOOST_TEST_TRAIT_FALSE((mp_valid<add_extents, int, int>));
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_with_index.cpp 2017-08-28 02:56:56.000000000 -0700
@@ -0,0 +1,90 @@
+
+// Copyright 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+#include <tuple>
+
+using boost::mp11::mp_size_t;
+using boost::mp11::mp_for_each;
+using boost::mp11::mp_with_index;
+using boost::mp11::mp_iota_c;
+
+struct F
+{
+ int i_;
+
+ explicit F( int i ): i_( i ) {}
+
+ template<std::size_t I> bool operator()( mp_size_t<I> ) const
+ {
+ BOOST_TEST_EQ( I, i_ );
+ return false;
+ }
+};
+
+struct G
+{
+ void operator()( mp_size_t<0> ) const
+ {
+ }
+
+ template<std::size_t N> void operator()( mp_size_t<N> ) const
+ {
+ for( std::size_t i = 0; i < N; ++i )
+ {
+ mp_with_index<N>( i, F(i) );
+ mp_with_index<mp_size_t<N>>( i, F(i) );
+ }
+ }
+};
+
+int main()
+{
+#if BOOST_WORKAROUND( BOOST_MSVC, < 1900 )
+
+ G()( mp_size_t<1>{} );
+ G()( mp_size_t<2>{} );
+ G()( mp_size_t<3>{} );
+ G()( mp_size_t<4>{} );
+ G()( mp_size_t<5>{} );
+ G()( mp_size_t<6>{} );
+ G()( mp_size_t<7>{} );
+ G()( mp_size_t<8>{} );
+ G()( mp_size_t<9>{} );
+ G()( mp_size_t<10>{} );
+ G()( mp_size_t<11>{} );
+ G()( mp_size_t<12>{} );
+ G()( mp_size_t<13>{} );
+ G()( mp_size_t<14>{} );
+ G()( mp_size_t<15>{} );
+ G()( mp_size_t<16>{} );
+
+ G()( mp_size_t<32+1>{} );
+
+ G()( mp_size_t<48+2>{} );
+
+ G()( mp_size_t<64+3>{} );
+
+ G()( mp_size_t<96+4>{} );
+
+ G()( mp_size_t<112+5>{} );
+
+ G()( mp_size_t<128+6>{} );
+
+#else
+
+ mp_for_each<mp_iota_c<134>>( G() );
+
+#endif
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\mp_with_index_cx.cpp 2017-08-28 02:56:56.000000000 -0700
@@ -0,0 +1,41 @@
+
+// Copyright 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/config.hpp>
+
+#if defined( BOOST_NO_CXX14_CONSTEXPR )
+
+int main() {}
+
+#else
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+
+using boost::mp11::mp_size_t;
+using boost::mp11::mp_with_index;
+
+struct F
+{
+ template<std::size_t I> constexpr std::size_t operator()( mp_size_t<I> ) const
+ {
+ return I;
+ }
+};
+
+#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
+
+int main()
+{
+ constexpr std::size_t i = mp_with_index<64>( 57, F{} );
+ STATIC_ASSERT( i == 57 );
+}
+
+#endif
---
+++ libs\mp11\test\mp11.cpp 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,14 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11.hpp>
+
+int main()
+{
+}
---
+++ libs\mp11\test\mpl.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,108 @@
+
+// Copyright 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/mpl.hpp>
+#include <boost/mp11/list.hpp>
+
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/back.hpp>
+#include <boost/mpl/begin.hpp>
+#include <boost/mpl/end.hpp>
+#include <boost/mpl/distance.hpp>
+#include <boost/mpl/clear.hpp>
+#include <boost/mpl/empty.hpp>
+#include <boost/mpl/erase.hpp>
+#include <boost/mpl/front.hpp>
+#include <boost/mpl/insert.hpp>
+#include <boost/mpl/insert_range.hpp>
+#include <boost/mpl/is_sequence.hpp>
+#include <boost/mpl/pop_front.hpp>
+#include <boost/mpl/push_back.hpp>
+#include <boost/mpl/push_front.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/transform.hpp>
+#include <boost/mpl/reverse.hpp>
+#include <boost/mpl/remove.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/back_inserter.hpp>
+
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+#include <tuple>
+
+template<class T> using add_pointer_t = typename std::add_pointer<T>::type;
+
+template<class L1> void test()
+{
+ namespace mpl = boost::mpl;
+ using namespace boost::mp11;
+
+ // intrinsics
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<typename mpl::at<L1, mpl::int_<0>>::type, mp_at_c<L1, 0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<typename mpl::at<L1, mpl::int_<1>>::type, mp_at_c<L1, 1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<typename mpl::at<L1, mpl::int_<2>>::type, mp_at_c<L1, 2>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<typename mpl::at_c<L1, 0>::type, mp_at_c<L1, 0>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<typename mpl::at_c<L1, 1>::type, mp_at_c<L1, 1>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<typename mpl::at_c<L1, 2>::type, mp_at_c<L1, 2>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<typename mpl::back<L1>::type, float>));
+
+ BOOST_TEST_EQ((mpl::distance<typename mpl::begin<L1>::type, typename mpl::end<L1>::type>::type::value), mp_size<L1>::value);
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<typename mpl::clear<L1>::type, mp_clear<L1>>));
+
+ BOOST_TEST_TRAIT_FALSE((typename mpl::empty<L1>::type));
+ BOOST_TEST_TRAIT_TRUE((typename mpl::empty<mp_clear<L1>>::type));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<typename mpl::erase<L1, typename mpl::begin<L1>::type>::type, mp_pop_front<L1>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<typename mpl::front<L1>::type, mp_front<L1>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<typename mpl::insert<L1, typename mpl::begin<L1>::type, void>::type, mp_push_front<L1, void>>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<typename mpl::insert<L1, typename mpl::end<L1>::type, void>::type, mp_push_back<L1, void>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<typename mpl::insert_range<L1, typename mpl::end<L1>::type, L1>::type, mp_append<L1, L1>>));
+
+ BOOST_TEST_TRAIT_TRUE((typename mpl::is_sequence<L1>::type));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<typename mpl::pop_front<L1>::type, mp_pop_front<L1>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<typename mpl::push_back<L1, char>::type, mp_push_back<L1, char>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<typename mpl::push_front<L1, char>::type, mp_push_front<L1, char>>));
+
+ BOOST_TEST_EQ((mpl::size<L1>::type::value), mp_size<L1>::value);
+
+ // algorithms
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<typename mpl::transform<L1, std::add_pointer<mpl::_1>>::type, mp_transform<add_pointer_t, L1>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<typename mpl::reverse<L1>::type, mp_reverse<L1>>));
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<typename mpl::remove<L1, int>::type, mp_remove<L1, int>>));
+
+ using L2 = typename mpl::copy<L1, mpl::back_inserter<mpl::vector<>>>::type;
+ using L3 = typename mpl::copy<L2, mpl::back_inserter<mp_clear<L1>>>::type;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<L1, L3>));
+}
+
+int main()
+{
+ using boost::mp11::mp_list;
+
+ test<mp_list<int, void, float>>();
+ test<std::tuple<int, long, float>>(); // MPL instantiates the tuple, so no 'void'
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\tuple_apply.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,132 @@
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/tuple.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <tuple>
+#include <memory>
+#include <utility>
+#include <array>
+
+int main()
+{
+ using boost::mp11::tuple_apply;
+
+ {
+ std::tuple<int, short, char> tp{ 1, 2, 3 };
+
+ {
+ int s = tuple_apply( [&]( int x, int y, int z ){ return 100 * x + 10 * y + z; }, tp );
+ BOOST_TEST_EQ( s, 123 );
+ }
+
+ {
+ int s = tuple_apply( [&]( int x, int y, int z ){ return 100 * x + 10 * y + z; }, std::move(tp) );
+ BOOST_TEST_EQ( s, 123 );
+ }
+ }
+
+ {
+ std::tuple<int, short, char> const tp{ 1, 2, 3 };
+
+ {
+ int s = tuple_apply( [&]( int x, int y, int z ){ return 100 * x + 10 * y + z; }, tp );
+ BOOST_TEST_EQ( s, 123 );
+ }
+
+ {
+ int s = tuple_apply( [&]( int x, int y, int z ){ return 100 * x + 10 * y + z; }, std::move(tp) );
+ BOOST_TEST_EQ( s, 123 );
+ }
+ }
+
+#if defined( __clang_major__ ) && __clang_major__ == 3 && __clang_minor__ < 8
+#else
+
+ {
+ std::tuple<std::unique_ptr<int>, std::unique_ptr<int>, std::unique_ptr<int>> tp{ std::unique_ptr<int>(new int(1)), std::unique_ptr<int>(new int(2)), std::unique_ptr<int>(new int(3)) };
+
+ int s = tuple_apply( [&]( std::unique_ptr<int> px, std::unique_ptr<int> py, std::unique_ptr<int> pz ){ return 100 * *px + 10 * *py + *pz; }, std::move(tp) );
+ BOOST_TEST_EQ( s, 123 );
+ }
+
+#endif
+
+ {
+ std::pair<int, short> tp{ 1, 2 };
+
+ {
+ int s = tuple_apply( [&]( int x, int y ){ return 10 * x + y; }, tp );
+ BOOST_TEST_EQ( s, 12 );
+ }
+
+ {
+ int s = tuple_apply( [&]( int x, int y ){ return 10 * x + y; }, std::move(tp) );
+ BOOST_TEST_EQ( s, 12 );
+ }
+ }
+
+ {
+ std::pair<int, short> const tp{ 1, 2 };
+
+ {
+ int s = tuple_apply( [&]( int x, int y ){ return 10 * x + y; }, tp );
+ BOOST_TEST_EQ( s, 12 );
+ }
+
+ {
+ int s = tuple_apply( [&]( int x, int y ){ return 10 * x + y; }, std::move(tp) );
+ BOOST_TEST_EQ( s, 12 );
+ }
+ }
+
+ {
+ std::array<int, 3> tp{{ 1, 2, 3 }};
+
+ {
+ int s = tuple_apply( [&]( int x, int y, int z ){ return 100 * x + 10 * y + z; }, tp );
+ BOOST_TEST_EQ( s, 123 );
+ }
+
+ {
+ int s = tuple_apply( [&]( int x, int y, int z ){ return 100 * x + 10 * y + z; }, std::move(tp) );
+ BOOST_TEST_EQ( s, 123 );
+ }
+ }
+
+ {
+ std::array<int, 3> const tp{{ 1, 2, 3 }};
+
+ {
+ int s = tuple_apply( [&]( int x, int y, int z ){ return 100 * x + 10 * y + z; }, tp );
+ BOOST_TEST_EQ( s, 123 );
+ }
+
+ {
+ int s = tuple_apply( [&]( int x, int y, int z ){ return 100 * x + 10 * y + z; }, std::move(tp) );
+ BOOST_TEST_EQ( s, 123 );
+ }
+ }
+
+ {
+ std::tuple<> tp;
+
+ BOOST_TEST_EQ( tuple_apply( []{ return 11; }, tp ), 11 );
+ BOOST_TEST_EQ( tuple_apply( []{ return 12; }, std::move( tp ) ), 12 );
+ }
+
+ {
+ std::array<int, 0> tp;
+
+ BOOST_TEST_EQ( tuple_apply( []{ return 11; }, tp ), 11 );
+ BOOST_TEST_EQ( tuple_apply( []{ return 12; }, std::move( tp ) ), 12 );
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\tuple_apply_cx.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,72 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/mp11/tuple.hpp>
+#include <boost/config.hpp>
+
+// Technically std::tuple isn't constexpr enabled in C++11, but it works with libstdc++
+
+#if defined( BOOST_NO_CXX11_CONSTEXPR ) || ( defined( _LIBCPP_VERSION ) && __cplusplus < 201400L )
+
+int main() {}
+
+#else
+
+#include <tuple>
+#include <array>
+#include <utility>
+
+constexpr int f( int x, int y, int z )
+{
+ return x * 100 + y * 10 + z;
+}
+
+constexpr int g( int x, int y )
+{
+ return x * 10 + y;
+}
+
+constexpr int h()
+{
+ return 11;
+}
+
+int main()
+{
+ {
+ constexpr std::tuple<int, short, char> tp{ 1, 2, 3 };
+ constexpr auto r = boost::mp11::tuple_apply( f, tp );
+ static_assert( r == 123, "r == 123" );
+ }
+
+ {
+ constexpr std::pair<short, char> tp{ 1, 2 };
+ constexpr auto r = boost::mp11::tuple_apply( g, tp );
+ static_assert( r == 12, "r == 12" );
+ }
+
+ {
+ constexpr std::array<short, 3> tp{{ 1, 2, 3 }};
+ constexpr auto r = boost::mp11::tuple_apply( f, tp );
+ static_assert( r == 123, "r == 123" );
+ }
+
+#if defined( __clang_major__ ) && __clang_major__ == 3 && __clang_minor__ < 9
+// "error: default initialization of an object of const type 'const std::tuple<>' without a user-provided default constructor"
+#else
+
+ {
+ constexpr std::tuple<> tp;
+ constexpr auto r = boost::mp11::tuple_apply( h, tp );
+ static_assert( r == 11, "r == 11" );
+ }
+
+#endif
+}
+
+#endif
---
+++ libs\mp11\test\tuple_for_each.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,171 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/mp11/tuple.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <tuple>
+#include <memory>
+#include <utility>
+#include <array>
+
+int main()
+{
+ using boost::mp11::tuple_for_each;
+
+ {
+ std::tuple<int, short, char> tp{ 1, 2, 3 };
+
+ {
+ int s = 0;
+
+ tuple_for_each( tp, [&]( int x ){ s = s * 10 + x; } );
+
+ BOOST_TEST_EQ( s, 123 );
+ }
+
+ {
+ int s = 0;
+
+ tuple_for_each( std::move(tp), [&]( int x ){ s = s * 10 + x; } );
+
+ BOOST_TEST_EQ( s, 123 );
+ }
+ }
+
+ {
+ std::tuple<int, short, char> const tp{ 1, 2, 3 };
+
+ {
+ int s = 0;
+
+ tuple_for_each( tp, [&]( int x ){ s = s * 10 + x; } );
+
+ BOOST_TEST_EQ( s, 123 );
+ }
+
+ {
+ int s = 0;
+
+ tuple_for_each( std::move(tp), [&]( int x ){ s = s * 10 + x; } );
+
+ BOOST_TEST_EQ( s, 123 );
+ }
+ }
+
+#if defined( __clang_major__ ) && __clang_major__ == 3 && __clang_minor__ < 8
+#else
+
+ {
+ std::tuple<std::unique_ptr<int>, std::unique_ptr<int>, std::unique_ptr<int>> tp{ std::unique_ptr<int>(new int(1)), std::unique_ptr<int>(new int(2)), std::unique_ptr<int>(new int(3)) };
+
+ int s = 0;
+
+ tuple_for_each( std::move(tp), [&]( std::unique_ptr<int> p ){ s = s * 10 + *p; } );
+
+ BOOST_TEST_EQ( s, 123 );
+ }
+
+#endif
+
+ {
+ std::pair<int, short> tp{ 1, 2 };
+
+ {
+ int s = 0;
+
+ tuple_for_each( tp, [&]( int x ){ s = s * 10 + x; } );
+
+ BOOST_TEST_EQ( s, 12 );
+ }
+
+ {
+ int s = 0;
+
+ tuple_for_each( std::move(tp), [&]( int x ){ s = s * 10 + x; } );
+
+ BOOST_TEST_EQ( s, 12 );
+ }
+ }
+
+ {
+ std::pair<int, short> const tp{ 1, 2 };
+
+ {
+ int s = 0;
+
+ tuple_for_each( tp, [&]( int x ){ s = s * 10 + x; } );
+
+ BOOST_TEST_EQ( s, 12 );
+ }
+
+ {
+ int s = 0;
+
+ tuple_for_each( std::move(tp), [&]( int x ){ s = s * 10 + x; } );
+
+ BOOST_TEST_EQ( s, 12 );
+ }
+ }
+
+ {
+ std::array<int, 3> tp{{ 1, 2, 3 }};
+
+ {
+ int s = 0;
+
+ tuple_for_each( tp, [&]( int x ){ s = s * 10 + x; } );
+
+ BOOST_TEST_EQ( s, 123 );
+ }
+
+ {
+ int s = 0;
+
+ tuple_for_each( std::move(tp), [&]( int x ){ s = s * 10 + x; } );
+
+ BOOST_TEST_EQ( s, 123 );
+ }
+ }
+
+ {
+ std::array<int, 3> const tp{{ 1, 2, 3 }};
+
+ {
+ int s = 0;
+
+ tuple_for_each( tp, [&]( int x ){ s = s * 10 + x; } );
+
+ BOOST_TEST_EQ( s, 123 );
+ }
+
+ {
+ int s = 0;
+
+ tuple_for_each( std::move(tp), [&]( int x ){ s = s * 10 + x; } );
+
+ BOOST_TEST_EQ( s, 123 );
+ }
+ }
+
+ {
+ std::tuple<> tp;
+
+ BOOST_TEST_EQ( tuple_for_each( tp, 11 ), 11 );
+ BOOST_TEST_EQ( tuple_for_each( std::move( tp ), 12 ), 12 );
+ }
+
+ {
+ std::array<int, 0> tp;
+
+ BOOST_TEST_EQ( tuple_for_each( tp, 11 ), 11 );
+ BOOST_TEST_EQ( tuple_for_each( std::move( tp ), 12 ), 12 );
+ }
+
+ return boost::report_errors();
+}
---
+++ libs\mp11\test\tuple_for_each_cx.cpp 2017-08-06 23:53:47.000000000 -0700
@@ -0,0 +1,53 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/mp11/tuple.hpp>
+#include <boost/config.hpp>
+
+// Technically std::tuple isn't constexpr enabled in C++11, but it works with libstdc++
+
+#if defined( BOOST_NO_CXX11_CONSTEXPR ) || ( defined( _LIBCPP_VERSION ) && __cplusplus < 201400L )
+
+int main() {}
+
+#else
+
+#include <tuple>
+#include <type_traits>
+
+struct assert_is_integral
+{
+ template<class T> constexpr bool operator()( T ) const
+ {
+ static_assert( std::is_integral<T>::value, "T must be an integral type" );
+ return true;
+ }
+};
+
+int main()
+{
+ {
+ constexpr std::tuple<int, short, char> tp{ 1, 2, 3 };
+ constexpr auto r = boost::mp11::tuple_for_each( tp, assert_is_integral() );
+ (void)r;
+ }
+
+#if defined( __clang_major__ ) && __clang_major__ == 3 && __clang_minor__ < 9
+// "error: default initialization of an object of const type 'const std::tuple<>' without a user-provided default constructor"
+#else
+
+ {
+ constexpr std::tuple<> tp;
+ constexpr auto r = boost::mp11::tuple_for_each( tp, 11 );
+ static_assert( r == 11, "r == 11" );
+ }
+
+#endif
+}
+
+#endif
---
+++ libs\mp11\index.html 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,15 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="0; URL=doc/html/mp11.html">
+</head>
+<body>
+Automatic redirection failed, please go to
+<a href="doc/html/mp11.html">doc/html/mp11.html</a>.
+</body>
+</html>
+<!--
+ © Copyright Beman Dawes, 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
+-->
---
+++ libs\mp11\README.md 2017-08-06 23:53:46.000000000 -0700
@@ -0,0 +1,20 @@
+# Mp11, a C++11 metaprogramming library
+
+Mp11 is a C++11 metaprogramming library based on template aliases and variadic templates.
+It implements the approach outlined in the article
+["Simple C++11 metaprogramming"](http://pdimov.com/cpp2/simple_cxx11_metaprogramming.html)
+and [its sequel](http://pdimov.com/cpp2/simple_cxx11_metaprogramming_2.html).
+
+As of 2017-08-02, Mp11 is part of Boost. It hasn't appeared in a release yet, but [a snapshot of the documentation is available](http://www.boost.org/doc/libs/develop/libs/mp11/).
+
+## Supported compilers
+
+* g++ 4.7 or later
+* clang++ 3.5 or later
+* Visual Studio 2013, 2015, 2017
+
+Tested on [Travis](https://travis-ci.org/boostorg/mp11/) and [Appveyor](https://ci.appveyor.com/project/pdimov/mp11/).
+
+## License
+
+Distributed under the [Boost Software License, Version 1.0](http://boost.org/LICENSE_1_0.txt).
--- libs\process\doc\concepts.qbk 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\doc\concepts.qbk 2017-08-26 23:03:08.000000000 -0700
@@ -47,13 +47,13 @@
[endsect]
[section:process Processes]
-A process is an independently executable entity, which is different from a thread, in that it has it's own resources.
+A process is an independently executable entity, which is different from a thread, in that it has its own resources.
Those include memory and hardware resources.
Every process is identified by a unique number[footnote it is unique as long as the process is active], called the process identification digit, `pid`.
[section:exit_code Exit code]
A process will return an integer value indicating whether it was successful. On posix
--- libs\process\doc\extend.qbk 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\doc\extend.qbk 2017-08-26 23:03:08.000000000 -0700
@@ -100,17 +100,18 @@
```
struct async_foo : __handler__, __require_io_service__
{
tempalte<typename Executor>
void on_setup(Executor & exec)
{
- __io_service__ & ios = __get_io_service__(exec.seq); //gives us a reference and a compiler error if not present.
+ io_service & ios = __get_io_service__(exec.seq); //gives us a reference and a compiler error if not present.
//do something with ios
}
};
```
+[caution All async_handlers use one signal(SIGCHLD) on posix, which is only guaranteed to work when all use the same `io_service`]
[note Inheriting [globalref boost::process::extend::require_io_service require_io_service] is necessary, so [funcref boost::process::system system] provides one.]
Additionally the handler can provide a function that is invoked when the child process exits. This is done through __async_handler__.
[note [globalref boost::process::extend::async_handler async_handler] implies [globalref boost::process::extend::require_io_service require_io_service] .]
--- libs\process\doc\faq.qbk 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\doc\faq.qbk 2017-08-26 23:03:08.000000000 -0700
@@ -21,14 +21,14 @@
os << elem;
}
}
```
We switched the read and write operation up, so that's causing a dead-lock.
-This locks immediately. This is because `c++filt` expects input, before
-outputting any data. The launching process on the other hand wait's for it's output.
+This locks immediately. This is because `c++filt` expects input, before
+outputting any data. The launching process on the other hand waits for its output.
[endsect]
[section:closep Why does the pipe not close?]
Now for another example, which might look correct, let's consider you want
--- libs\process\doc\tutorial.qbk 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\doc\tutorial.qbk 2017-08-26 23:03:08.000000000 -0700
@@ -78,13 +78,13 @@
So as a first step, we'll use the `exe-args` style.
```
int result = bp::system("/usr/bin/g++", "main.cpp");
```
-With that sytax we still have "g++" hard-coded, so let's assume we get the string
+With that syntax we still have "g++" hard-coded, so let's assume we get the string
from an external source as `boost::filesystem::path`, we can do this too.
```
boost::filesystem::path p = "/usr/bin/g++"; //or get it from somewhere else.
int result = bp::system(p, "main.cpp");
```
@@ -106,14 +106,14 @@
Given that in our example used the [funcref boost::process::system system] function,
our program will wait until the child process is completed. This maybe unwanted,
especially since compiling can take a while.
In order to avoid that, boost.process provides several ways to launch a process.
-Besides the already mentioned [funcref boost::process::system system] function and it's
-asynchronous version [funcref boost::process::async_system async_system],
+Besides the already mentioned [funcref boost::process::system system] function and its
+asynchronous version [funcref boost::process::async_system async_system],
we can also use the [funcref boost::process::spawn spawn] function or the
[classref boost::process::child child] class.
The [funcref boost::process::spawn spawn] function launches a process and
immediately detaches it, so no handle will be returned and the process will be ignored.
This is not what we need for compiling, but maybe we want to entertain the user,
@@ -197,13 +197,13 @@
[@http://en.cppreference.com/w/cpp/io/basic_iostream std::iostream] interface.
```
std::vector<std::string> read_outline(std::string & file)
{
bp::ipstream is; //reading pipe-stream
- bp::child c(bp::search_patk("nm"), file, bp::std_out > is);
+ bp::child c(bp::search_path("nm"), file, bp::std_out > is);
std::vector<std::string> data;
std::string line;
while (c.child_running() && std::getline(is, line) && !line.empty())
data.push_back(line);
@@ -275,13 +275,13 @@
but the compiler output will just be put into one large buffer.
With [@http://www.boost.org/doc/libs/release/libs/asio/ boost.asio] this is what it looks like.
```
io_service ios;
-std::vector<char> buf;
+std::vector<char> buf(4096);
bp::async_pipe ap(ios);
bp::child c(bp::search_path("g++"), "main.cpp", bp::std_out > ap);
asio_async_read(ap, asio_buffer(buf),
@@ -339,16 +339,16 @@
if they do not modify the group membership. E.g. if you call `make` which
launches other processes and call terminate on it,
it will not terminate all the child processes of the child unless you use a group.
The two main reasons to use groups are:
-# Being able two terminate child processes of the child process
+# Being able to terminate child processes of the child process
# Grouping several processes into one, just so they can be terminated at once
-If we have program like `make`, which does launch it's own child processes,
+If we have program like `make`, which does launch its own child processes,
a call of child_terminate might not suffice. I.e. if we have a makefile launching `gcc`
and use the following code, the `gcc` process will still run afterwards:
```
bp::child c("make");
if (!c.child_wait_for(std::chrono::seconds(10)) //give it 10 seconds
@@ -385,13 +385,13 @@
g.group_wait();
};
```
In the example, it will wait for both processes at the end of the function unless
-an exception occures. I.e. if an exception is thrown, the group will be terminated.
+an exception occurs. I.e. if an exception is thrown, the group will be terminated.
Please see the [headerref boost/process/group.hpp reference] for more information.
[endsect]
[section:env Environment]
@@ -402,13 +402,13 @@
```
//get a handle to the current environment
auto env = boost::this_process::environment();
//add a variable to the current environment
env["VALUE_1"] = "foo";
-//copy it into a environment seperate to the one of this process
+//copy it into a environment separate to the one of this process
bp::environment env_ = env;
//append two values to a variable in the new env
env_["VALUE_2"] += {"bar1", "bar2"};
//launch a process with `env_`
bp::system("stuff", env_);
--- libs\process\test\async.cpp 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\async.cpp 2017-08-26 23:03:09.000000000 -0700
--- libs\process\test\async_fut.cpp 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\async_fut.cpp 2017-08-26 23:03:09.000000000 -0700
@@ -72,6 +72,32 @@
BOOST_REQUIRE_GE(line.size(), val.size());
if (line >= val)
BOOST_CHECK(boost::algorithm::starts_with(line, val));
}
+BOOST_AUTO_TEST_CASE(emtpy_out, *boost::unit_test::timeout(2))
+{
+ using boost::unit_test::framework::master_test_suite;
+
+ boost::asio::io_service io_service;
+
+
+ std::error_code ec;
+ std::future<std::string> fut;
+
+ bp::spawn(
+ master_test_suite().argv[1],
+ "test", "--exit-code", "0",
+ bp::std_out > fut,
+ io_service,
+ ec
+ );
+ BOOST_REQUIRE(!ec);
+
+
+ io_service.run();
+
+ BOOST_REQUIRE(fut.valid());
+ BOOST_CHECK_EQUAL(fut.get(), "");
+}
+
--- libs\process\test\async_system.cpp 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\async_system.cpp 2017-08-26 23:03:09.000000000 -0700
--- libs\process\test\bind_stderr.cpp 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\bind_stderr.cpp 2017-08-26 23:03:09.000000000 -0700
@@ -26,13 +26,13 @@
#include <string>
#include <istream>
#include <iostream>
#include <cstdlib>
#if defined(BOOST_WINDOWS_API)
-# include <Windows.h>
+# include <windows.h>
typedef boost::asio::windows::stream_handle pipe_end;
#elif defined(BOOST_POSIX_API)
# include <sys/wait.h>
# include <unistd.h>
typedef boost::asio::posix::stream_descriptor pipe_end;
#endif
--- libs\process\test\bind_stdin.cpp 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\bind_stdin.cpp 2017-08-26 23:03:09.000000000 -0700
@@ -28,13 +28,13 @@
#include <thread>
#include <boost/config.hpp>
#if defined(BOOST_WINDOWS_API)
-# include <Windows.h>
+# include <windows.h>
typedef boost::asio::windows::stream_handle pipe_end;
#elif defined(BOOST_POSIX_API)
# include <sys/wait.h>
# include <unistd.h>
typedef boost::asio::posix::stream_descriptor pipe_end;
#endif
--- libs\process\test\bind_stdout.cpp 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\bind_stdout.cpp 2017-08-26 23:03:09.000000000 -0700
@@ -26,13 +26,13 @@
#include <boost/filesystem.hpp>
#include <string>
#include <istream>
#include <cstdlib>
#if defined(BOOST_WINDOWS_API)
-# include <Windows.h>
+# include <windows.h>
typedef boost::asio::windows::stream_handle pipe_end;
#elif defined(BOOST_POSIX_API)
# include <sys/wait.h>
# include <unistd.h>
typedef boost::asio::posix::stream_descriptor pipe_end;
#endif
--- libs\process\test\bind_stdout_stderr.cpp 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\bind_stdout_stderr.cpp 2017-08-26 23:03:09.000000000 -0700
@@ -24,13 +24,13 @@
#include <boost/asio.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <string>
#include <istream>
#if defined(BOOST_WINDOWS_API)
-# include <Windows.h>
+# include <windows.h>
typedef boost::asio::windows::stream_handle pipe_end;
#elif defined(BOOST_POSIX_API)
typedef boost::asio::posix::stream_descriptor pipe_end;
#endif
namespace bp = boost::process;
--- libs\process\test\environment.cpp 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\environment.cpp 2017-08-26 23:03:09.000000000 -0700
@@ -214,32 +214,32 @@
BOOST_CHECK_EQUAL(env.at("b").to_string(), "2");
BOOST_CHECK_EQUAL(env.at("c").to_string(), "3");
BOOST_CHECK_EQUAL(env.size(), 3u);
BOOST_CHECK_EQUAL(std::distance(env.begin(), env.end()), 3u);
BOOST_CHECK_EQUAL(std::distance(env.cbegin(), env.cend()), 3u);
- env.erase("a");
+ env.erase("c");
BOOST_CHECK_EQUAL(env.size(), 2u);
- BOOST_CHECK_EQUAL(env.count("a"), 0u);
+ BOOST_CHECK_EQUAL(env.at("a").to_string(), "1");
BOOST_CHECK_EQUAL(env.at("b").to_string(), "2");
- BOOST_CHECK_EQUAL(env.at("c").to_string(), "3");
+ BOOST_CHECK_EQUAL(env.count("c"), 0u);
BOOST_CHECK_EQUAL(std::distance(env.begin(), env.end()), 2u);
BOOST_CHECK_EQUAL(std::distance(env.cbegin(), env.cend()), 2u);
env.erase("b");
BOOST_CHECK_EQUAL(env.size(), 1u);
- BOOST_CHECK_EQUAL(env.count("a"), 0u);
+ BOOST_CHECK_EQUAL(env.at("a").to_string(), "1");
BOOST_CHECK_EQUAL(env.count("b"), 0u);
- BOOST_CHECK_EQUAL(env.at("c").to_string(), "3");
+ BOOST_CHECK_EQUAL(env.count("c"), 0u);
BOOST_CHECK_EQUAL(std::distance(env.begin(), env.end()), 1u);
BOOST_CHECK_EQUAL(std::distance(env.cbegin(), env.cend()), 1u);
env.clear();
BOOST_CHECK(env.empty());
BOOST_CHECK_EQUAL(env.size(), 0u);
BOOST_CHECK_EQUAL(std::distance(env.begin(), env.end()), 0u);
BOOST_CHECK_EQUAL(std::distance(env.cbegin(), env.cend()), 0u);
}
--- libs\process\test\error.cpp 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\error.cpp 2017-08-26 23:03:09.000000000 -0700
--- libs\process\test\exit_code.cpp 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\exit_code.cpp 2017-08-26 23:03:09.000000000 -0700
@@ -15,13 +15,13 @@
#include <boost/process/async.hpp>
#include <boost/process/child.hpp>
#include <boost/system/error_code.hpp>
#include <boost/asio.hpp>
#if defined(BOOST_WINDOWS_API)
-# include <Windows.h>
+# include <windows.h>
typedef boost::asio::windows::stream_handle pipe_end;
#elif defined(BOOST_POSIX_API)
# include <sys/wait.h>
# include <signal.h>
typedef boost::asio::posix::stream_descriptor pipe_end;
#endif
--- libs\process\test\group.cpp 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\group.cpp 2017-08-26 23:03:09.000000000 -0700
@@ -26,13 +26,13 @@
#include <string>
#include <thread>
#include <istream>
#include <iostream>
#include <cstdlib>
#if defined(BOOST_WINDOWS_API)
-# include <Windows.h>
+# include <windows.h>
typedef boost::asio::windows::stream_handle pipe_end;
#elif defined(BOOST_POSIX_API)
# include <sys/wait.h>
# include <unistd.h>
typedef boost::asio::posix::stream_descriptor pipe_end;
#endif
--- libs\process\test\Jamfile.jam 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\Jamfile.jam 2017-08-26 23:03:09.000000000 -0700
@@ -50,13 +50,13 @@
test-suite bare :
[ run environment.cpp system filesystem ]
[ run async_pipe.cpp system filesystem ]
[ run pipe.cpp system filesystem ]
;
-test-suite execution :
+test-suite with-valgrind :
[ run async.cpp system thread filesystem : : sparring_partner ]
[ run async_fut.cpp system thread filesystem : : sparring_partner ]
[ run args_cmd.cpp system filesystem : : sparring_partner ]
[ run wargs_cmd.cpp system filesystem : : sparring_partner ]
[ run bind_stderr.cpp filesystem : : sparring_partner ]
[ run bind_stdin.cpp system filesystem : : sparring_partner ]
@@ -75,25 +75,29 @@
[ run group.cpp system thread filesystem : : sub_launch ]
[ run run_exe.cpp filesystem : : sparring_partner ]
[ run run_exe_path.cpp filesystem : : sparring_partner ]
[ run search_path.cpp filesystem system : : : <target-os>windows:<source>shell32 ]
[ run shell.cpp filesystem system : : sparring_partner ]
[ run shell_path.cpp filesystem system ]
- [ run async_system.cpp filesystem system coroutine : : sparring_partner : <link>static ]
[ run system_test1.cpp filesystem system : : sparring_partner ]
[ run system_test2.cpp filesystem system : : sparring_partner ]
[ run spawn.cpp filesystem system : : sparring_partner ]
[ run start_dir.cpp filesystem system : : sparring_partner ]
[ run terminate.cpp system filesystem : : sparring_partner ]
[ run throw_on_error.cpp system filesystem : : sparring_partner ]
[ run wait.cpp system filesystem : : sparring_partner ]
+ [ run wait_for.cpp system filesystem : : sparring_partner ]
+ [ run on_exit.cpp system filesystem : : sparring_partner ]
+ [ run on_exit2.cpp system filesystem : : sparring_partner ]
+ [ run on_exit3.cpp system filesystem : : sparring_partner ]
[ compile-fail spawn_fail.cpp ]
[ compile-fail async_system_fail.cpp ]
[ run posix_specific.cpp system filesystem : : sparring_partner : <build>no <target-os>linux:<build>yes ]
[ run windows_specific.cpp filesystem system : : sparring_partner : <build>no <target-os>windows:<build>yes ]
: <dependency>bare ;
-run vfork.cpp system filesystem : : sparring_partner : <build>no <target-os>linux:<build>yes ;
-explicit vfork ;
-
-
-
+test-suite without-valgrind :
+ [ run async_system.cpp filesystem system coroutine : : sparring_partner : <link>static ]
+ [ run vfork.cpp system filesystem : : sparring_partner : <build>no <target-os>linux:<build>yes ]
+ ;
+
+
---
+++ libs\process\test\on_exit.cpp 2017-08-26 23:03:09.000000000 -0700
@@ -0,0 +1,52 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MAIN
+#define BOOST_TEST_IGNORE_SIGCHLD
+#include <boost/test/included/unit_test.hpp>
+#include <boost/process.hpp>
+#include <boost/asio.hpp>
+#include <chrono>
+#include <thread>
+
+BOOST_AUTO_TEST_CASE(single_ios, *boost::unit_test::timeout(6))
+{
+ using boost::unit_test::framework::master_test_suite;
+
+ if (master_test_suite().argc > 2 && strcmp(master_test_suite().argv[1], "sleep") == 0)
+ {
+ auto s = atoi(master_test_suite().argv[2]);
+ std::this_thread::sleep_for(std::chrono::seconds(s));
+ return;
+ }
+
+ namespace bp = boost::process;
+ boost::asio::io_service ios;
+ std::chrono::steady_clock::time_point p1, p2;
+
+ // launch a child that will sleep for 2s
+ auto c1 = bp::child(master_test_suite().argv[0], "sleep", "2", ios,
+ bp::on_exit([&p1](int, const std::error_code&)
+ { p1 = std::chrono::steady_clock::now(); }));
+
+ // wait a bit, make sure the child launch for my test
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+
+ // launch a child that will sleep for 4s
+ auto c2 = bp::child(master_test_suite().argv[0], "sleep", "4", ios,
+ bp::on_exit([&p2](int, const std::error_code&)
+ { p2 = std::chrono::steady_clock::now(); }));
+
+ // wait for the notifications
+ while (!ios.stopped())
+ ios.run_one();
+
+ BOOST_REQUIRE((p2 - p1) > std::chrono::seconds(1));
+}
+
---
+++ libs\process\test\on_exit2.cpp 2017-08-26 23:03:09.000000000 -0700
@@ -0,0 +1,50 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MAIN
+#define BOOST_TEST_IGNORE_SIGCHLD
+#include <boost/test/included/unit_test.hpp>
+#include <boost/process.hpp>
+#include <boost/asio.hpp>
+#include <chrono>
+#include <thread>
+
+BOOST_AUTO_TEST_CASE(double_ios, *boost::unit_test::timeout(6))
+{
+ using boost::unit_test::framework::master_test_suite;
+
+ if (master_test_suite().argc > 2 && strcmp(master_test_suite().argv[1], "sleep") == 0)
+ {
+ auto s = atoi(master_test_suite().argv[2]);
+ std::this_thread::sleep_for(std::chrono::seconds(s));
+ return;
+ }
+
+ namespace bp = boost::process;
+ boost::asio::io_service ios;
+ std::chrono::steady_clock::time_point p1, p2;
+
+ // launch a child that will sleep for 2s
+ auto c1 = bp::child(master_test_suite().argv[0], "sleep", "2", ios,
+ bp::on_exit([&p1](int, const std::error_code&)
+ { p1 = std::chrono::steady_clock::now(); }));
+
+ // wait a bit, make sure the child launch for my test
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+
+ // launch a child that will sleep for 4s
+ auto c2 = bp::child(master_test_suite().argv[0], "sleep", "4", ios,
+ bp::on_exit([&p2](int, const std::error_code&)
+ { p2 = std::chrono::steady_clock::now(); }));
+
+
+ ios.run();
+ BOOST_REQUIRE((p2 - p1) > std::chrono::seconds(1));
+}
+
---
+++ libs\process\test\on_exit3.cpp 2017-08-26 23:03:09.000000000 -0700
@@ -0,0 +1,51 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MAIN
+#define BOOST_TEST_IGNORE_SIGCHLD
+#include <boost/test/included/unit_test.hpp>
+#include <boost/process.hpp>
+#include <boost/asio.hpp>
+#include <chrono>
+#include <thread>
+
+BOOST_AUTO_TEST_CASE(double_ios_threaded, *boost::unit_test::timeout(6))
+{
+ using boost::unit_test::framework::master_test_suite;
+
+ if (master_test_suite().argc > 2 && strcmp(master_test_suite().argv[1], "sleep") == 0)
+ {
+ auto s = atoi(master_test_suite().argv[2]);
+ std::this_thread::sleep_for(std::chrono::seconds(s));
+ return;
+ }
+
+ namespace bp = boost::process;
+ boost::asio::io_service ios;
+ std::chrono::steady_clock::time_point p1, p2;
+
+ // launch a child that will sleep for 2s
+ auto c1 = bp::child(master_test_suite().argv[0], "sleep", "2", ios,
+ bp::on_exit([&p1](int, const std::error_code&)
+ { p1 = std::chrono::steady_clock::now(); }));
+
+ // wait a bit, make sure the child launch for my test
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+
+ // launch a child that will sleep for 4s
+ auto c2 = bp::child(master_test_suite().argv[0], "sleep", "4", ios,
+ bp::on_exit([&p2](int, const std::error_code&)
+ { p2 = std::chrono::steady_clock::now(); }));
+
+ // wait for the notifications
+ std::thread ([&ios] { ios.run(); }).join();
+
+ BOOST_REQUIRE((p2 - p1) > std::chrono::seconds(1));
+}
+
--- libs\process\test\pipe.cpp 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\pipe.cpp 2017-08-26 23:03:09.000000000 -0700
--- libs\process\test\sparring_partner.cpp 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\sparring_partner.cpp 2017-08-26 23:03:09.000000000 -0700
@@ -25,13 +25,13 @@
#if defined(BOOST_POSIX_API)
# include <boost/lexical_cast.hpp>
# include <boost/iostreams/device/file_descriptor.hpp>
# include <boost/iostreams/stream.hpp>
# include <unistd.h>
#elif defined(BOOST_WINDOWS_API)
-# include <Windows.h>
+# include <windows.h>
#endif
using namespace boost::program_options;
int main(int argc, char *argv[])
--- libs\process\test\spawn.cpp 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\spawn.cpp 2017-08-26 23:03:09.000000000 -0700
@@ -27,13 +27,13 @@
#include <boost/filesystem.hpp>
#include <string>
#include <istream>
#include <cstdlib>
#if defined(BOOST_WINDOWS_API)
-# include <Windows.h>
+# include <windows.h>
typedef boost::asio::windows::stream_handle pipe_end;
#elif defined(BOOST_POSIX_API)
# include <sys/wait.h>
# include <unistd.h>
typedef boost::asio::posix::stream_descriptor pipe_end;
#endif
--- libs\process\test\spawn_fail.cpp 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\spawn_fail.cpp 2017-08-26 23:03:09.000000000 -0700
@@ -23,13 +23,13 @@
#include <boost/filesystem.hpp>
#include <string>
#include <istream>
#include <cstdlib>
#if defined(BOOST_WINDOWS_API)
-# include <Windows.h>
+# include <windows.h>
typedef boost::asio::windows::stream_handle pipe_end;
#elif defined(BOOST_POSIX_API)
# include <sys/wait.h>
# include <unistd.h>
typedef boost::asio::posix::stream_descriptor pipe_end;
#endif
--- libs\process\test\sub_launcher.cpp 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\sub_launcher.cpp 2017-08-26 23:03:09.000000000 -0700
--- libs\process\test\system_test1.cpp 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\system_test1.cpp 2017-08-26 23:03:09.000000000 -0700
@@ -32,13 +32,13 @@
#include <string>
#include <chrono>
#include <istream>
#include <cstdlib>
#if defined(BOOST_WINDOWS_API)
-# include <Windows.h>
+# include <windows.h>
typedef boost::asio::windows::stream_handle pipe_end;
#elif defined(BOOST_POSIX_API)
# include <sys/wait.h>
# include <unistd.h>
typedef boost::asio::posix::stream_descriptor pipe_end;
#endif
--- libs\process\test\system_test2.cpp 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\system_test2.cpp 2017-08-26 23:03:09.000000000 -0700
--- libs\process\test\wait.cpp 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\wait.cpp 2017-08-26 23:03:09.000000000 -0700
@@ -61,35 +61,6 @@
BOOST_REQUIRE(!ec);
io_service.run();
BOOST_CHECK(called);
}
-
-BOOST_AUTO_TEST_CASE(double_wait, *boost::unit_test::timeout(5))
-{
- using boost::unit_test::framework::master_test_suite;
- using namespace boost::asio;
-
- boost::asio::io_service io_service;
-
- std::error_code ec;
- std::atomic<bool> called{false};
-
- bp::child c(
- master_test_suite().argv[1],
- bp::args+={"test", "--wait", "1"},
- ec,
- io_service,
- bp::on_exit([&](int, const std::error_code&){called.store(true);})
-
- );
- BOOST_REQUIRE(!ec);
-
- std::thread th([&]{io_service.run();});
-
- c.wait();
-
- th.join();
- BOOST_CHECK(called.load());
-
-}
---
+++ libs\process\test\wait_for.cpp 2017-08-26 23:03:09.000000000 -0700
@@ -0,0 +1,104 @@
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_TEST_MAIN
+#define BOOST_TEST_IGNORE_SIGCHLD
+#include <boost/test/included/unit_test.hpp>
+#include <boost/process/error.hpp>
+#include <boost/process/child.hpp>
+#include <boost/process/args.hpp>
+#include <thread>
+#include <atomic>
+#include <system_error>
+#include <boost/asio.hpp>
+#if defined(BOOST_POSIX_API)
+# include <signal.h>
+#endif
+
+namespace bp = boost::process;
+
+BOOST_AUTO_TEST_CASE(wait_for)
+{
+ using boost::unit_test::framework::master_test_suite;
+
+ std::error_code ec;
+ bp::child c(
+ master_test_suite().argv[1],
+ bp::args+={"test", "--wait", "1"},
+ ec
+ );
+ BOOST_REQUIRE(!ec);
+
+ BOOST_CHECK(!c.wait_for(std::chrono::milliseconds(200)));
+ BOOST_CHECK( c.wait_for(std::chrono::milliseconds(1000)));
+}
+
+BOOST_AUTO_TEST_CASE(wait_for_ec)
+{
+ using boost::unit_test::framework::master_test_suite;
+
+ std::error_code ec;
+ bp::child c(
+ master_test_suite().argv[1],
+ bp::args+={"test", "--wait", "1"},
+ ec
+ );
+ BOOST_REQUIRE(!ec);
+
+ BOOST_CHECK(!c.wait_for(std::chrono::milliseconds(400),ec));
+ BOOST_CHECK( c.wait_for(std::chrono::milliseconds(1000),ec));
+
+ BOOST_CHECK_MESSAGE(!ec, ec.message());
+}
+
+
+BOOST_AUTO_TEST_CASE(wait_until)
+{
+ using boost::unit_test::framework::master_test_suite;
+ std::error_code ec;
+
+ bp::child c(
+ master_test_suite().argv[1],
+ bp::args+={"test", "--wait", "1"},
+ ec
+ );
+ BOOST_REQUIRE(!ec);
+
+ auto now = std::chrono::system_clock::now();
+
+ auto t1 = now + std::chrono::milliseconds(400);
+ auto t2 = now + std::chrono::milliseconds(1200);
+
+ BOOST_CHECK(!c.wait_until(t1));
+ BOOST_CHECK( c.wait_until(t2));
+
+}
+
+BOOST_AUTO_TEST_CASE(wait_until_ec)
+{
+ using boost::unit_test::framework::master_test_suite;
+ std::error_code ec;
+
+ bp::child c(
+ master_test_suite().argv[1],
+ bp::args+={"test", "--wait", "1"},
+ ec
+ );
+ BOOST_REQUIRE(!ec);
+
+ auto now = std::chrono::system_clock::now();
+
+ auto t1 = now + std::chrono::milliseconds(400);
+ auto t2 = now + std::chrono::milliseconds(1200);
+
+ BOOST_CHECK(!c.wait_until(t1, ec));
+ BOOST_CHECK( c.wait_until(t2, ec));
+
+ BOOST_CHECK_MESSAGE(!ec, ec.message());
+}
--- libs\process\test\wargs_cmd.cpp 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\test\wargs_cmd.cpp 2017-08-26 23:03:09.000000000 -0700
@@ -37,13 +37,12 @@
bp::std_out>is,
ec
);
if (ec)
std::cout << "EC: " << ec.message() << std::endl;
BOOST_REQUIRE(!ec);
- return ;
std::string s;
std::getline(is, s);
s.resize(4);
BOOST_CHECK_EQUAL(s, "test");
@@ -84,13 +83,13 @@
bp::child c(cmd,
bp::std_out>is,
ec
);
BOOST_REQUIRE(!ec);
- return ;
+
std::string s;
std::getline(is, s);
s.resize(4);
BOOST_CHECK_EQUAL(s, "test");
--- libs\process\README.md 2017-08-19 09:49:45.000000000 -0700
+++ libs\process\README.md 2017-08-26 23:03:08.000000000 -0700
@@ -1,16 +1,16 @@
-#[Boost Process (Boost.Process)](https://github.com/klemens-morgenstern/boost-process)
+# [Boost Process (Boost.Process)](https://github.com/klemens-morgenstern/boost-process)
-Boost.process is not yet part of the [Boost C++ Libraries](http://github.com/boostorg), but will probably be released in boost 1.64. It is a library for comfortable management of processes.
+Boost.process is a library for comfortable management of processes, released with boost 1.64.0.
### Test results
Branches | Build | Tests coverage |
----------------|-------------- | -------------- |
Develop: | [![Build Status](https://travis-ci.org/klemens-morgenstern/boost-process.svg?branch=develop)](https://travis-ci.org/klemens-morgenstern/boost-process) [![Build status](https://ci.appveyor.com/api/projects/status/peup7e6m0e1bb5ba?svg=true)](https://ci.appveyor.com/project/klemens-morgenstern/boost-process) | [![Coverage Status](https://coveralls.io/repos/github/klemens-morgenstern/boost-process/badge.svg?branch=develop)](https://coveralls.io/github/klemens-morgenstern/boost-process?branch=develop) |
-Master: | [![Build Status](https://travis-ci.org/klemens-morgenstern/boost-process.svg?branch=master)] (https://travis-ci.org/klemens-morgenstern/boost-process) [![Build status](https://ci.appveyor.com/api/projects/status/peup7e6m0e1bb5ba/branch/master?svg=true)](https://ci.appveyor.com/project/klemens-morgenstern/boost-process/branch/master) | [![Coverage Status](https://coveralls.io/repos/github/klemens-morgenstern/boost-process/badge.svg?branch=master)](https://coveralls.io/github/klemens-morgenstern/boost-process?branch=master) |
+Master: | [![Build Status](https://travis-ci.org/klemens-morgenstern/boost-process.svg?branch=master)](https://travis-ci.org/klemens-morgenstern/boost-process) [![Build status](https://ci.appveyor.com/api/projects/status/peup7e6m0e1bb5ba/branch/master?svg=true)](https://ci.appveyor.com/project/klemens-morgenstern/boost-process/branch/master) | [![Coverage Status](https://coveralls.io/repos/github/klemens-morgenstern/boost-process/badge.svg?branch=master)](https://coveralls.io/github/klemens-morgenstern/boost-process?branch=master) |
[Open Issues](https://github.com/klemens-morgenstern/boost-process/issues)
[Latest developer documentation](http://klemens-morgenstern.github.io/process/)
### About
@@ -18,7 +18,7 @@
### License
Distributed under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt).
### Dependency
-This library requires boost 1.63. Since this is not released yet you can clone the winapi module from [here](https://github.com/boostorg/winapi) to get it to work on windows.
+This library requires boost 1.64 with which it is released.
--- libs\smart_ptr\test\atomic_sp_constexpr_test.cpp 2017-08-19 09:49:49.000000000 -0700
+++ libs\smart_ptr\test\atomic_sp_constexpr_test.cpp 2017-08-28 18:55:51.000000000 -0700
@@ -14,13 +14,13 @@
#define HAVE_CONSTEXPR_INIT
#if defined( BOOST_NO_CXX11_CONSTEXPR )
# undef HAVE_CONSTEXPR_INIT
#endif
-#if BOOST_WORKAROUND( BOOST_MSVC, <= 1910 )
+#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
# undef HAVE_CONSTEXPR_INIT
#endif
#if defined(__clang__) && defined( BOOST_NO_CXX14_CONSTEXPR )
# undef HAVE_CONSTEXPR_INIT
#endif
--- libs\smart_ptr\test\sp_constexpr_test.cpp 2017-08-19 09:49:49.000000000 -0700
+++ libs\smart_ptr\test\sp_constexpr_test.cpp 2017-08-28 18:55:52.000000000 -0700
@@ -14,13 +14,13 @@
#define HAVE_CONSTEXPR_INIT
#if defined( BOOST_NO_CXX11_CONSTEXPR )
# undef HAVE_CONSTEXPR_INIT
#endif
-#if BOOST_WORKAROUND( BOOST_MSVC, <= 1910 )
+#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
# undef HAVE_CONSTEXPR_INIT
#endif
#if defined(__clang__) && defined( BOOST_NO_CXX14_CONSTEXPR )
# undef HAVE_CONSTEXPR_INIT
#endif
--- libs\smart_ptr\test\sp_constexpr_test2.cpp 2017-08-19 09:49:49.000000000 -0700
+++ libs\smart_ptr\test\sp_constexpr_test2.cpp 2017-08-28 18:55:52.000000000 -0700
@@ -14,13 +14,13 @@
#define HAVE_CONSTEXPR_INIT
#if defined( BOOST_NO_CXX11_CONSTEXPR )
# undef HAVE_CONSTEXPR_INIT
#endif
-#if BOOST_WORKAROUND( BOOST_MSVC, <= 1910 )
+#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
# undef HAVE_CONSTEXPR_INIT
#endif
#if defined(__clang__) && defined( BOOST_NO_CXX14_CONSTEXPR )
# undef HAVE_CONSTEXPR_INIT
#endif
--- libs\spirit\test\x3\with.cpp 2017-08-19 09:49:49.000000000 -0700
+++ libs\spirit\test\x3\with.cpp 2017-08-24 15:10:21.000000000 -0700
@@ -53,8 +53,62 @@
BOOST_TEST(test("(123,456)", start));
BOOST_TEST(!test("(abc,def)", start));
BOOST_TEST(val == 2);
}
+ { // injecting non-const lvalue into the context
+ int val = 0;
+ auto const r = int_[([](auto& ctx){
+ x3::get<my_tag>(ctx) += x3::_attr(ctx);
+ })];
+ BOOST_TEST(test("123,456", with<my_tag>(val)[r % ',']));
+ BOOST_TEST(579 == val);
+ }
+
+ { // injecting rvalue into the context
+ auto const r1 = int_[([](auto& ctx){
+ x3::get<my_tag>(ctx) += x3::_attr(ctx);
+ })];
+ auto const r2 = rule<struct my_rvalue_rule_class, int>() =
+ x3::lit('(') >> (r1 % ',') >> x3::lit(')')[([](auto& ctx){
+ x3::_val(ctx) = x3::get<my_tag>(ctx);
+ })];
+ int attr = 0;
+ BOOST_TEST(test_attr("(1,2,3)", with<my_tag>(100)[r2], attr));
+ BOOST_TEST(106 == attr);
+ }
+
+ { // injecting const/non-const lvalue and rvalue into the context
+ struct functor {
+ int operator()(int& val) {
+ return val * 10; // non-const ref returns 10 * injected val
+ }
+ int operator()(int const& val) {
+ return val; // const ref returns injected val
+ }
+ };
+
+ auto f = [](auto& ctx){
+ x3::_val(ctx) = x3::_attr(ctx) + functor()(x3::get<my_tag>(ctx));
+ };
+ auto const r = rule<struct my_rule_class2, int>() = int_[f];
+
+ int attr = 0;
+ int const cval = 10;
+ BOOST_TEST(test_attr("5", with<my_tag>(cval)[r], attr));
+ BOOST_TEST(15 == attr); // x3::get returns const ref to cval
+
+ attr = 0;
+ int val = 10;
+ BOOST_TEST(test_attr("5", with<my_tag>(val)[r], attr));
+ BOOST_TEST(105 == attr); // x3::get returns ref to val
+
+ attr = 0;
+
+ BOOST_TEST(test_attr("5", with<my_tag>(10)[r], attr));
+ // x3::get returns ref to member variable of with_directive
+ BOOST_TEST(105 == attr);
+ }
+
return boost::report_errors();
}
--- libs\stacktrace\build\has_windbg_cached.cpp 2017-08-19 09:49:49.000000000 -0700
+++ libs\stacktrace\build\has_windbg_cached.cpp 2017-08-24 16:44:48.000000000 -0700
@@ -1,21 +1,28 @@
// Copyright Antony Polukhin, 2016-2017.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
+#include <boost/config.hpp>
+
+#include <string>
#include <cstring>
#include <windows.h>
#include "dbgeng.h"
+#ifdef BOOST_NO_CXX11_THREAD_LOCAL
+# error Your compiler does not support C++11 thread_local storage. It's impossible to build with BOOST_STACKTRACE_USE_WINDBG_CACHED.
+#endif
+
int foo() {
- static thread_local int i = 0;
+ static thread_local std::string i = std::string();
- return i;
+ return i.size();
}
int main() {
::CoInitializeEx(0, COINIT_MULTITHREADED);
return foo();
}
--- libs\thread\doc\changes.qbk 2017-08-19 09:49:49.000000000 -0700
+++ libs\thread\doc\changes.qbk 2017-08-26 22:32:23.000000000 -0700
@@ -1,15 +1,58 @@
[/
(C) Copyright 2007-11 Anthony Williams.
- (C) Copyright 2011-16 Vicente J. Botet Escriba.
+ (C) Copyright 2011-17 Vicente J. Botet Escriba.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
]
[section:changes History]
+
+[heading Version 4.8.0 - boost 1.66]
+
+[*Know Bugs:]
+
+* [@http://svn.boost.org/trac/boost/ticket/3926 #3926] thread_specific_ptr + dlopen library causes a SIGSEGV.
+
+* [@http://svn.boost.org/trac/boost/ticket/10964 #10964] future<future<T>>::unwrap().then() Deadlocks
+
+
+Please take a look at [@https://svn.boost.org/trac/boost/query?status=assigned&status=new&status=reopened&component=thread&type=!Feature+Requests&col=id&col=summary&order=id thread Know Bugs] to see the current state.
+
+Please take a look at [@http://www.boost.org/development/tests/master/developer/thread.html thread master regression test] to see the last regression test snapshot.
+
+[*Fixed Bugs:]
+
+* [@http://svn.boost.org/trac/boost/ticket/12949 #12949] using sleep_for in a thread context without including boost/thread/thread.hpp yields incorrect behaviour when BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC is defined
+* [@http://svn.boost.org/trac/boost/ticket/13019 #13019] ABI compatibility for BOOST_THREAD_PROVIDES_INTERRUPTIONS incomplete
+* [@http://svn.boost.org/trac/boost/ticket/13163 #13163] boost::detail::heap_new does not have a variadic variant
+
+* [@https://github.com/boostorg/thread/issues/130 #130] windows: Bug in boost::condition_variable on Windows
+
+[heading Version 4.7.4 - boost 1.65]
+
+[*Fixed Bugs:]
+
+* [@http://svn.boost.org/trac/boost/ticket/6787 #6787] boost::thread::sleep() hangs if system time is rolled back
+* [@http://svn.boost.org/trac/boost/ticket/12519 #12519] boost::thread::try_join_for does not return after timeout
+* [@http://svn.boost.org/trac/boost/ticket/12874 #12874] future<> extension constructor must be under BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
+* [@http://svn.boost.org/trac/boost/ticket/12888 #12888] Linking with boost thread does not work on mingw/gcc 4.4
+* [@http://svn.boost.org/trac/boost/ticket/12958 #12958] sync_bounded_queue::wait_pull_front( lve ) might throw
+* [@http://svn.boost.org/trac/boost/ticket/13077 #13077] Linking to static 64bit libboost_thread fails DLL initialization
+* [@http://svn.boost.org/trac/boost/ticket/13155 #13155] log doesn't build on a system with pthreads
+
+* [@https://github.com/boostorg/thread/issues/121 #121] on_tls_prepare is broken under VS2017
+
+[heading Version 4.7.3 - boost 1.64]
+
+[*Fixed Bugs:]
+
+* [@https://github.com/boostorg/thread/issues/113 #113] Add a Thread template on all the scoped thread and thread guard classes
+* [@https://github.com/boostorg/thread/issues/117 #117] loop_executor should block on it's work_queue instead of polling
+* [@https://github.com/boostorg/thread/issues/119 #119] basic_condition_variable::relocker::~relocker can throw an exception
[heading Version 4.7.2 - boost 1.63]
[*Fixed Bugs:]
* fix boost::synchronized_value<>::load()
@@ -24,13 +67,13 @@
* [@http://svn.boost.org/trac/boost/ticket/3926 #3926] thread_specific_ptr + dlopen library causes a SIGSEGV.
Please define BOOST_THREAD_PATCH to apply the patch that could unfortunately results is a regression as described in [@http://svn.boost.org/trac/boost/ticket/12049 #12049].
Please take a look at [@https://svn.boost.org/trac/boost/query?status=assigned&status=new&status=reopened&component=thread&type=!Feature+Requests&col=id&col=summary&order=id thread Know Bugs] to see the current state.
-Please take a look at [@http://www.boost.org/development/tests/master/developer/thread.html thread trunk regression test] to see the last regression test snapshot.
+Please take a look at [@http://www.boost.org/development/tests/master/developer/thread.html thread master regression test] to see the last regression test snapshot.
[*Fixed Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/11097 #11097] test_scheduled_tp - ThreadSanitizer: heap-use-after-free
* [@http://svn.boost.org/trac/boost/ticket/11951 #11951] Memory leak in boost::when_all
--- libs\thread\doc\thread.qbk 2017-08-19 09:49:49.000000000 -0700
+++ libs\thread\doc\thread.qbk 2017-08-26 22:32:23.000000000 -0700
@@ -5,16 +5,16 @@
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
]
[library Thread
[quickbook 1.5]
- [version 4.7.2]
+ [version 4.8.0]
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
[copyright 2007-11 Anthony Williams]
- [copyright 2011-16 Vicente J. Botet Escriba]
+ [copyright 2011-17 Vicente J. Botet Escriba]
[purpose C++ Library for launching threads and synchronizing data between them]
[category text]
[license
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
[@http://www.boost.org/LICENSE_1_0.txt])
--- libs\thread\src\pthread\thread.cpp 2017-08-19 09:49:49.000000000 -0700
+++ libs\thread\src\pthread\thread.cpp 2017-08-26 22:32:24.000000000 -0700
@@ -49,13 +49,13 @@
i->second->unlock();
i->first->notify_all();
}
for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end();
i != e; ++i)
{
- (*i)->make_ready();
+ (*i)->notify_deferred();
}
}
struct thread_exit_callback_node
{
boost::detail::thread_exit_function_base* func;
@@ -454,13 +454,13 @@
condition_variable cond;
cond.do_wait_for(lock, ts);
# endif
}
}
- void BOOST_THREAD_DECL sleep_until(const timespec& ts)
+ void BOOST_THREAD_DECL sleep_until_realtime(const timespec& ts)
{
timespec now = boost::detail::timespec_now_realtime();
if (boost::detail::timespec_gt(ts, now))
{
for (int foo=0; foo < 5; ++foo)
{
@@ -484,13 +484,12 @@
{
return;
}
}
}
}
-
}
}
namespace hidden
{
void BOOST_THREAD_DECL sleep_for(const timespec& ts)
{
@@ -504,24 +503,24 @@
else
{
boost::this_thread::no_interruption_point::hidden::sleep_for(ts);
}
}
- void BOOST_THREAD_DECL sleep_until(const timespec& ts)
+ void BOOST_THREAD_DECL sleep_until_realtime(const timespec& ts)
{
boost::detail::thread_data_base* const thread_info=boost::detail::get_current_thread_data();
if(thread_info)
{
unique_lock<mutex> lk(thread_info->sleep_mutex);
while(thread_info->sleep_condition.do_wait_until(lk,ts)) {}
}
else
{
- boost::this_thread::no_interruption_point::hidden::sleep_until(ts);
+ boost::this_thread::no_interruption_point::hidden::sleep_until_realtime(ts);
}
}
} // hidden
} // this_thread
namespace this_thread
--- libs\thread\src\win32\thread.cpp 2017-08-19 09:49:49.000000000 -0700
+++ libs\thread\src\win32\thread.cpp 2017-08-26 22:32:25.000000000 -0700
@@ -54,13 +54,13 @@
i->second->unlock();
i->first->notify_all();
}
for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end();
i != e; ++i)
{
- (*i)->make_ready();
+ (*i)->notify_deferred();
}
}
}
namespace
{
--- libs\thread\src\win32\tss_pe.cpp 2017-08-19 09:49:49.000000000 -0700
+++ libs\thread\src\win32\tss_pe.cpp 2017-08-28 20:49:57.000000000 -0700
@@ -108,16 +108,34 @@
#endif
//Definitions required by implementation
-
- typedef int (__cdecl *_PVFV)();
- #define INIRETSUCCESS 0
- #define PVAPI int __cdecl
+ #if (_MSC_VER < 1300) || ((_MSC_VER > 1900) && (_MSC_VER < 1910)) // 1300 == VC++ 7.0, 1900 == VC++ 14.0, 1910 == VC++ 2017
+ typedef void ( __cdecl *_PVFV_ )();
+ typedef void ( __cdecl *_PIFV_ )();
+ #define INIRETSUCCESS_V
+ #define INIRETSUCCESS_I
+ #define PVAPI_V void __cdecl
+ #define PVAPI_I void __cdecl
+ #elif (_MSC_VER >= 1910)
+ typedef void ( __cdecl *_PVFV_ )();
+ typedef int ( __cdecl *_PIFV_ )();
+ #define INIRETSUCCESS_V
+ #define INIRETSUCCESS_I 0
+ #define PVAPI_V void __cdecl
+ #define PVAPI_I int __cdecl
+ #else
+ typedef int ( __cdecl *_PVFV_ )();
+ typedef int ( __cdecl *_PIFV_ )();
+ #define INIRETSUCCESS_V 0
+ #define INIRETSUCCESS_I 0
+ #define PVAPI_V int __cdecl
+ #define PVAPI_I int __cdecl
+ #endif
typedef void (NTAPI* _TLSCB)(HINSTANCE, DWORD, PVOID);
//Symbols for connection to the runtime environment
extern "C"
@@ -127,70 +145,70 @@
}
namespace
{
//Forward declarations
- static PVAPI on_tls_prepare();
- static PVAPI on_process_init();
- static PVAPI on_process_term();
+ static PVAPI_I on_tls_prepare();
+ static PVAPI_V on_process_init();
+ static PVAPI_V on_process_term();
static void NTAPI on_tls_callback(HINSTANCE, DWORD, PVOID);
//The .CRT$Xxx information is taken from Codeguru:
//http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/
#if (_MSC_VER >= 1400)
#pragma section(".CRT$XIU",long,read)
#pragma section(".CRT$XCU",long,read)
#pragma section(".CRT$XTU",long,read)
#pragma section(".CRT$XLC",long,read)
__declspec(allocate(".CRT$XLC")) _TLSCB __xl_ca=on_tls_callback;
- __declspec(allocate(".CRT$XIU"))_PVFV p_tls_prepare = on_tls_prepare;
- __declspec(allocate(".CRT$XCU"))_PVFV p_process_init = on_process_init;
- __declspec(allocate(".CRT$XTU"))_PVFV p_process_term = on_process_term;
+ __declspec(allocate(".CRT$XIU"))_PIFV_ p_tls_prepare = on_tls_prepare;
+ __declspec(allocate(".CRT$XCU"))_PVFV_ p_process_init = on_process_init;
+ __declspec(allocate(".CRT$XTU"))_PVFV_ p_process_term = on_process_term;
#else
#if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
# pragma data_seg(push, old_seg)
#endif
//Callback to run tls glue code first.
//I don't think it is necessary to run it
//at .CRT$XIB level, since we are only
//interested in thread detachement. But
//this could be changed easily if required.
#pragma data_seg(".CRT$XIU")
- static _PVFV p_tls_prepare = on_tls_prepare;
+ static _PIFV_ p_tls_prepare = on_tls_prepare;
#pragma data_seg()
//Callback after all global ctors.
#pragma data_seg(".CRT$XCU")
- static _PVFV p_process_init = on_process_init;
+ static _PVFV_ p_process_init = on_process_init;
#pragma data_seg()
//Callback for tls notifications.
#pragma data_seg(".CRT$XLB")
_TLSCB p_thread_callback = on_tls_callback;
#pragma data_seg()
//Callback for termination.
#pragma data_seg(".CRT$XTU")
- static _PVFV p_process_term = on_process_term;
+ static _PVFV_ p_process_term = on_process_term;
#pragma data_seg()
#if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
# pragma data_seg(pop, old_seg)
#endif
#endif
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4189)
#endif
- PVAPI on_tls_prepare()
+ PVAPI_I on_tls_prepare()
{
//The following line has an important side effect:
//if the TLS directory is not already there, it will
//be created by the linker. In other words, it forces a tls
//directory to be generated by the linker even when static tls
//(i.e. __declspec(thread)) is not used.
@@ -219,19 +237,19 @@
++pfbegin;
}
*pfdst = 0;
#endif
- return INIRETSUCCESS;
+ return INIRETSUCCESS_I;
}
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
- PVAPI on_process_init()
+ PVAPI_V on_process_init()
{
//Schedule on_thread_exit() to be called for the main
//thread before destructors of global objects have been
//called.
//It will not be run when 'quick' exiting the
@@ -242,19 +260,19 @@
atexit(boost::on_thread_exit);
//Call Boost process entry callback here
boost::on_process_enter();
- return INIRETSUCCESS;
+ return INIRETSUCCESS_V;
}
- PVAPI on_process_term()
+ PVAPI_V on_process_term()
{
boost::on_process_exit();
- return INIRETSUCCESS;
+ return INIRETSUCCESS_V;
}
void NTAPI on_tls_callback(HINSTANCE /*h*/, DWORD dwReason, PVOID /*pv*/)
{
switch (dwReason)
{
--- libs\thread\test\test_9856.cpp 2017-08-19 09:49:49.000000000 -0700
+++ libs\thread\test\test_9856.cpp 2017-08-28 20:50:00.000000000 -0700
@@ -3,13 +3,13 @@
#include <iostream>
using namespace boost;
int main() {
atomic<size_t> total(0), failures(0);
-
+
#pragma omp parallel shared(total, failures) num_threads(1000)
{
mutex mtx;
condition_variable cond;
unique_lock<mutex> lk(mtx);
for (int i = 0; i < 500; i++) {
@@ -17,13 +17,13 @@
if (cv_status::timeout != cond.wait_for(lk, chrono::milliseconds(10)))
++failures;
}
}
if(failures)
std::cout << "There were " << failures << " failures out of " << total << " timed waits." << std::endl;
- if((100*failures)/total>10)
+ if((100*failures)/total>40)
{
std::cerr << "This exceeds 10%, so failing the test." << std::endl;
return 1;
}
return 0;
}
--- tools\build\src\engine\boehm_gc\misc.c 2017-08-19 09:49:50.000000000 -0700
+++ tools\build\src\engine\boehm_gc\misc.c 2017-08-21 15:16:58.000000000 -0700
@@ -862,13 +862,13 @@
ABORT("Open of log file failed");
}
tmp = WriteFile(GC_stdout, buf, (DWORD)len, &written, NULL);
if (!tmp)
DebugBreak();
# if defined(_MSC_VER) && defined(_DEBUG)
- _CrtDbgReport(_CRT_WARN, NULL, 0, NULL, "%.*s", len, buf);
+ _CrtDbgReport(_CRT_WARN, NULL, 0, NULL, "%.*s", (int)len, buf);
# endif
if (GC_need_to_lock) LeaveCriticalSection(&GC_write_cs);
return tmp ? (int)written : -1;
}
# undef GC_need_to_lock
--- tools\build\src\engine\filent.c 2017-08-19 09:49:50.000000000 -0700
+++ tools\build\src\engine\filent.c 2017-08-21 15:17:37.000000000 -0700
@@ -482,13 +482,13 @@
if ( c = strrchr( name, '/' ) )
name = c + 1;
if ( c = strrchr( name, '\\' ) )
name = c + 1;
}
- sprintf( buf, "%.*s", endname - name, name );
+ sprintf( buf, "%.*s", (int)( endname - name ), name );
if ( strcmp( buf, "") != 0 )
{
file_info_t * member = 0;
/* NT static libraries appear to store the objects in a sequence
--- tools\build\src\tools\builtin.jam 2017-08-19 09:49:50.000000000 -0700
+++ tools\build\src\tools\builtin.jam 2017-08-24 16:09:26.000000000 -0700
@@ -277,15 +277,16 @@
# The specific instruction set in an architecture to compile.
feature.feature instruction-set :
# x86 and x86-64
native i486 i586 i686 pentium pentium-mmx pentiumpro pentium2 pentium3
pentium3m pentium-m pentium4 pentium4m prescott nocona core2 corei7 corei7-avx core-avx-i
conroe conroe-xe conroe-l allendale merom merom-xe kentsfield kentsfield-xe penryn wolfdale
- yorksfield nehalem sandy-bridge ivy-bridge haswell k6 k6-2 k6-3 athlon athlon-tbird athlon-4 athlon-xp
- athlon-mp k8 opteron athlon64 athlon-fx k8-sse3 opteron-sse3 athlon64-sse3 amdfam10 barcelona
- bdver1 bdver2 bdver3 btver1 btver2 winchip-c6 winchip2 c3 c3-2 atom
+ yorksfield nehalem sandy-bridge ivy-bridge haswell broadwell skylake skylake-avx512 cannonlake
+ k6 k6-2 k6-3 athlon athlon-tbird athlon-4 athlon-xp athlon-mp k8 opteron athlon64 athlon-fx
+ k8-sse3 opteron-sse3 athlon64-sse3 amdfam10 barcelona bdver1 bdver2 bdver3 bdver4 btver1
+ btver2 znver1 winchip-c6 winchip2 c3 c3-2 atom
# ia64
itanium itanium1 merced itanium2 mckinley
# Sparc
v7 cypress v8 supersparc sparclite hypersparc sparclite86x f930 f934
--- tools\build\src\tools\gcc.jam 2017-08-19 09:49:50.000000000 -0700
+++ tools\build\src\tools\gcc.jam 2017-08-24 16:03:27.000000000 -0700
@@ -1102,12 +1102,16 @@
cpu-flags gcc OPTIONS : x86 : nehalem : -march=corei7 ;
cpu-flags gcc OPTIONS : x86 : corei7-avx : -march=corei7-avx ;
cpu-flags gcc OPTIONS : x86 : sandy-bridge : -march=corei7-avx ;
cpu-flags gcc OPTIONS : x86 : core-avx-i : -march=core-avx-i ;
cpu-flags gcc OPTIONS : x86 : ivy-bridge : -march=core-avx-i ;
cpu-flags gcc OPTIONS : x86 : haswell : -march=core-avx-i -mavx2 -mfma -mbmi -mbmi2 -mlzcnt ;
+cpu-flags gcc OPTIONS : x86 : broadwell : -march=broadwell ;
+cpu-flags gcc OPTIONS : x86 : skylake : -march=skylake ;
+cpu-flags gcc OPTIONS : x86 : skylake-avx512 : -march=skylake-avx512 ;
+cpu-flags gcc OPTIONS : x86 : cannonlake : -march=skylake-avx512 -mavx512vbmi -mavx512ifma -msha ;
cpu-flags gcc OPTIONS : x86 : k6 : -march=k6 ;
cpu-flags gcc OPTIONS : x86 : k6-2 : -march=k6-2 ;
cpu-flags gcc OPTIONS : x86 : k6-3 : -march=k6-3 ;
cpu-flags gcc OPTIONS : x86 : athlon : -march=athlon ;
cpu-flags gcc OPTIONS : x86 : athlon-tbird : -march=athlon-tbird ;
cpu-flags gcc OPTIONS : x86 : athlon-4 : -march=athlon-4 ;
@@ -1123,14 +1127,16 @@
cpu-flags gcc OPTIONS : x86 : athlon64-sse3 : -march=athlon64-sse3 ;
cpu-flags gcc OPTIONS : x86 : amdfam10 : -march=amdfam10 ;
cpu-flags gcc OPTIONS : x86 : barcelona : -march=barcelona ;
cpu-flags gcc OPTIONS : x86 : bdver1 : -march=bdver1 ;
cpu-flags gcc OPTIONS : x86 : bdver2 : -march=bdver2 ;
cpu-flags gcc OPTIONS : x86 : bdver3 : -march=bdver3 ;
+cpu-flags gcc OPTIONS : x86 : bdver4 : -march=bdver4 ;
cpu-flags gcc OPTIONS : x86 : btver1 : -march=btver1 ;
cpu-flags gcc OPTIONS : x86 : btver2 : -march=btver2 ;
+cpu-flags gcc OPTIONS : x86 : znver1 : -march=znver1 ;
cpu-flags gcc OPTIONS : x86 : winchip-c6 : -march=winchip-c6 ;
cpu-flags gcc OPTIONS : x86 : winchip2 : -march=winchip2 ;
cpu-flags gcc OPTIONS : x86 : c3 : -march=c3 ;
cpu-flags gcc OPTIONS : x86 : c3-2 : -march=c3-2 ;
##
cpu-flags gcc OPTIONS : x86 : atom : -march=atom ;
--- tools\build\src\tools\intel-darwin.jam 2017-08-19 09:49:50.000000000 -0700
+++ tools\build\src\tools\intel-darwin.jam 2017-08-24 16:04:12.000000000 -0700
@@ -129,15 +129,17 @@
flags intel-darwin.compile OPTIONS <optimization>space : -O1 ; # no specific space optimization flag in icc
#
.cpu-type-em64t = prescott nocona core2 corei7 corei7-avx core-avx-i
conroe conroe-xe conroe-l allendale merom
merom-xe kentsfield kentsfield-xe penryn wolfdale
- yorksfield nehalem sandy-bridge ivy-bridge haswell ;
+ yorksfield nehalem sandy-bridge ivy-bridge haswell
+ broadwell skylake skylake-avx512 cannonlake ;
.cpu-type-amd64 = k8 opteron athlon64 athlon-fx k8-sse3 opteron-sse3
- athlon64-sse3 amdfam10 barcelona bdver1 bdver2 bdver3 btver1 btver2 ;
+ athlon64-sse3 amdfam10 barcelona bdver1 bdver2 bdver3
+ bdver4 btver1 btver2 znver1 ;
.cpu-type-x86-64 = $(.cpu-type-em64t) $(.cpu-type-amd64) ;
flags intel-darwin.compile OPTIONS <instruction-set>$(.cpu-type-x86-64)/<address-model>32 : -m32 ; # -mcmodel=small ;
flags intel-darwin.compile OPTIONS <instruction-set>$(.cpu-type-x86-64)/<address-model>64 : -m64 ; # -mcmodel=large ;
flags intel-darwin.compile.c OPTIONS <warnings>off : -w0 ;
--- tools\build\src\tools\msvc.jam 2017-08-19 09:49:50.000000000 -0700
+++ tools\build\src\tools\msvc.jam 2017-08-24 14:05:58.000000000 -0700
@@ -1647,16 +1647,17 @@
.cpu-type-g5 = i586 pentium pentium-mmx ;
.cpu-type-g6 = i686 pentiumpro pentium2 pentium3 pentium3m pentium-m k6
k6-2 k6-3 winchip-c6 winchip2 c3 c3-2 ;
.cpu-type-em64t = prescott nocona core2 corei7 corei7-avx core-avx-i
conroe conroe-xe conroe-l allendale merom
merom-xe kentsfield kentsfield-xe penryn wolfdale
- yorksfield nehalem sandy-bridge ivy-bridge haswell ;
+ yorksfield nehalem sandy-bridge ivy-bridge haswell
+ broadwell skylake skylake-avx512 cannonlake ;
.cpu-type-amd64 = k8 opteron athlon64 athlon-fx k8-sse3 opteron-sse3
athlon64-sse3 amdfam10 barcelona bdver1 bdver2 bdver3
- btver1 btver2 ;
+ bdver4 btver1 btver2 znver1 ;
.cpu-type-g7 = pentium4 pentium4m athlon athlon-tbird athlon-4 athlon-xp
athlon-mp $(.cpu-type-em64t) $(.cpu-type-amd64) ;
.cpu-type-itanium = itanium itanium1 merced ;
.cpu-type-itanium2 = itanium2 mckinley ;
.cpu-type-arm = armv2 armv2a armv3 armv3m armv4 armv4t armv5 armv5t armv5te armv6 armv6j iwmmxt ep9312
armv7 armv7s ;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment