使用 "auto" 推断嵌套初始化列表的类型
Using "auto" to deduce the type of a nested initializer list
我正在尝试使用 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
A braced-init-list is not an expression and therefore has no type, e.g. decltype({1,2})
is ill-formed. Having no type implies that template type deduction cannot deduce a type that matches a braced-init-list, so given the declaration template<class T> void f(T);
the expression f({1,2,3})
is ill-formed. However, the template parameter can otherwise be deduced, as is the case for std::vector<int> v(std::istream_iterator<int>(std::cin), {})
, where the iterator type is deduced by the first argument but also used in the second parameter position. A special exception is made for type deduction using the keyword auto , which deduces any braced-init-list as std::initializer_list
in copy-list-initialization.
文档似乎表明使用 auto
进行类型推导有一个特殊的例外,所以你会认为这会起作用......但似乎当你使用嵌套列表时 auto
无法推断类型。
I have a program where these initializer lists could be of arbitrary sizes and depths so hardcoding the types is not practical.
那么你需要解决这个问题。
您不应该将花括号初始化列表视为一种无需考虑其类型即可创建值数组的快捷方式。那不是他们的目的。它们的目的是初始化值。类型 std::initializer_list
旨在成为初始化某些类型过程中的中间阶段(这就是为什么采用单个 initializer_list
的构造函数在列表初始化中被赋予特殊含义)。
如果您想拥有各种深度的数组等数组,那么您将需要弄清楚该构造需要是哪种类型并将其键入。 auto
只能推导出单层braced-init-list;如果您需要更深层次,则需要明确指定类型。
there is a special exception made for type deduction using auto
是的,有。但它仅适用于推导 auto
本身 的列表,不适用于 auto
推导所需的任何内容。
为了 auto list = {{1, 2, 3}};
工作,编译器必须推断出 两种类型 :要用于 {1, 2, 3}
的类型和将要使用的类型用于 list
。推导 list
的类型需要推导嵌套的 braced-init-list 的类型。但是你不能 推断出花括号初始化列表的类型。因此它不起作用。
还应该注意的是,即使它确实有效,实际上也不会 有效。原因是 list
内部的 initializer_list
将引用一个临时数组。将在初始化表达式结束时销毁的临时数组。这与 string_view sv = std::string("foo");
没有产生有用的东西的原因基本相同。
我正在尝试使用 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
A braced-init-list is not an expression and therefore has no type, e.g.
decltype({1,2})
is ill-formed. Having no type implies that template type deduction cannot deduce a type that matches a braced-init-list, so given the declarationtemplate<class T> void f(T);
the expressionf({1,2,3})
is ill-formed. However, the template parameter can otherwise be deduced, as is the case forstd::vector<int> v(std::istream_iterator<int>(std::cin), {})
, where the iterator type is deduced by the first argument but also used in the second parameter position. A special exception is made for type deduction using the keyword auto , which deduces any braced-init-list asstd::initializer_list
in copy-list-initialization.
文档似乎表明使用 auto
进行类型推导有一个特殊的例外,所以你会认为这会起作用......但似乎当你使用嵌套列表时 auto
无法推断类型。
I have a program where these initializer lists could be of arbitrary sizes and depths so hardcoding the types is not practical.
那么你需要解决这个问题。
您不应该将花括号初始化列表视为一种无需考虑其类型即可创建值数组的快捷方式。那不是他们的目的。它们的目的是初始化值。类型 std::initializer_list
旨在成为初始化某些类型过程中的中间阶段(这就是为什么采用单个 initializer_list
的构造函数在列表初始化中被赋予特殊含义)。
如果您想拥有各种深度的数组等数组,那么您将需要弄清楚该构造需要是哪种类型并将其键入。 auto
只能推导出单层braced-init-list;如果您需要更深层次,则需要明确指定类型。
there is a special exception made for type deduction using
auto
是的,有。但它仅适用于推导 auto
本身 的列表,不适用于 auto
推导所需的任何内容。
为了 auto list = {{1, 2, 3}};
工作,编译器必须推断出 两种类型 :要用于 {1, 2, 3}
的类型和将要使用的类型用于 list
。推导 list
的类型需要推导嵌套的 braced-init-list 的类型。但是你不能 推断出花括号初始化列表的类型。因此它不起作用。
还应该注意的是,即使它确实有效,实际上也不会 有效。原因是 list
内部的 initializer_list
将引用一个临时数组。将在初始化表达式结束时销毁的临时数组。这与 string_view sv = std::string("foo");
没有产生有用的东西的原因基本相同。