:twisted_rightwards_arrows: merge develop
diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml
index 93bbba4..ccc0762 100644
--- a/.github/workflows/ubuntu.yml
+++ b/.github/workflows/ubuntu.yml
@@ -25,7 +25,7 @@
         run: apt-get update ; apt-get install -y git unzip
       - uses: actions/checkout@v4
       - name: Get latest CMake and ninja
-        uses: lukka/get-cmake@v3.27.7
+        uses: lukka/get-cmake@v3.31.0
       - name: Run CMake
         run: cmake -S . -B build -DJSON_CI=On
       - name: Build
@@ -62,7 +62,7 @@
     steps:
       - uses: actions/checkout@v4
       - name: Get latest CMake and ninja
-        uses: lukka/get-cmake@v3.27.7
+        uses: lukka/get-cmake@v3.31.0
       - name: Run CMake
         run: cmake -S . -B build -DJSON_CI=On
       - name: Build
@@ -79,7 +79,7 @@
         run: apt-get update ; apt-get install -y git clang-tools unzip
       - uses: actions/checkout@v4
       - name: Get latest CMake and ninja
-        uses: lukka/get-cmake@v3.27.7
+        uses: lukka/get-cmake@v3.31.0
       - name: Run CMake
         run: cmake -S . -B build -DJSON_CI=On
       - name: Build
@@ -96,7 +96,7 @@
         run: apt-get update ; apt-get install -y build-essential unzip wget git
       - uses: actions/checkout@v4
       - name: Get latest CMake and ninja
-        uses: lukka/get-cmake@v3.27.7
+        uses: lukka/get-cmake@v3.31.0
       - name: Run CMake
         run: cmake -S . -B build -DJSON_CI=On
       - name: Build
@@ -148,7 +148,7 @@
     steps:
       - uses: actions/checkout@v4
       - name: Get latest CMake and ninja
-        uses: lukka/get-cmake@v3.27.7
+        uses: lukka/get-cmake@v3.31.0
       - name: Run CMake
         run: cmake -S . -B build -DJSON_CI=On
       - name: Build
@@ -165,7 +165,7 @@
         run: apt-get update ; apt-get install -y unzip git
       - uses: actions/checkout@v4
       - name: Get latest CMake and ninja
-        uses: lukka/get-cmake@v3.27.7
+        uses: lukka/get-cmake@v3.31.0
       - name: Set env FORCE_STDCPPFS_FLAG for clang 7 / 8 / 9 / 10
         run: echo "JSON_FORCED_GLOBAL_COMPILE_OPTIONS=-DJSON_HAS_FILESYSTEM=0;-DJSON_HAS_EXPERIMENTAL_FILESYSTEM=0" >> "$GITHUB_ENV"
         if: ${{ matrix.compiler == '7' || matrix.compiler == '8' || matrix.compiler == '9' || matrix.compiler == '10' }}
@@ -206,16 +206,21 @@
     strategy:
       matrix:
         standard: [11, 14, 17, 20, 23]
+        stdlib: [libcxx, libstdcxx]
     steps:
       - name: Install git and unzip
         run: apt-get update ; apt-get install -y git unzip
       - uses: actions/checkout@v4
       - name: Get latest CMake and ninja
-        uses: lukka/get-cmake@v3.27.7
+        uses: lukka/get-cmake@v3.31.0
       - name: Run CMake
         run: cmake -S . -B build -DJSON_CI=On
-      - name: Build
+      - name: Build with libc++
+        run: cmake --build build --target ci_test_clang_libcxx_cxx${{ matrix.standard }}
+        if: ${{ matrix.stdlib == 'libcxx' }}
+      - name: Build with libstdc++
         run: cmake --build build --target ci_test_clang_cxx${{ matrix.standard }}
+        if: ${{ matrix.stdlib == 'libstdcxx' }}
 
   ci_cuda_example:
     runs-on: ubuntu-latest
@@ -231,7 +236,7 @@
     runs-on: ubuntu-latest
     container: ghcr.io/nlohmann/json-ci:v2.2.0
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v4
       - name: Run CMake
         run: cmake -S . -B build -DJSON_CI=On
       - name: Build
@@ -243,7 +248,9 @@
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v4
-      - uses: actions/setup-python@v3
+      - uses: actions/setup-python@v5
+        with:
+          python-version: '3.11'
       - name: Install REUSE tool
         run:  python -m pip install reuse
       - name: Run REUSE lint
diff --git a/README.md b/README.md
index 25f443a..34a79f4 100644
--- a/README.md
+++ b/README.md
@@ -1111,7 +1111,7 @@
 
 ## Supported compilers
 
-Though it's 2023 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work:
+Though it's 2024 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work:
 
 - GCC 4.8 - 14.2 (and possibly later)
 - Clang 3.4 - 20.0 (and possibly later)
@@ -1898,7 +1898,7 @@
 
 In case you have downloaded the library rather than checked out the code via Git, test `cmake_fetch_content_configure` will fail. Please execute `ctest -LE git_required` to skip these tests. See [issue #2189](https://github.com/nlohmann/json/issues/2189) for more information.
 
-Some tests change the installed files and hence make the whole process not reproducible. Please execute `ctest -LE not_reproducible` to skip these tests. See [issue #2324](https://github.com/nlohmann/json/issues/2324) for more information.
+Some tests change the installed files and hence make the whole process not reproducible. Please execute `ctest -LE not_reproducible` to skip these tests. See [issue #2324](https://github.com/nlohmann/json/issues/2324) for more information. Furthermore, assertions must be switched off to ensure reproducible builds (see [discussion 4494](https://github.com/nlohmann/json/discussions/4494)).
 
 Note you need to call `cmake -LE "not_reproducible|git_required"` to exclude both labels. See [issue #2596](https://github.com/nlohmann/json/issues/2596) for more information.
 
diff --git a/cmake/ci.cmake b/cmake/ci.cmake
index bbb2d4c..692790a 100644
--- a/cmake/ci.cmake
+++ b/cmake/ci.cmake
@@ -13,7 +13,7 @@
 string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" ASTYLE_TOOL_VERSION "${ASTYLE_TOOL_VERSION}")
 message(STATUS "🔖 Artistic Style ${ASTYLE_TOOL_VERSION} (${ASTYLE_TOOL})")
 
-find_program(CLANG_TOOL NAMES clang++-HEAD clang++ clang++-17 clang++-16 clang++-15 clang++-14 clang++-13 clang++-12 clang++-11 clang++)
+find_program(CLANG_TOOL NAMES clang++-HEAD clang++ clang++-20 clang++-19 clang++-18 clang++-17 clang++-16 clang++-15 clang++-14 clang++-13 clang++-12 clang++-11 clang++)
 execute_process(COMMAND ${CLANG_TOOL} --version OUTPUT_VARIABLE CLANG_TOOL_VERSION ERROR_VARIABLE CLANG_TOOL_VERSION)
 string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TOOL_VERSION "${CLANG_TOOL_VERSION}")
 message(STATUS "🔖 Clang ${CLANG_TOOL_VERSION} (${CLANG_TOOL})")
@@ -461,6 +461,19 @@
         COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
         COMMENT "Compile and test with Clang for C++${CXX_STANDARD}"
     )
+
+    add_custom_target(ci_test_clang_libcxx_cxx${CXX_STANDARD}
+        COMMAND CXX=${CLANG_TOOL} CXXFLAGS="${CLANG_CXXFLAGS}" ${CMAKE_COMMAND}
+            -DCMAKE_BUILD_TYPE=Debug -GNinja
+            -DJSON_BuildTests=ON -DJSON_FastTests=ON
+            -DJSON_TestStandards=${CXX_STANDARD}
+            -DCMAKE_CXX_FLAGS="-stdlib=libc++"
+            -DCMAKE_EXE_LINKER_FLAGS="-lc++abi"
+            -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD}
+        COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD}
+        COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
+        COMMENT "Compile and test with Clang for C++${CXX_STANDARD} (libc++)"
+    )
 endforeach()
 
 ###############################################################################
@@ -900,7 +913,7 @@
 # Use more installed compilers.
 ###############################################################################
 
-foreach(COMPILER g++-4.8 g++-4.9 g++-5 g++-6 g++-7 g++-8 g++-9 g++-10 g++-11 clang++-3.5 clang++-3.6 clang++-3.7 clang++-3.8 clang++-3.9 clang++-4.0 clang++-5.0 clang++-6.0 clang++-7 clang++-8 clang++-9 clang++-10 clang++-11 clang++-12 clang++-13 clang++-14 clang++-15 clang++-16 clang++-17)
+foreach(COMPILER g++-4.8 g++-4.9 g++-5 g++-6 g++-7 g++-8 g++-9 g++-10 g++-11 clang++-3.5 clang++-3.6 clang++-3.7 clang++-3.8 clang++-3.9 clang++-4.0 clang++-5.0 clang++-6.0 clang++-7 clang++-8 clang++-9 clang++-10 clang++-11 clang++-12 clang++-13 clang++-14 clang++-15 clang++-16 clang++-17 clang++-18 clang++-19 clang++-20)
     find_program(COMPILER_TOOL NAMES ${COMPILER})
     if (COMPILER_TOOL)
         unset(ADDITIONAL_FLAGS)
diff --git a/include/nlohmann/detail/input/parser.hpp b/include/nlohmann/detail/input/parser.hpp
index 3463a65..54cc0c7 100644
--- a/include/nlohmann/detail/input/parser.hpp
+++ b/include/nlohmann/detail/input/parser.hpp
@@ -69,7 +69,7 @@
   public:
     /// a parser reading from an input adapter
     explicit parser(InputAdapterType&& adapter,
-                    parser_callback_t<BasicJsonType>& cb = nullptr,
+                    parser_callback_t<BasicJsonType> cb = nullptr,
                     const bool allow_exceptions_ = true,
                     const bool skip_comments = false)
         : callback(std::move(cb))
diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp
index 904dec0..8839bea 100644
--- a/include/nlohmann/json.hpp
+++ b/include/nlohmann/json.hpp
@@ -4011,7 +4011,7 @@
     template<typename InputType>
     JSON_HEDLEY_WARN_UNUSED_RESULT
     static basic_json parse(InputType&& i,
-                            parser_callback_t& cb = nullptr,
+                            parser_callback_t cb = nullptr,
                             const bool allow_exceptions = true,
                             const bool ignore_comments = false)
     {
@@ -4026,7 +4026,7 @@
     JSON_HEDLEY_WARN_UNUSED_RESULT
     static basic_json parse(IteratorType first,
                             IteratorType last,
-                            parser_callback_t& cb = nullptr,
+                            parser_callback_t cb = nullptr,
                             const bool allow_exceptions = true,
                             const bool ignore_comments = false)
     {
diff --git a/tests/src/unit-bson.cpp b/tests/src/unit-bson.cpp
index 13216f2..fdfc350 100644
--- a/tests/src/unit-bson.cpp
+++ b/tests/src/unit-bson.cpp
@@ -621,7 +621,7 @@
     {
         SECTION("std::ostringstream")
         {
-            std::basic_ostringstream<std::uint8_t> ss;
+            std::basic_ostringstream<char> ss;
             json::to_bson(json_representation, ss);
             json j3 = json::from_bson(ss.str());
             CHECK(json_representation == j3);
diff --git a/tests/src/unit-cbor.cpp b/tests/src/unit-cbor.cpp
index 5d371f3..e20fc07 100644
--- a/tests/src/unit-cbor.cpp
+++ b/tests/src/unit-cbor.cpp
@@ -1880,7 +1880,7 @@
         {
             SECTION("std::ostringstream")
             {
-                std::basic_ostringstream<std::uint8_t> ss;
+                std::basic_ostringstream<char> ss;
                 json::to_cbor(j1, ss);
                 json j3 = json::from_cbor(ss.str());
                 CHECK(j1 == j3);
diff --git a/tests/src/unit-deserialization.cpp b/tests/src/unit-deserialization.cpp
index 0dc86be..c64af93 100644
--- a/tests/src/unit-deserialization.cpp
+++ b/tests/src/unit-deserialization.cpp
@@ -20,6 +20,7 @@
 #include <sstream>
 #include <valarray>
 
+
 namespace
 {
 struct SaxEventLogger : public nlohmann::json_sax<json>
@@ -1131,13 +1132,15 @@
     }
 }
 
-TEST_CASE_TEMPLATE("deserialization of different character types (ASCII)", T, // NOLINT(readability-math-missing-parentheses)
-                   char, unsigned char, signed char,
-                   wchar_t,
-                   char16_t, char32_t,
-                   std::uint8_t, std::int8_t,
-                   std::int16_t, std::uint16_t,
-                   std::int32_t, std::uint32_t)
+// select the types to test - char8_t is only available in C++20
+#define TYPE_LIST(...) __VA_ARGS__
+#ifdef JSON_HAS_CPP_20
+    #define ASCII_TYPES TYPE_LIST(char, wchar_t, char16_t, char32_t, char8_t)
+#else
+    #define ASCII_TYPES TYPE_LIST(char, wchar_t, char16_t, char32_t)
+#endif
+
+TEST_CASE_TEMPLATE("deserialization of different character types (ASCII)", T, ASCII_TYPES) // NOLINT(readability-math-missing-parentheses)
 {
     std::vector<T> const v = {'t', 'r', 'u', 'e'};
     CHECK(json::parse(v) == json(true));
@@ -1150,7 +1153,7 @@
 }
 
 TEST_CASE_TEMPLATE("deserialization of different character types (UTF-8)", T, // NOLINT(readability-math-missing-parentheses)
-                   char, unsigned char, std::uint8_t)
+                   char, unsigned char, std::uint8_t)// NOLINT(readability-math-missing-parentheses)
 {
     // a star emoji
     std::vector<T> const v = {'"', static_cast<T>(0xe2u), static_cast<T>(0xadu), static_cast<T>(0x90u), static_cast<T>(0xefu), static_cast<T>(0xb8u), static_cast<T>(0x8fu), '"'};
@@ -1163,7 +1166,7 @@
 }
 
 TEST_CASE_TEMPLATE("deserialization of different character types (UTF-16)", T, // NOLINT(readability-math-missing-parentheses)
-                   char16_t, std::uint16_t)
+                   char16_t) // NOLINT(readability-math-missing-parentheses)
 {
     // a star emoji
     std::vector<T> const v = {static_cast<T>('"'), static_cast<T>(0x2b50), static_cast<T>(0xfe0f), static_cast<T>('"')};
@@ -1176,7 +1179,7 @@
 }
 
 TEST_CASE_TEMPLATE("deserialization of different character types (UTF-32)", T, // NOLINT(readability-math-missing-parentheses)
-                   char32_t, std::uint32_t)
+                   char32_t) // NOLINT(readability-math-missing-parentheses)
 {
     // a star emoji
     std::vector<T> const v = {static_cast<T>('"'), static_cast<T>(0x2b50), static_cast<T>(0xfe0f), static_cast<T>('"')};
diff --git a/tests/src/unit-msgpack.cpp b/tests/src/unit-msgpack.cpp
index 5e26dee..e91aab4 100644
--- a/tests/src/unit-msgpack.cpp
+++ b/tests/src/unit-msgpack.cpp
@@ -1604,7 +1604,7 @@
         {
             SECTION("std::ostringstream")
             {
-                std::basic_ostringstream<std::uint8_t> ss;
+                std::basic_ostringstream<char> ss;
                 json::to_msgpack(j1, ss);
                 json j3 = json::from_msgpack(ss.str());
                 CHECK(j1 == j3);
diff --git a/tests/src/unit-regression2.cpp b/tests/src/unit-regression2.cpp
index a1f5fe9..84e7f55 100644
--- a/tests/src/unit-regression2.cpp
+++ b/tests/src/unit-regression2.cpp
@@ -675,6 +675,7 @@
     }
 
 #ifdef JSON_HAS_CPP_20
+#ifndef _LIBCPP_VERSION // see https://github.com/nlohmann/json/issues/4490
 #if __has_include(<span>)
     SECTION("issue #2546 - parsing containers of std::byte")
     {
@@ -685,6 +686,7 @@
     }
 #endif
 #endif
+#endif
 
     SECTION("issue #2574 - Deserialization to std::array, std::pair, and std::tuple with non-default constructable types fails")
     {
diff --git a/tests/src/unit-udt_macro.cpp b/tests/src/unit-udt_macro.cpp
index 2c44fc7..2755397 100644
--- a/tests/src/unit-udt_macro.cpp
+++ b/tests/src/unit-udt_macro.cpp
@@ -472,7 +472,7 @@
     }
 }
 
-TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE and NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE", T,
+TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE and NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE", T, // NOLINT(readability-math-missing-parentheses)
                    persons::derived_person_with_private_data,
                    persons::derived_person_without_private_data_1,
                    persons::derived_person_without_private_data_2)