Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uniform initialization of iterators

I am very new to C++11 and there is a problem with iterators and uniform initialization, which I do not understand.

Consider the following example, which does not compile:

#include <iostream>
#include <vector>

int main() {

    std::vector<int> t{1, 2, 3, 4, 5};
    auto iter{t.begin()};                   

    for (; iter != t.end(); ++iter) {
        std::cout << *iter;
    }

    return 0;
}

In line 6 a vector is initialized using uniform initialization. In line 7 I try to do the same with an iterator. It does not work. Changing line 7 to auto iter = t.begin() is ok. I know I could simply use "range based for" for this, but the question is: Why does uniform initialization not work with iterators but is fine with basic types, like int i{0}; ?

like image 443
MaxPowers Avatar asked Mar 20 '23 08:03

MaxPowers


2 Answers

When you use an initializer-list as the initializer with auto, the variable declared is deduced as an initializer list. In other words, iter is declared as std::initializer_list<vector<int>::iterator>, and not vector<int>::iterator as you might expect.

Changing it to auto iter = t.begin() is the best way to proceed.

like image 137
Brian Bi Avatar answered Apr 01 '23 14:04

Brian Bi


C++11 has a special rule for auto and braced initialization which is inferred to std::initializer_list. In your case your choices are one of the following:

auto iter(t.begin());
auto iter = t.begin();

The behavior is described at:

§7.1.6.4/7 auto specifier [dcl.spec.auto]

Let T be the declared type of the variable or return type of the function. If the placeholder is the auto type-specifier, the deduced type is determined using the rules for template argument deduction. If the deduction is for a return statement and the initializer is a braced-init-list (8.5.4), the program is ill-formed. Otherwise, obtain P from T by replacing the occurrences of auto with either a new invented type template parameter U or, if the initializer is a braced-init-list, with std::initializer_- list. Deduce a value for U using the rules of template argument deduction from a function call (14.8.2.1), where P is a function template parameter type and the initializer is the corresponding argument. If the deduction fails, the declaration is ill-formed. Otherwise, the type deduced for the variable or return type is obtained by substituting the deduced U into P.

(emphasis mine).

Scott Meyer has recently presented a talk about this very problem. I'd recommend watching the video.

like image 45
Shoe Avatar answered Apr 01 '23 13:04

Shoe