You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When passing a json value using brace initialization with a single element
(e.g., `json j{someObj}` or `foo({someJson})`), C++ always prefers the
initializer_list constructor over the copy/move constructor. This caused
the value to be unexpectedly wrapped in a single-element array.
This bug was previously compiler-dependent (GCC wrapped, Clang did not),
but Clang 20 started matching GCC behavior, making it a universal issue.
Fix: In the initializer_list constructor, when type deduction is enabled
and the list has exactly one element, copy/move it directly instead of
creating a single-element array.
Before:
json obj = {{"key", 1}};
json j{obj}; // -> [{"key":1}] (wrong: array)
foo({obj}); // -> [{"key":1}] (wrong: array)
After:
json j{obj}; // -> {"key":1} (correct: copy)
foo({obj}); // -> {"key":1} (correct: copy)
To explicitly create a single-element array, use json::array({value}).
Fixes the issue #5074
Copy file name to clipboardExpand all lines: docs/mkdocs/docs/home/faq.md
+15-4Lines changed: 15 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -20,7 +20,16 @@
20
20
21
21
yield different results (`#!json [true]` vs. `#!json true`)?
22
22
23
-
This is a known issue, and -- even worse -- the behavior differs between GCC and Clang. The "culprit" for this is the library's constructor overloads for initializer lists to allow syntax like
23
+
Starting from this version, single-value brace initialization is treated as copy/move instead of wrapping in a single-element array:
24
+
25
+
```cpp
26
+
json j_orig = {{"key", "value"}};
27
+
28
+
json j{j_orig};
29
+
j_orig.method();
30
+
```
31
+
32
+
The root cause was the library's constructor overloads for initializer lists, which allow syntax like
24
33
25
34
```cpp
26
35
json array = {1, 2, 3, 4};
@@ -32,11 +41,13 @@ for arrays and
32
41
json object = {{"one", 1}, {"two", 2}};
33
42
```
34
43
35
-
for objects.
44
+
for objects. Because C++ always prefers `initializer_list` constructors for brace initialization, a single-element brace-init `json j{someValue}` previously wrapped the value in an array instead of copying it.
36
45
37
-
!!! tip
46
+
After the fix, a single-element brace-init behaves like copy/move initialization. To explicitly create a single-element array, use `json::array({value})`.
47
+
48
+
!!! note
38
49
39
-
To avoid any confusion and ensure portable code, **do not** use brace initialization with the types `basic_json`, `json`, or `ordered_json` unless you want to create an object or array as shown in the examples above.
50
+
The fix changes the behavior of single-element brace initialization: `json j{x}` is now equivalent to `json j(x)` (copy/move) rather than `json j = json::array({x})` (single-element array). Code relying on the old behavior should be updated to use `json::array({x})` explicitly.
0 commit comments