Не могу определить initializer_list в cbegin - PullRequest
0 голосов
/ 17 мая 2018

Так что я могу сделать это:

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?

Edit:

Похоже, проблема в том, что мой initializer_list не рассматривается как initializer_list, потому что, если я делаю это, он работает:

copy_n(cbegin(initializer_list<int>{ 13, 42 }), 2, ostream_iterator<int>(cout, " "));

Живой пример

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Инициализатор списка хранит только указатели на исходный список, и по своей конструкции он не позволяет пользователю изменять данные, т.е.

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>

0 голосов
/ 17 мая 2018

{ 13, 42 } - список инициализированных фигурных скобок.У него нет типа, это просто список, и это зависит от того, как он используется и как с ним обращаются.std::cbegin определяется как

template< class C > 
constexpr auto cbegin( const C& c ) -> decltype(std::begin(c));

, и поскольку список инициализированных фигурных скобок не имеет типа, вывод типа шаблона завершается ошибкой.В ранжированном цикле 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 должен работать со списком инициализированных фигурных скобок , auto выведет { 13, 42 } в std::initiaizer_list<int>, поскольку список содержит только int с.


Если вы измените код на

copy_n(begin({ 13, 42 }), 2, ostream_iterator<int>(cout, " "));

, хотя std::begin определен как cbegin и принимает тип шаблона, <initializer_list> вводит перегрузку , которая занимает std::initializer_list и вместо этого вызывается.

...