<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[json库的initializer_list创建问题]]></title><description><![CDATA[<p dir="auto">用c++17  variant实现的json库，想实现用 {} 大括号快速构建一个嵌套的json对象，但是加入了initializerlist后出现了灾难性的构造问题，无法构造数组、对象类型，更无法构建复杂的嵌套类型。如果去掉其中一个列表初始化，只保留构建数组的初始化列表，也不能实现匹配的问题，除非在构造时手动标明类型，但这和列表初始化的初衷完全背离了</p>
<p dir="auto">main</p>
<pre><code>#include "include/json/json.h"
#include &lt;iostream&gt;

using myjson::Json;
using std::cin, std::cout, std::endl;
int main(int, char **) {
  // 数组也无法用initializer_list构造，除非将部分单参数构造变为隐式，但这本质就是错误的，可能导致一系列问题
  Json json_1 { 3.141, 2, 17};
  // Json json2
  // {
  //     {"pi", 3.141},
  //     {"happy", true},
  //     {"name", "Niels"},
  //     {"nothing", nullptr},
  //     {
  //         "answer", {
  //             {"everything", 42}
  //         }
  //     },
  //     {"list", {1, 0, 2}}
  // };
  cout&lt;&lt;json_1.is_array()&lt;&lt;endl;
  cout&lt;&lt;json_2.is_object()&lt;&lt;endl;
  return 0;
}

</code></pre>
<p dir="auto">json.h</p>
<pre><code>#pragma once

#include &lt;cstddef&gt;
#include &lt;initializer_list&gt;
#include &lt;stdexcept&gt;
#include &lt;string&gt;
#include &lt;unordered_map&gt;
#include &lt;utility&gt;
#include &lt;variant&gt;
#include &lt;vector&gt;

namespace myjson {
class Json;

template &lt;typename... Ts&gt; struct overload : Ts... {
  using Ts::operator()...;
};
template &lt;typename... Ts&gt; overload(Ts...) -&gt; overload&lt;Ts...&gt;;

using JsonArray = std::vector&lt;Json&gt;;
using JsonObject = std::unordered_map&lt;std::string, Json&gt;;

class Json {
public:
  using ValueType = std::variant&lt;std::nullptr_t, bool, int, double, std::string,
                                 JsonArray, JsonObject&gt;;
public:
  Json() : m_value(nullptr) {}
  Json(const Json &amp;) = default;
  Json(Json &amp;&amp;) = default;
  ~Json() = default;
  // 从基本类型构造
  Json(std::nullptr_t) : m_value(nullptr) {}
  explicit Json(bool value) : m_value(value) {}
  // 防止 bool 构造为 int
  template&lt;typename Int, typename = std::enable_if_t&lt;std::is_integral_v&lt;Int&gt;
  &amp;&amp; !std::is_same_v&lt;Int, bool&gt;&gt;&gt; 
  explicit Json(int value) noexcept : m_value(static_cast&lt;int&gt;(value)) {} 
  explicit Json(double value) : m_value(value) {}
  explicit Json(const std::string&amp; value) : m_value(value) {}

  //const char* 是否需要构造存疑
  // explicit Json(const char* value) : m_value(std::string(value)) {}
  explicit Json(JsonArray value) : m_value(std::move(value)) {}
  explicit Json(JsonObject value) : m_value(std::move(value)) {}

  
    Json(std::initializer_list&lt;Json&gt; init){
      JsonArray array;
      for (const auto&amp; element : init) {
          array.emplace_back(element);
      }
      m_value = std::move(array);
  }
  // object initializer_list构造
  // Json(std::initializer_list&lt;std::pair&lt;const std::string, Json&gt;&gt; init) {
  //     JsonObject dict;
  //     for (const auto&amp; p : init) {
  //         dict.insert(p);
  //     }
  //     m_value = std::move(dict);
  // }

  Json &amp;operator=(const Json &amp;other) = default;
  Json &amp;operator=(Json &amp;&amp;other) = default;

public:
  &lsqb;&lsqb;nodiscard&rsqb;&rsqb; constexpr bool is_boolean() const noexcept {
    return std::holds_alternative&lt;bool&gt;(m_value);
  }
  &lsqb;&lsqb;nodiscard&rsqb;&rsqb; constexpr bool is_integer() const noexcept {
    return std::holds_alternative&lt;int&gt;(m_value);
  }
  &lsqb;&lsqb;nodiscard&rsqb;&rsqb; constexpr bool is_null() const noexcept {
    return std::holds_alternative&lt;nullptr_t&gt;(m_value);
  }
  &lsqb;&lsqb;nodiscard&rsqb;&rsqb; constexpr bool is_double() const noexcept {
    return std::holds_alternative&lt;double&gt;(m_value);
  }
  &lsqb;&lsqb;nodiscard&rsqb;&rsqb; constexpr bool is_string() const noexcept {
    return std::holds_alternative&lt;std::string&gt;(m_value);
  }
  &lsqb;&lsqb;nodiscard&rsqb;&rsqb; constexpr bool is_array() const noexcept {
    return std::holds_alternative&lt;JsonArray&gt;(m_value);
  }
  &lsqb;&lsqb;nodiscard&rsqb;&rsqb; constexpr bool is_object() const noexcept {
    return std::holds_alternative&lt;JsonObject&gt;(m_value);
  }

  template &lt;typename T&gt; const T &amp;get() const {
    if (!std::holds_alternative&lt;T&gt;(m_value))
      throw std::runtime_error("type mismatch");
    return std::get&lt;T&gt;(m_value);
  }

  template &lt;typename T&gt; T &amp;get() {
    if (!std::holds_alternative&lt;T&gt;(m_value))
      throw std::runtime_error("type mismatch");
    return std::get&lt;T&gt;(m_value);
  }
JsonArray as_array() {
  if (!is_array())
    throw std::runtime_error("Not an array");
  return get&lt;JsonArray&gt;();
}

JsonObject as_dict() {
  if (!is_object())
    throw std::runtime_error("Not an dict");
  return get&lt;JsonObject&gt;();
}

private:
  ValueType m_value;
};

} // namespace myjson
</code></pre>
]]></description><link>http://forum.d2learn.org/topic/131/json库的initializer_list创建问题</link><generator>RSS for Node</generator><lastBuildDate>Thu, 13 Aug 2026 15:58:28 GMT</lastBuildDate><atom:link href="http://forum.d2learn.org/topic/131.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 07 Sep 2025 18:01:14 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to json库的initializer_list创建问题 on Mon, 08 Sep 2025 04:31:58 GMT]]></title><description><![CDATA[<p dir="auto"><a class="mention plugin-mentions-user plugin-mentions-a" href="http://forum.d2learn.org/uid/3">@SPeak</a><br />
按照这个思路，只保留一个列表初始化，用了一个辅助函数检测了每个元素是否是数组，如果是数组就检测长度是否是2，然后首元素是否是string，如果初始化列表里全部元素都符合就判定为object。这个代码运行成功了，感谢大佬</p>
<pre><code>  Json(std::initializer_list&lt;Json&gt; init) {
    if (is_object_list(init)) {
      JsonObject dict;
      for (const auto &amp;el : init) {
        auto pair = std::get_if&lt;JsonArray&gt;(&amp;el.m_value);
        // 必须是长度为2的数组
        assert(pair &amp;&amp; pair-&gt;size() == 2);
        auto key = std::get_if&lt;std::string&gt;(&amp;(*pair)[0].m_value);
        // 第一个元素必须是字符串
        assert(key);
        dict.emplace(*key, (*pair)[1]);
      }
      m_value = std::move(dict);
    } else {
      m_value = JsonArray(init);
    }
  }

  bool is_object_list(std::initializer_list&lt;Json&gt; init) {
    return std::all_of(init.begin(), init.end(), [](const Json &amp;el) {
      auto pair = std::get_if&lt;JsonArray&gt;(&amp;el.m_value);
      if (!pair || pair-&gt;size() != 2)
        return false;
      return std::holds_alternative&lt;std::string&gt;((*pair)[0].m_value);
    });
  }
</code></pre>
]]></description><link>http://forum.d2learn.org/post/571</link><guid isPermaLink="true">http://forum.d2learn.org/post/571</guid><dc:creator><![CDATA[dustchens]]></dc:creator><pubDate>Mon, 08 Sep 2025 04:31:58 GMT</pubDate></item><item><title><![CDATA[Reply to json库的initializer_list创建问题 on Sun, 07 Sep 2025 20:49:19 GMT]]></title><description><![CDATA[<p dir="auto">至于为什么 initializer_list 和 数组冲突, 因为数组Vector 他本质是间接 initializer_list, 并且当一个对象有 initializer_list 构造函数时 优先匹配 initializer_list</p>
<p dir="auto">具体可以参考mcpp-stand的在线电子书的initializer_list章节: <a href="https://sunrisepeak.github.io/mcpp-standard/cpp11/09-list-initialization.html" rel="nofollow ugc">https://sunrisepeak.github.io/mcpp-standard/cpp11/09-list-initialization.html</a></p>
<p dir="auto"><img src="/assets/uploads/files/1757278107727-698da96b-859a-4526-9e41-279eee855cbb-image.png" alt="image.png" class=" img-fluid img-markdown" /></p>
]]></description><link>http://forum.d2learn.org/post/570</link><guid isPermaLink="true">http://forum.d2learn.org/post/570</guid><dc:creator><![CDATA[SPeak]]></dc:creator><pubDate>Sun, 07 Sep 2025 20:49:19 GMT</pubDate></item><item><title><![CDATA[Reply to json库的initializer_list创建问题 on Sun, 07 Sep 2025 20:46:01 GMT]]></title><description><![CDATA[<p dir="auto"><a class="mention plugin-mentions-user plugin-mentions-a" href="http://forum.d2learn.org/uid/133">@dustchens</a> 可以尝试从最简单的方式先满足Json风格初始化, 然后再这个基础看看怎么调整比较适合解析。 可能是一些思路</p>
<ul>
<li>可以对 initializer_list类型复用 即是数组 也是 key-value, 内部再解析到对应的类型
<ul>
<li>size = 2 时是 kv</li>
<li>size &gt; 2 时
<ul>
<li>所有子元素size=2 -&gt; kv对象</li>
<li>数组</li>
<li>或也可以增加一些类型信息辅助解析</li>
</ul>
</li>
</ul>
</li>
<li>Vector 本质也是间接使用 initializer_list</li>
</ul>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;initializer_list&gt;

struct Json {
    Json() = default;
    Json(std::initializer_list&lt;Json&gt; init) { std::cout &lt;&lt; "initializer_list of Json with size: " &lt;&lt; init.size() &lt;&lt; std::endl; }
    Json(double value) { std::cout &lt;&lt; "double: " &lt;&lt; value &lt;&lt; std::endl; }
    Json(int value) { std::cout &lt;&lt; "int: " &lt;&lt; value &lt;&lt; std::endl; }
    Json(bool value) { std::cout &lt;&lt; "bool: " &lt;&lt; std::boolalpha &lt;&lt; value &lt;&lt; std::endl; }
    Json(std::nullptr_t value) { std::cout &lt;&lt; "null" &lt;&lt; std::endl; }
    Json(const char* value) { std::cout &lt;&lt; "const char*: " &lt;&lt; value &lt;&lt; std::endl; }
    Json(std::string value) { std::cout &lt;&lt; "string: " &lt;&lt; value &lt;&lt; std::endl; }
};

int main() {
    Json json_1 { 3.141, 2, 17 };
    std::cout &lt;&lt; "----" &lt;&lt; std::endl;
    Json json_2 {
        {"pi", 3.141},
        {"happy", true},
        {"name", "Niels"},
        {"nothing", nullptr},
        {
            "answer", {
                {"everything", 42}
            }
        },
        {"list", {1, 0, 2}}
    };

    return 0;
}


</code></pre>
<hr />
<p dir="auto"><img src="/assets/uploads/files/1757276781910-3f3a453c-7349-40a0-bbdf-50b8a980f8e3-image.png" alt="image.png" class=" img-fluid img-markdown" /></p>
]]></description><link>http://forum.d2learn.org/post/569</link><guid isPermaLink="true">http://forum.d2learn.org/post/569</guid><dc:creator><![CDATA[SPeak]]></dc:creator><pubDate>Sun, 07 Sep 2025 20:46:01 GMT</pubDate></item><item><title><![CDATA[Reply to json库的initializer_list创建问题 on Sun, 07 Sep 2025 18:08:55 GMT]]></title><description><![CDATA[<p dir="auto">可能给每个类型都加一个构造函数也是有问题的设计，也许需要一个模板替代</p>
]]></description><link>http://forum.d2learn.org/post/568</link><guid isPermaLink="true">http://forum.d2learn.org/post/568</guid><dc:creator><![CDATA[dustchens]]></dc:creator><pubDate>Sun, 07 Sep 2025 18:08:55 GMT</pubDate></item></channel></rss>