简体   繁体   中英

C++ iterating std::accumulate() over a map of unique_ptr: no known conversion

This is probably a case of Friday afternoon blindness... why is the accumulation over the map not working. It hands me a compile error

main.cpp:35:80: note:   no known conversion for argument 2 from ‘std::pair, std::unique_ptr >’ to ‘const std::pair, std::unique_ptr >&’

What is wrong with this cast?

#include <vector>
#include <map>
#include <memory>
#include <numeric>
#include <iostream>

using namespace std;

struct Foo
{
    long bar() const {return 1;}
};


int main()
{

    std::vector<std::unique_ptr<Foo>> v;

    auto baz = [](long x, const std::unique_ptr<Foo>& p){return x + p->bar();};

    std::accumulate(v.begin(), v.end(), 0L, baz);



    std::map<std::string, std::unique_ptr<Foo>> m;

    auto bam = [](long x, const std::pair<std::string, std::unique_ptr<Foo>>& p) {
        return x + p.second->bar();
    };

    std::accumulate(m.begin(), m.end(), 0L, bam);


    return 0;
}

The value_type of std::map is std::pair<const Key, T> ; note that the key is qualified as const . So for std::map<std::string, std::unique_ptr<Foo>> the value_type is std::pair<const std::string, std::unique_ptr<Foo>> , but not std::pair<std::string, std::unique_ptr<Foo>> . Because of std::unique_ptr , a temporary std::pair<const std::string, std::unique_ptr<Foo>> can't be copy-constructed from std::pair<std::string, std::unique_ptr<Foo>> (and bound to parameter p with type of reference to const ).

You can change the lambda's parameter's type to match the value_type exactly, then the argument could be bound directly.

auto bam = [](long x, const std::pair<const std::string, std::unique_ptr<Foo>>& p) {
//                                    ^^^^^
    return x + p.second->bar();
};

You can also use member types of std::map like value_type or const_reference .

auto bam = [](long x, const std::map<std::string, std::unique_ptr<Foo>>::value_type& p) {
    return x + p.second->bar();
};

auto bam = [](long x, std::map<std::string, std::unique_ptr<Foo>>::const_reference p) {
    return x + p.second->bar();
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM