diff --git a/.clang-tidy b/.clang-tidy index a375f76141..d3ecf33b9d 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -21,6 +21,7 @@ Checks: | modernize-avoid-bind, modernize-loop-convert, modernize-make-shared, + modernize-make-unique, modernize-redundant-void-arg, modernize-replace-auto-ptr, modernize-replace-disallow-copy-and-assign-macro, @@ -35,6 +36,7 @@ Checks: | modernize-use-noexcept, modernize-use-nullptr, modernize-use-override, + modernize-use-transparent-functors, modernize-use-using, readability-avoid-const-params-in-decls, readability-braces-around-statements, diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eb2fcf2b67..d0342c41c3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -99,7 +99,7 @@ jobs: cmake-args: -DCMAKE_CXX_STANDARD=14 - runs-on: macos-15-intel python-version: '3.13' - cmake-args: -DCMAKE_CXX_STANDARD=11 + cmake-args: -DCMAKE_CXX_STANDARD=14 - runs-on: macos-latest python-version: '3.12' cmake-args: -DCMAKE_CXX_STANDARD=17 -DPYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION=ON @@ -152,7 +152,7 @@ jobs: python-version: ${{ matrix.python-version }} cmake-args: ${{ matrix.cmake-args }} - # This checks inplace builds with C++11 + # This checks inplace builds with C++14 inplace: if: github.event.pull_request.draft == false strategy: @@ -254,12 +254,15 @@ jobs: run: uv tool install ninja - name: Configure via preset - run: cmake --preset venv -DPYBIND11_CREATE_WITH_UV="${{ matrix.python-version }}" + run: > + cmake --preset venv + -DPYBIND11_CREATE_WITH_UV="${{ matrix.python-version }}" + -DCMAKE_CXX_STANDARD=14 - - name: Build C++11 + - name: Build C++14 run: cmake --build --preset venv - - name: Python tests C++11 + - name: Python tests C++14 run: cmake --build --preset testsvenv -t pytest # Testing on clang using the excellent silkeh clang docker images @@ -536,43 +539,43 @@ jobs: set +e; source /opt/intel/oneapi/setvars.sh; set -e python3 -m pip install -r tests/requirements.txt - - name: Configure C++11 + - name: Configure C++14 run: | set +e; source /opt/intel/oneapi/setvars.sh; set -e - cmake -S . -B build-11 \ + cmake -S . -B build-14 \ -DPYBIND11_WERROR=ON \ -DDOWNLOAD_CATCH=ON \ -DDOWNLOAD_EIGEN=OFF \ - -DCMAKE_CXX_STANDARD=11 \ + -DCMAKE_CXX_STANDARD=14 \ -DCMAKE_CXX_COMPILER=$(which icpc) \ -DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)") - - name: Build C++11 + - name: Build C++14 run: | set +e; source /opt/intel/oneapi/setvars.sh; set -e - cmake --build build-11 -j 2 -v + cmake --build build-14 -j 2 -v - - name: Python tests C++11 + - name: Python tests C++14 run: | set +e; source /opt/intel/oneapi/setvars.sh; set -e sudo service apport stop - cmake --build build-11 --target check + cmake --build build-14 --target check - - name: C++ tests C++11 + - name: C++ tests C++14 timeout-minutes: 3 run: | set +e; source /opt/intel/oneapi/setvars.sh; set -e - cmake --build build-11 --target cpptest + cmake --build build-14 --target cpptest - - name: Interface test C++11 + - name: Interface test C++14 run: | set +e; source /opt/intel/oneapi/setvars.sh; set -e - cmake --build build-11 --target test_cmake_build + cmake --build build-14 --target test_cmake_build - name: Visibility test run: | set +e; source /opt/intel/oneapi/setvars.sh; set -e - cmake --build build-11 --target test_cross_module_rtti + cmake --build build-14 --target test_cross_module_rtti - name: Configure C++17 run: | @@ -659,7 +662,7 @@ jobs: -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON -DDOWNLOAD_EIGEN=ON - -DCMAKE_CXX_STANDARD=11 + -DCMAKE_CXX_STANDARD=14 -DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)") - name: Build @@ -810,7 +813,7 @@ jobs: -DDOWNLOAD_CATCH=ON -DDOWNLOAD_EIGEN=ON ${{ matrix.args }} - - name: Build C++11 + - name: Build C++14 run: cmake --build build -j 2 - name: Python tests @@ -859,7 +862,7 @@ jobs: -DDOWNLOAD_CATCH=ON -DDOWNLOAD_EIGEN=ON ${{ matrix.args }} - - name: Build C++11 + - name: Build C++14 run: cmake --build build --config Debug -j 2 - name: Python tests @@ -969,25 +972,25 @@ jobs: - uses: actions/checkout@v7 - - name: Configure C++11 + - name: Configure C++14 # LTO leads to many undefined reference like # `pybind11::detail::function_call::function_call(pybind11::detail::function_call&&) run: >- - cmake -G "MinGW Makefiles" -DCMAKE_CXX_STANDARD=11 -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON + cmake -G "MinGW Makefiles" -DCMAKE_CXX_STANDARD=14 -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON -DPYTHON_EXECUTABLE=$(python -c "import sys; print(sys.executable)") -S . -B build - - name: Build C++11 + - name: Build C++14 run: cmake --build build -j 2 - - name: Python tests C++11 + - name: Python tests C++14 run: cmake --build build --target pytest -j 2 - - name: C++11 tests + - name: C++14 tests timeout-minutes: 3 run: PYTHONHOME=/${{matrix.sys}} PYTHONPATH=/${{matrix.sys}} cmake --build build --target cpptest -j 2 - - name: Interface test C++11 + - name: Interface test C++14 run: PYTHONHOME=/${{matrix.sys}} PYTHONPATH=/${{matrix.sys}} cmake --build build --target test_cmake_build - name: Visibility test @@ -996,31 +999,6 @@ jobs: - name: Clean directory run: git clean -fdx - - name: Configure C++14 - run: >- - cmake -G "MinGW Makefiles" -DCMAKE_CXX_STANDARD=14 -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON - -DPYTHON_EXECUTABLE=$(python -c "import sys; print(sys.executable)") - -S . -B build2 - - - name: Build C++14 - run: cmake --build build2 -j 2 - - - name: Python tests C++14 - run: cmake --build build2 --target pytest -j 2 - - - name: C++14 tests - timeout-minutes: 3 - run: PYTHONHOME=/${{matrix.sys}} PYTHONPATH=/${{matrix.sys}} cmake --build build2 --target cpptest -j 2 - - - name: Interface test C++14 - run: PYTHONHOME=/${{matrix.sys}} PYTHONPATH=/${{matrix.sys}} cmake --build build2 --target test_cmake_build - - - name: Visibility test - run: PYTHONHOME=/${{matrix.sys}} PYTHONPATH=/${{matrix.sys}} cmake --build build2 --target test_cross_module_rtti - - - name: Clean directory - run: git clean -fdx - - name: Configure C++17 run: >- cmake -G "MinGW Makefiles" -DCMAKE_CXX_STANDARD=17 -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON diff --git a/.github/workflows/upstream.yml b/.github/workflows/upstream.yml index 7ad8c99014..2ac1fd9a63 100644 --- a/.github/workflows/upstream.yml +++ b/.github/workflows/upstream.yml @@ -49,28 +49,28 @@ jobs: cmake --version pip list - # First build - C++11 mode and inplace - - name: Configure C++11 + # First build - C++14 mode and inplace + - name: Configure C++14 run: > - cmake -S . -B build11 + cmake -S . -B build14 -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON -DDOWNLOAD_EIGEN=ON - -DCMAKE_CXX_STANDARD=11 + -DCMAKE_CXX_STANDARD=14 -DCMAKE_BUILD_TYPE=Debug - - name: Build C++11 - run: cmake --build build11 -j 2 + - name: Build C++14 + run: cmake --build build14 -j 2 - - name: Python tests C++11 - run: cmake --build build11 --target pytest -j 2 + - name: Python tests C++14 + run: cmake --build build14 --target pytest -j 2 - - name: C++11 tests + - name: C++14 tests timeout-minutes: 3 - run: cmake --build build11 --target cpptest -j 2 + run: cmake --build build14 --target cpptest -j 2 - - name: Interface test C++11 - run: cmake --build build11 --target test_cmake_build + - name: Interface test C++14 + run: cmake --build build14 --target test_cmake_build # Second build - C++17 mode and in a build directory - name: Configure C++17 diff --git a/CMakeLists.txt b/CMakeLists.txt index 65f794a49d..2ef6af928f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -294,8 +294,7 @@ if(NOT TARGET pybind11_headers) pybind11_headers ${pybind11_system} INTERFACE $ $) - target_compile_features(pybind11_headers INTERFACE cxx_inheriting_constructors cxx_user_literals - cxx_right_angle_brackets) + target_compile_features(pybind11_headers INTERFACE cxx_std_14) if(NOT "${PYBIND11_INTERNALS_VERSION}" STREQUAL "") target_compile_definitions( pybind11_headers INTERFACE "PYBIND11_INTERNALS_VERSION=${PYBIND11_INTERNALS_VERSION}") diff --git a/docs/advanced/deprecated.rst b/docs/advanced/deprecated.rst index c9f4a2e666..fde0423f47 100644 --- a/docs/advanced/deprecated.rst +++ b/docs/advanced/deprecated.rst @@ -3,8 +3,8 @@ Deprecated ########## -Support for C++11 is deprecated and will be removed in a future version. Please -use at least C++14. +Support for C++11 was removed in pybind11 3.1. Please use at least C++14; +C++17 or newer is recommended. Support for FindPythonLibs (not available in CMake 3.26+ mode) is deprecated and will be removed in a future version. The default mode is also going to diff --git a/docs/basics.rst b/docs/basics.rst index 7f77f201fe..8bf0d12f04 100644 --- a/docs/basics.rst +++ b/docs/basics.rst @@ -143,7 +143,7 @@ On Linux, the above example can be compiled using the following command: .. code-block:: bash - $ c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3 -m pybind11 --extension-suffix) + $ c++ -O3 -Wall -shared -std=c++14 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3 -m pybind11 --extension-suffix) .. note:: diff --git a/docs/classes.rst b/docs/classes.rst index 97ad72f3f6..a24e182f77 100644 --- a/docs/classes.rst +++ b/docs/classes.rst @@ -414,8 +414,7 @@ The overload signatures are also visible in the method's docstring: | | Set the pet's name -If you have a C++14 compatible compiler [#cpp14]_, you can use an alternative -syntax to cast the overloaded function: +You can also use an alternative syntax to cast the overloaded function: .. code-block:: cpp @@ -439,20 +438,6 @@ on constness, the ``py::const_`` tag should be used: .def("foo_mutable", py::overload_cast(&Widget::foo)) .def("foo_const", py::overload_cast(&Widget::foo, py::const_)); -If you prefer the ``py::overload_cast`` syntax but have a C++11 compatible compiler only, -you can use ``py::detail::overload_cast_impl`` with an additional set of parentheses: - -.. code-block:: cpp - - template - using overload_cast_ = pybind11::detail::overload_cast_impl; - - py::class_(m, "Pet") - .def("set", overload_cast_()(&Pet::set), "Set the pet's age") - .def("set", overload_cast_()(&Pet::set), "Set the pet's name"); - -.. [#cpp14] A compiler which supports the ``-std=c++14`` flag. - .. note:: To define multiple overloaded constructors, simply declare one after the diff --git a/docs/compiling.rst b/docs/compiling.rst index a6bee86ffe..8c8ec2af72 100644 --- a/docs/compiling.rst +++ b/docs/compiling.rst @@ -78,7 +78,7 @@ that. Your ``meson.build`` file would look something like this: 'cpp', version: '0.1.0', default_options: [ - 'cpp_std=c++11', + 'cpp_std=c++14', ], ) @@ -649,7 +649,7 @@ On Linux, you can compile an example such as the one given in .. code-block:: bash - $ c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix) + $ c++ -O3 -Wall -shared -std=c++14 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix) The ``python3 -m pybind11 --includes`` command fetches the include paths for both pybind11 and Python headers. This assumes that pybind11 has been installed @@ -663,7 +663,7 @@ building the module: .. code-block:: bash - $ c++ -O3 -Wall -shared -std=c++11 -undefined dynamic_lookup $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix) + $ c++ -O3 -Wall -shared -std=c++14 -undefined dynamic_lookup $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix) For quick tests, the command line tool can also produce the full set of flags for you, based on ``python-config``: diff --git a/include/pybind11/attr.h b/include/pybind11/attr.h index d337595a0b..5daef10d73 100644 --- a/include/pybind11/attr.h +++ b/include/pybind11/attr.h @@ -677,28 +677,24 @@ struct process_attributes { PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(r); PYBIND11_WORKAROUND_INCORRECT_GCC_UNUSED_BUT_SET_PARAMETER(r); using expander = int[]; - (void) expander{ - 0, ((void) process_attribute::type>::init(args, r), 0)...}; + (void) expander{0, ((void) process_attribute>::init(args, r), 0)...}; } static void init(const Args &...args, type_record *r) { PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(r); PYBIND11_WORKAROUND_INCORRECT_GCC_UNUSED_BUT_SET_PARAMETER(r); using expander = int[]; - (void) expander{0, - (process_attribute::type>::init(args, r), 0)...}; + (void) expander{0, (process_attribute>::init(args, r), 0)...}; } static void precall(function_call &call) { PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(call); using expander = int[]; - (void) expander{0, - (process_attribute::type>::precall(call), 0)...}; + (void) expander{0, (process_attribute>::precall(call), 0)...}; } static void postcall(function_call &call, handle fn_ret) { PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(call, fn_ret); PYBIND11_WORKAROUND_INCORRECT_GCC_UNUSED_BUT_SET_PARAMETER(fn_ret); using expander = int[]; - (void) expander{ - 0, (process_attribute::type>::postcall(call, fn_ret), 0)...}; + (void) expander{0, (process_attribute>::postcall(call, fn_ret), 0)...}; } }; diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 1d857a0ed5..a6bf8389be 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -49,17 +49,18 @@ typename make_caster::template cast_op_type cast_op(make_caster &caster return caster.operator result_t(); } template -typename make_caster::template cast_op_type::type> +typename make_caster::template cast_op_type> cast_op(make_caster &&caster) { - using result_t = typename make_caster::template cast_op_type< - typename std::add_rvalue_reference::type>; // See PR #4893 + using result_t = + typename make_caster::template cast_op_type>; // See PR + // #4893 return std::move(caster).operator result_t(); } template class type_caster_enum_type { private: - using Underlying = typename std::underlying_type::type; + using Underlying = std::underlying_type_t; public: static constexpr auto name = const_name(); @@ -167,11 +168,10 @@ class type_caster> { using reference_t = type &; using subcaster_cast_op_type = typename caster_t::template cast_op_type; - static_assert( - std::is_same::type &, subcaster_cast_op_type>::value - || std::is_same::value, - "std::reference_wrapper caster requires T to have a caster with an " - "`operator T &()` or `operator const T &()`"); + static_assert(std::is_same &, subcaster_cast_op_type>::value + || std::is_same::value, + "std::reference_wrapper caster requires T to have a caster with an " + "`operator T &()` or `operator const T &()`"); public: bool load(handle src, bool convert) { return subcaster.load(src, convert); } @@ -230,9 +230,8 @@ using is_std_char_type = any_of, /* std::string */ template struct type_caster::value && !is_std_char_type::value>> { using _py_type_0 = conditional_t; - using _py_type_1 = conditional_t::value, - _py_type_0, - typename std::make_unsigned<_py_type_0>::type>; + using _py_type_1 + = conditional_t::value, _py_type_0, std::make_unsigned_t<_py_type_0>>; using py_type = conditional_t::value, double, _py_type_1>; public: @@ -310,39 +309,39 @@ struct type_caster::value && !is_std_char_t } template - static typename std::enable_if::value, handle>::type + static std::enable_if_t::value, handle> cast(U src, return_value_policy /* policy */, handle /* parent */) { return PyFloat_FromDouble((double) src); } template - static typename std::enable_if::value && std::is_signed::value - && (sizeof(U) <= sizeof(long)), - handle>::type + static std::enable_if_t::value && std::is_signed::value + && (sizeof(U) <= sizeof(long)), + handle> cast(U src, return_value_policy /* policy */, handle /* parent */) { return PYBIND11_LONG_FROM_SIGNED((long) src); } template - static typename std::enable_if::value && std::is_unsigned::value - && (sizeof(U) <= sizeof(unsigned long)), - handle>::type + static std::enable_if_t::value && std::is_unsigned::value + && (sizeof(U) <= sizeof(unsigned long)), + handle> cast(U src, return_value_policy /* policy */, handle /* parent */) { return PYBIND11_LONG_FROM_UNSIGNED((unsigned long) src); } template - static typename std::enable_if::value && std::is_signed::value - && (sizeof(U) > sizeof(long)), - handle>::type + static std::enable_if_t::value && std::is_signed::value + && (sizeof(U) > sizeof(long)), + handle> cast(U src, return_value_policy /* policy */, handle /* parent */) { return PyLong_FromLongLong((long long) src); } template - static typename std::enable_if::value && std::is_unsigned::value - && (sizeof(U) > sizeof(unsigned long)), - handle>::type + static std::enable_if_t::value && std::is_unsigned::value + && (sizeof(U) > sizeof(unsigned long)), + handle> cast(U src, return_value_policy /* policy */, handle /* parent */) { return PyLong_FromUnsignedLongLong((unsigned long long) src); } @@ -1269,13 +1268,12 @@ struct move_only_holder_caster< } template - using cast_op_type - = conditional_t::type, - const std::unique_ptr &>::value - || std::is_same::type, - const std::unique_ptr &>::value, - const std::unique_ptr &, - std::unique_ptr>; + using cast_op_type = conditional_t< + std::is_same, const std::unique_ptr &>::value + || std::is_same, + const std::unique_ptr &>::value, + const std::unique_ptr &, + std::unique_ptr>; explicit operator std::unique_ptr() { if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) { @@ -1738,7 +1736,7 @@ template ::value, int> = object cast(T &&value, return_value_policy policy = return_value_policy::automatic_reference, handle parent = handle()) { - using no_ref_T = typename std::remove_reference::type; + using no_ref_T = std::remove_reference_t; if (policy == return_value_policy::automatic) { policy = std::is_pointer::value ? return_value_policy::take_ownership : std::is_lvalue_reference::value ? return_value_policy::copy diff --git a/include/pybind11/detail/argument_vector.h b/include/pybind11/detail/argument_vector.h index 6e2c2ec481..41da4872d7 100644 --- a/include/pybind11/detail/argument_vector.h +++ b/include/pybind11/detail/argument_vector.h @@ -31,7 +31,7 @@ PYBIND11_WARNING_DISABLE_MSVC(4127) PYBIND11_NAMESPACE_BEGIN(detail) // Shared implementation utility for our small_vector-like containers. -// We support C++11 and C++14, so we cannot use +// We support C++14, so we cannot use // std::variant. Union with the tag packed next to the inline // array's size is smaller anyway, allowing 1 extra handle of // inline storage for free. Compare the layouts (1 line per diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 740001db78..e52871284d 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -72,6 +72,10 @@ # endif #endif +#if !defined(PYBIND11_CPP14) +# error "pybind11 requires C++14 or newer" +#endif + // These PYBIND11_HAS_... macros are consolidated in pybind11/detail/common.h // to simplify backward compatibility handling for users (e.g., via #ifdef checks): #define PYBIND11_HAS_TYPE_CASTER_STD_FUNCTION_SPECIALIZATIONS 1 @@ -109,10 +113,8 @@ // Compiler version assertions #if defined(__INTEL_COMPILER) -# if __INTEL_COMPILER < 1800 -# error pybind11 requires Intel C++ compiler v18 or newer -# elif __INTEL_COMPILER < 1900 && defined(PYBIND11_CPP14) -# error pybind11 supports only C++11 with Intel C++ compiler v18. Use v19 or newer for C++14. +# if __INTEL_COMPILER < 1900 +# error pybind11 requires Intel C++ compiler v19 or newer # endif /* The following pragma cannot be pop'ed: https://community.intel.com/t5/Intel-C-Compiler/Inline-and-no-inline-warning/td-p/1216764 */ @@ -179,10 +181,8 @@ // For unknown reasons all PYBIND11_DEPRECATED member trigger a warning when declared // whether it is used or not # define PYBIND11_DEPRECATED(reason) -#elif defined(PYBIND11_CPP14) -# define PYBIND11_DEPRECATED(reason) [[deprecated(reason)]] #else -# define PYBIND11_DEPRECATED(reason) __attribute__((deprecated(reason))) +# define PYBIND11_DEPRECATED(reason) [[deprecated(reason)]] #endif #if defined(PYBIND11_CPP17) @@ -203,9 +203,8 @@ # if defined(PYBIND11_CPP17) && __has_include() # define PYBIND11_HAS_OPTIONAL 1 # endif -// std::experimental::optional (but not allowed in c++11 mode) -# if defined(PYBIND11_CPP14) && (__has_include() && \ - !__has_include()) +// std::experimental::optional +# if __has_include() && !__has_include() # define PYBIND11_HAS_EXP_OPTIONAL 1 # endif // std::variant @@ -706,22 +705,11 @@ static_assert(std::is_standard_layout::value, template struct always_false : std::false_type {}; -/// from __cpp_future__ import (convenient aliases from C++14/17) -#if defined(PYBIND11_CPP14) +/// Convenient aliases from C++14 using std::conditional_t; using std::enable_if_t; using std::remove_cv_t; using std::remove_reference_t; -#else -template -using enable_if_t = typename std::enable_if::type; -template -using conditional_t = typename std::conditional::type; -template -using remove_cv_t = typename std::remove_cv::type; -template -using remove_reference_t = typename std::remove_reference::type; -#endif #if defined(PYBIND11_CPP20) && defined(__cpp_lib_remove_cvref) using std::remove_cvref; @@ -740,56 +728,8 @@ template using is_same_ignoring_cvref = std::is_same, U>; /// Index sequences -#if defined(PYBIND11_CPP14) using std::index_sequence; using std::make_index_sequence; -#else -template -struct index_sequence {}; -// Comments about the algorithm below. -// -// Credit: This is based on an algorithm by taocpp here: -// https://github.com/taocpp/sequences/blob/main/include/tao/seq/make_integer_sequence.hpp -// but significantly simplified. -// -// We build up a sequence S by repeatedly doubling its length and sometimes adding 1 to the end. -// E.g. if the current S is 0...3, then we either go to 0...7 or 0...8 on the next pass. -// The goal is to end with S = 0...N-1. -// The key insight is that the times we need to add an additional digit to S correspond -// exactly to the 1's in the binary representation of the number N. -// -// Invariants: -// - digit is a power of 2 -// - N_digit_is_1 is whether N's binary representation has a 1 in that digit's position. -// - end <= N -// - S is 0...end-1. -// - if digit > 0, end * digit * 2 <= N < (end+1) * digit * 2 -// -// The process starts with digit > N, end = 0, and S is empty. -// The process concludes with digit=0, in which case, end == N and S is 0...N-1. - -template // N_digit_is_1=false -struct make_index_sequence_impl - : make_index_sequence_impl { -}; -template -struct make_index_sequence_impl - : make_index_sequence_impl {}; -template -struct make_index_sequence_impl<0, false, N, end, S...> { - using type = index_sequence; -}; -constexpr size_t next_power_of_2(size_t N) { return N == 0 ? 1 : next_power_of_2(N >> 1) << 1; } -template -using make_index_sequence = - typename make_index_sequence_impl::type; -#endif /// Make an index sequence of the indices of true arguments template @@ -917,45 +857,38 @@ template struct type_list {}; /// Compile-time integer sum -#ifdef __cpp_fold_expressions template constexpr size_t constexpr_sum(Ts... ns) { - return (0 + ... + size_t{ns}); -} -#else -constexpr size_t constexpr_sum() { return 0; } -template -constexpr size_t constexpr_sum(T n, Ts... ns) { - return size_t{n} + constexpr_sum(ns...); -} -#endif - -PYBIND11_NAMESPACE_BEGIN(constexpr_impl) -/// Implementation details for constexpr functions -constexpr int first(int i) { return i; } -template -constexpr int first(int i, T v, Ts... vs) { - return v ? i : first(i + 1, vs...); -} - -constexpr int last(int /*i*/, int result) { return result; } -template -constexpr int last(int i, int result, T v, Ts... vs) { - return last(i + 1, v ? i : result, vs...); + size_t result = 0; + for (size_t n : {size_t{0}, size_t{ns}...}) { + result += n; + } + return result; } -PYBIND11_NAMESPACE_END(constexpr_impl) /// Return the index of the first type in Ts which satisfies Predicate. /// Returns sizeof...(Ts) if none match. template