无法在cbegin中定义initializer_list

时间:2018-05-17 15:54:55

标签: c++ constructor iterator initializer-list explicit

所以我可以这样做:

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, " "));

Live Example

2 个答案:

答案 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 listauto会将{ 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>