我有2个包含不同数据的结构,每个结构都有一个方法将这些数据序列化为JSON字符串:
struct Struct1
{
Struct1(int value) : value(value){};
int value;
std::string ToJSON() const
{
std::string ret = "{value: " + std::to_string(value) + "}";
return ret;
}
};
struct Struct2
{
Struct2(std::string id, std::string image, std::string name) : id(id), image(image), name(name){};
std::string id;
std::string image;
std::string name;
std::string ToJSON() const
{
return "{id: " + id + " image: " + image + " name: " + name + "}";
}
};
我需要将其中的几个存储在一个容器中,以便稍后迭代它们并从每个对象获取JSON字符串。我使用std::variant
执行此操作。
std::vector<std::variant<Struct1, Struct2>> v3;
然后我可以像这样迭代容器:
auto GetJSONString = [](auto&& _in){return _in.ToJSON();};
for (const auto& nextV : v3)
{
auto test = std::visit(GetJSONString, nextV);
std::cout << test << " ";
}
std::cout << std::endl;
在我尝试使用braced-init-lists填充向量之前,一切正常。
换句话说,这是有效的:
std::vector<std::variant<Struct1, Struct2>> v{Struct1(5), Struct2("someid", "someimage", "somename")};
但这不是:
std::vector<std::variant<Struct1, Struct2>> v4{ {13}, {"someid", "someimage", "somename"}};
在不工作的代码上,我得到以下编译器错误:
error: no matching function for call to 'std::vector<std::variant<Struct2, Struct1> >::vector(<brace-enclosed initializer list>)
我不明白为什么会这样。在这种情况下我不能使用大括号初始化吗?如果是的话,......为什么?或者我是否需要以某种方式修改我的结构以支持这种初始化?
Here是wandbox.org上的一个最小工作示例,用于进一步说明我的问题。
答案 0 :(得分:2)
不,你不能。不,没有任何改变可以让它发挥作用。这是一个非常简单的例子:在这种情况下我不能使用大括号初始化吗?如果是的话,......为什么?或者我是否需要以某种方式修改我的结构以支持这种初始化?
template <typename T> void foo(T&& );
foo({1}); // what is T?
Braced-init-lists没有类型,因此无法推断出它们。 variant
构造函数的工作方式是推导其参数,然后选择从中初始化的最佳替代方法。它不能从你的braced-init-list那样做,你必须使用一个有类型的表达式。
唯一可行的方法是variant<A, B, C>
本身有非模板构造函数variant(A&& )
,variant(B&& )
和variant(C&& )
。 然后,braced-init-lists会起作用。
答案 1 :(得分:1)
您打算让代码调用的variant
constructor是
template<typename T>
constexpr variant(T&& t)
但该构造函数模板的模板参数推断将失败,因为braced-init-lists do not have a type。
使用以std::in_place_type_t<T>
作为第一个参数的构造函数可以更接近
std::vector<std::variant<Struct2, Struct1>> v4{
{ std::in_place_type<Struct1>, 13 },
{ std::in_place_type<Struct2>, "someid", "someimage", "somename" }
};
但这也失败了,因为有问题的variant
构造函数是explicit
,ill-formed for copy-list-initialization。
因此,您列出的选项是最佳选择
std::vector<std::variant<Struct2, Struct1>> v4{
Struct1{ 13 },
Struct2{ "someid", "someimage", "somename" }
};