jeudi 28 janvier 2016

Cannot iterate over map whose elements hold a uniq_ptr

The following code fails to compile:

#include <iostream>
#include <memory>
#include <map>

struct HaveUniq {
    std::unique_ptr<int> uniq;
};

void print_hus(const std::map<int, HaveUniq>& hus) {
    for (const std::pair<int, HaveUniq>& p: hus)
        std::cout << *p.second.uniq << std::endl;
}

int main() {
    std::map<int, HaveUniq> hus;
    for (int i = 0; i < 10; ++i)
        hus[i].uniq = std::unique_ptr<int>(new int(i));
    print_hus(hus);
}

With the following error:

uniq_wtf.cpp: In function ‘void print_hus(const std::map<int, HaveUniq>&)’:
uniq_wtf.cpp:10:42: error: invalid initialization of reference of type 
‘const std::pair<int, HaveUniq>&’ from expression of type
‘const std::pair<const int, HaveUniq>’
for (const std::pair<int, HaveUniq>& p: hus)

So, it tries to iterate over values rather than constant references, and it cannot coerce those values into references.

It is clear that an objects that has a unique_ptr as one of its fields cannot have a default copying constructor. But if I understand correctly, iterating over a map doesn't involve copying, so it shouldn't be a problem. Or does the map iterator actually copy the values? And why would it have problem with coercing values to references?

By the way, the code works if the unique_ptr is replaced with simple integer, and if the map is replaced with std::array.

Aucun commentaire:

Enregistrer un commentaire