初始化 std::variant 的映射以表示 JSON 文件
Initialize a map of std::variant to represent a JSON file
作为学校项目的一部分,我必须读取 JSON 配置文件来填充定义如下的自定义 Conf
对象:
struct ConfValue;
using ConfObject = std::map<std::string, ConfValue>;
using ConfArray = std::vector<ConfValue>;
/**
* Represents a configuration value.
*/
struct ConfValue {
std::variant<std::monostate, ConfObject, ConfArray, std::string, long long, double, bool> v;
};
/**
* Configuration (format influenced by JSON).
*/
using Conf = ConfObject;
我希望能够构造一个由此 JSON 文件表示的默认对象:
{
"port": 4242,
"module": "modheader",
"modulePath": ["../modules/", "./modules"]
}
它可以为我提供在真实配置文件中搜索的内容的映射、每个字段的类型以及每个字段的默认值。
我尝试使用支撑初始化来做到这一点,但无论我尝试什么,都无法编译:
Conf default_conf_{
{"port", ConfValue{4242}},
{"module", ConfValue{"modHeader"}},
{"modulePath", ConfArray{"../modules/", "./modules"}}
};
我想用 C++ 做的事情是否可行?如果可行,怎么做? :)
附带问题:是否可以在 运行 时获取 std::variant 的类型?
您可能会使用:
Conf default_conf {
{"port", ConfValue{4242LL}},
{"module", ConfValue{"modHeader"}},
{"modulePath", ConfValue{ConfArray{ConfValue{"../modules/"}, ConfValue{"./modules"}}}}
};
这里有两个独立的问题。
首先,如果没有更多帮助,4242
将无法工作。您可以将其减少为:
std::variant<long long, bool> v = 4242; // error
转换不明确。所以你必须做出一个更好的匹配。因此,4242LL
.
其次,您只需要在 modulePath
值中添加更多大括号 - 因为我们需要列表初始化所有 ConfValue
,我们不能只构造它们:
Conf default_conf_{{
{"port", {4242LL}},
{"module", {"modHeader"}},
{"modulePath", {ConfArray{{"../modules/"}, {"./modules"}}}}
}};
您基本上需要 ConfArray
来识别所有这些大括号的含义。如果您向 ConfValue
添加了一些构造函数,您也可以取消它。
作为学校项目的一部分,我必须读取 JSON 配置文件来填充定义如下的自定义 Conf
对象:
struct ConfValue;
using ConfObject = std::map<std::string, ConfValue>;
using ConfArray = std::vector<ConfValue>;
/**
* Represents a configuration value.
*/
struct ConfValue {
std::variant<std::monostate, ConfObject, ConfArray, std::string, long long, double, bool> v;
};
/**
* Configuration (format influenced by JSON).
*/
using Conf = ConfObject;
我希望能够构造一个由此 JSON 文件表示的默认对象:
{
"port": 4242,
"module": "modheader",
"modulePath": ["../modules/", "./modules"]
}
它可以为我提供在真实配置文件中搜索的内容的映射、每个字段的类型以及每个字段的默认值。
我尝试使用支撑初始化来做到这一点,但无论我尝试什么,都无法编译:
Conf default_conf_{
{"port", ConfValue{4242}},
{"module", ConfValue{"modHeader"}},
{"modulePath", ConfArray{"../modules/", "./modules"}}
};
我想用 C++ 做的事情是否可行?如果可行,怎么做? :)
附带问题:是否可以在 运行 时获取 std::variant 的类型?
您可能会使用:
Conf default_conf {
{"port", ConfValue{4242LL}},
{"module", ConfValue{"modHeader"}},
{"modulePath", ConfValue{ConfArray{ConfValue{"../modules/"}, ConfValue{"./modules"}}}}
};
这里有两个独立的问题。
首先,如果没有更多帮助,4242
将无法工作。您可以将其减少为:
std::variant<long long, bool> v = 4242; // error
转换不明确。所以你必须做出一个更好的匹配。因此,4242LL
.
其次,您只需要在 modulePath
值中添加更多大括号 - 因为我们需要列表初始化所有 ConfValue
,我们不能只构造它们:
Conf default_conf_{{
{"port", {4242LL}},
{"module", {"modHeader"}},
{"modulePath", {ConfArray{{"../modules/"}, {"./modules"}}}}
}};
您基本上需要 ConfArray
来识别所有这些大括号的含义。如果您向 ConfValue
添加了一些构造函数,您也可以取消它。