使用"auto"推断嵌套初始值设定项列表的类型



我正在尝试使用auto自动推断嵌套std::initializer_list的类型。

auto list = {
{{ 0, 1}, { 2, 3 }},
{{ 4, 5}, { 6, 7 }},
};

这里的实际类型是std::initializer_list<std::initializer_list<std::initializer_list<int>>>,但是当我尝试编译它时,我收到一个错误,指出auto无法推断该类型。有没有办法让auto识别这样的结构?

我有一个程序,其中这些初始值设定项列表可以是任意大小和深度,因此硬编码类型是不切实际的。

附加信息:

我在这里找到了有关初始值设定项列表的文档:https://en.cppreference.com/w/cpp/language/list_initialization

大括号的初始化列表不是表达式,因此没有类型,例如decltype({1,2})格式不正确。没有类型意味着模板类型推导无法推断出与大括号初始化列表匹配的类型,因此给定声明template<class T> void f(T);表达式f({1,2,3})格式不正确。但是,模板参数也可以以其他方式推导,例如std::vector<int> v(std::istream_iterator<int>(std::cin), {}),其中迭代器类型由第一个参数推导,但也用于第二个参数位置。使用关键字 auto 进行类型推断有一个特殊的例外,它推断出任何大括号的初始化列表作为复制列表初始化中的std::initializer_list

文档似乎表明,使用auto进行类型推断有一个特殊的例外,所以你会认为这会起作用......但是,当您使用嵌套列表时,似乎auto无法推断出类型。

我有一个程序,其中这些初始值设定项列表可以是任意大小和深度,因此对类型进行硬编码是不切实际的。

然后你需要解决这个问题。

您不应该将大括号初始化列表视为一种快速而肮脏的方式来制作值数组,而不必考虑它们的类型。那不是他们的目的。它们的目的是初始化值。类型std::initializer_list旨在成为初始化某个类型的过程中的中间阶段(这就是为什么采用单个initializer_list的构造函数在列表初始化中被赋予特殊含义的原因(。

如果你想拥有不同深度的数组的数组数组等等,那么你将需要弄清楚该构造需要哪种类型并键入它。auto只能推导出一个级别的大括号初始化列表;如果需要更深层次,则需要显式指定类型。

使用auto进行类型扣除有一个特殊例外

是的,有。但它只适用于推导auto本身的清单,不适用于auto的推导需要的任何东西。

为了使auto list = {{1, 2, 3}};正常工作,编译器必须推断出两种类型:用于{1, 2, 3}的类型和用于list的类型。推导list的类型需要推导嵌套大括号初始化列表的类型。但是您无法推断出大括号初始化列表的类型。因此它不起作用。

还应该注意的是,即使它确实有效,它实际上也不会起作用。原因是list内部的initializer_list将引用临时数组。将在初始化表达式结束时销毁的临时数组。这基本上与string_view sv = std::string("foo");不能产生有用的东西的原因相同。

最新更新