所以我可以这样做:
for(const auto i : { 13, 42 }) cout << i << ' ';
但我不能这样做:
copy_n(cbegin({ 13, 42 }), 2, ostream_iterator<int>(cout, " "));
它给了我错误:
错误:没有匹配函数来调用
cbegin(<brace-enclosed initializer list>)
for
- 允许这个而不是cbegin
函数的语句有什么用?
修改
问题似乎是我的initializer_list
没有被视为initializer_list
,因为如果我这样做就行了:
copy_n(cbegin(initializer_list<int>{ 13, 42 }), 2, ostream_iterator<int>(cout, " "));
答案 0 :(得分:2)
{ 13, 42 }
是支持初始化列表。它没有类型,它只是一个列表,它取决于它如何被处理。 std::cbegin
定义为
template< class C >
constexpr auto cbegin( const C& c ) -> decltype(std::begin(c));
由于支持的初始化列表没有类型,因此模板类型推断失败。在基于范围的for循环中,我们使用不同的列表。基于for循环的范围扩展为
{
init-statement
auto && __range = range_expression ;
auto __begin = begin_expr ;
auto __end = end_expr ;
for ( ; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
auto && __range = range_expression ;
成为auto && __range = { 13, 42 }
。现在auto
遵循模板类型扣除,但由于委员会决定auto
should work with braced initializer list,auto
会将{ 13, 42 }
推断为std::initiaizer_list<int>
,因为该列表仅包含{{1} }}第
如果您将代码更改为
int
即使copy_n(begin({ 13, 42 }), 2, ostream_iterator<int>(cout, " "));
定义为std::begin
并采用模板类型,cbegin
introduces an overload也需要<initializer_list>
,而且会被调用。< / p>
答案 1 :(得分:1)
初始化列表仅存储指向原始列表的指针,并且根据设计,它不允许用户修改数据,即
const T* begin(); // returns a constant object
因此begin
成员或begin
免费功能相当于cbegin
。这就是为什么只有begin
存在。
<强>更新强>
关于cbegin(std::initializer_list<int>...
:这是有效的,因为你明确指定了类型,而cbegin(const Container&...
实际上是一个模板函数,begin(std::initializer_list<U>...
是一个不同的模板函数,正如我在第一部分中所说的那样答案是没有cbegin(std::initializer_list<U>...
功能。
解决部分是你不能做“链式”模板演绎,它没有意义:Container -> std::initializer_list<U> -> std::initializer_list<int>
。两种推论中只有一种可能存在,Container -> std::initializer_list<int>
或std::initializer_list<U> -> std::initializer_list<int>