我可以将Brad-Init-list用于STD ::变体的向量吗?



i有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;

一切正常工作,直到我尝试使用Brad-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>)

我不明白这是为什么。在这种情况下,我不能使用支撑初始化吗?如果是这样,...为什么?还是我需要以某种方式修改我的结构以支持这种初始化?

这是wandbox.org上的最小工作示例,以进一步说明我的问题。

在这种情况下,我不能使用支架初始化吗?如果是这样,...为什么?还是我需要以某种方式修改我的结构以支持这种初始化?

不,你不能。不,您无法做出任何改变以使其正常工作。这是一个非常简单的示例:

template <typename T> void foo(T&& );
foo({1}); // what is T?

支撑列表没有类型,因此不能推导它们。variant的构造函数的工作方式是推论其参数,然后选择最佳替代品以初始化。它不能从您的支撑列表中做到这一点,您必须使用具有类型的表达式。

唯一可以使工作的方法是variant<A, B, C>本身具有 non-Template 构造函数variant(A&& )variant(B&& )variant(C&& )。然后,,支撑式列表将起作用。

您打算致电的variant构造函数是

template<typename T>
constexpr variant(T&& t)

但是该构造函数模板的模板参数扣除将失败,因为 braced-init-lists 没有类型。

使用将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,该构建器不适合用于复制列表initialization。

所以您列出的选项是最好的

std::vector<std::variant<Struct2, Struct1>> v4{
     Struct1{ 13 },
     Struct2{ "someid", "someimage", "somename" }
};

最新更新