Skip to content

Define json::value's unique_ptr constructor and destructor out of line - #36

Merged
garethsb merged 1 commit into
cpprest-ltsfrom
fix/clang21-incomplete-json-value
Nov 5, 2026
Merged

garethsb merged 1 commit into
cpprest-ltsfrom
fix/clang21-incomplete-json-value

Conversation

@garethsb

@garethsb garethsb commented Nov 5, 2026

Copy link
Copy Markdown
Collaborator

cpprest/json.h defines the private json::value constructor that takes a std::unique_ptr<details::_Value> inline, and the destructor is implicit. Both destroy the unique_ptr where _Value is incomplete. From C++23, std::unique_ptr's destructor is constexpr, and Clang 21 instantiates it there, so std::default_delete's static_assert fails in every translation unit that includes cpprest/json.h.

This PR declares the constructor and the destructor in json.h and defines them in json.cpp, where _Value is complete. The change is taken from vcpkg's ports/cpprestsdk/fix-incomplete-json-value.patch, added by Nicholas Matteo in microsoft/vcpkg#51307, and keeps him as the commit author. The one difference from the patch is where the destructor is declared: here it is with the other public special members, not in a public: block among the private members. json::value already declares its copy and move operations, so declaring the destructor leaves them unchanged.

Testing

I tested with Clang 21.1.8 on Ubuntu 26.04:

  • A file that includes cpprest/json.h fails at -std=c++23 without this change, with both libstdc++ 15 and libc++ 21. It compiles with this change at C++17, C++20 and C++23.
  • With -DCMAKE_CXX_STANDARD=23, the library build fails without this change and succeeds with it. The library's CMake adds -std=c++11, so only a consumer's C++23 setting triggers the error.
  • The default build passes all 7 test suites.

Not Included

Issue #13 also asks for a CI job with a recent Clang, so this PR doesn't close it. A C++23 job can't build the tests yet, because three test files don't compile at C++20 or later:

  • test_runner.cpp uses requires as a variable name, and requires is a keyword from C++20.
  • strings.cpp and memstream_tests.cpp write char16_t values to a stream through UnitTest++, and C++20 deletes those stream operators.

Part of #13.

Co-authored-by: Gareth's 🤖 buddy

json.h defines the private constructor that takes a
std::unique_ptr<details::_Value> inline, and the destructor is
implicit, so both destroy the unique_ptr where _Value is incomplete.
From C++23, std::unique_ptr's destructor is constexpr, and Clang 21
instantiates it there, so std::default_delete's static_assert fails in
every translation unit that includes cpprest/json.h. Declare the
constructor and the destructor in json.h, and define them in json.cpp,
where _Value is complete.

Taken from vcpkg's ports/cpprestsdk/fix-incomplete-json-value.patch,
added in microsoft/vcpkg@d015e31e90 (microsoft/vcpkg#51307). The
destructor is declared with the other public special members, rather
than in a public section among the private members.

Part of #13.

Signed-off-by: Gareth Sylvester-Bradley <garethsb@nvidia.com>
@garethsb
garethsb merged commit f5b8079 into cpprest-lts Nov 5, 2026
8 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants