vendredi 28 septembre 2018

Why can't I use a lambda in a std::map constructor?

I am currently working on a program for which I must create a map to store data using a specific key. Although a strict weak ordering is possible for that key, the ordering has no meaning relative to the meaning of the key. As such, I decided to give my map a comparator lambda instead of overriding operator< on my key type. When I do this, however, I get a plethora of compile errors that seem to boil down to the idea that a lambda can not be converted into the type that the compiler requires. Why is this?

Minimum complete verifiable example:

#include <iostream>

#include <map>

struct CustomClass{
    unsigned a;
};

int main(){
    std::map<CustomClass, int> bad_map([](const CustomClass &a, const CustomClass &b){ return a.a < b.a; });
}

Clang 6.0.1 errors on Linux:

$ clang++ bug.cpp -o bug
bug11.cpp:9:29: error: no matching constructor for initialization of 'std::map<CustomClass, int>'
        std::map<CustomClass, int> bad_map([](const CustomClass &a, const CustomClass &b){ return a.a < b.a; });
                                   ^       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../include/c++/8.2.1/bits/stl_map.h:192:7: note: candidate constructor not viable: no known conversion from '(lambda at bug11.cpp:9:37)' to
      'const std::less<CustomClass>' for 1st argument
      map(const _Compare& __comp,
      ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../include/c++/8.2.1/bits/stl_map.h:205:7: note: candidate constructor not viable: no known conversion from '(lambda at bug11.cpp:9:37)' to 'const
      std::map<CustomClass, int, std::less<CustomClass>, std::allocator<std::pair<const CustomClass, int> > >' for 1st argument
      map(const map&) = default;
      ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../include/c++/8.2.1/bits/stl_map.h:213:7: note: candidate constructor not viable: no known conversion from '(lambda at bug11.cpp:9:37)' to
      'std::map<CustomClass, int, std::less<CustomClass>, std::allocator<std::pair<const CustomClass, int> > >' for 1st argument
      map(map&&) = default;
      ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../include/c++/8.2.1/bits/stl_map.h:226:7: note: candidate constructor not viable: no known conversion from '(lambda at bug11.cpp:9:37)' to
      'initializer_list<std::map<CustomClass, int, std::less<CustomClass>, std::allocator<std::pair<const CustomClass, int> > >::value_type>' (aka 'initializer_list<pair<const CustomClass, int> >') for
      1st argument
      map(initializer_list<value_type> __l,
      ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../include/c++/8.2.1/bits/stl_map.h:234:7: note: candidate constructor not viable: no known conversion from '(lambda at bug11.cpp:9:37)' to 'const
      std::map<CustomClass, int, std::less<CustomClass>, std::allocator<std::pair<const CustomClass, int> > >::allocator_type' (aka 'const std::allocator<std::pair<const CustomClass, int> >') for 1st
      argument
      map(const allocator_type& __a)
      ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../include/c++/8.2.1/bits/stl_map.h:254:2: note: candidate constructor template not viable: requires 3 arguments, but 1 was provided
        map(_InputIterator __first, _InputIterator __last,
        ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../include/c++/8.2.1/bits/stl_map.h:271:2: note: candidate constructor template not viable: requires 2 arguments, but 1 was provided
        map(_InputIterator __first, _InputIterator __last)
        ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../include/c++/8.2.1/bits/stl_map.h:288:2: note: candidate constructor template not viable: requires at least 3 arguments, but 1 was provided
        map(_InputIterator __first, _InputIterator __last,
        ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../include/c++/8.2.1/bits/stl_map.h:183:7: note: candidate constructor not viable: requires 0 arguments, but 1 was provided
      map() = default;
      ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../include/c++/8.2.1/bits/stl_map.h:238:7: note: candidate constructor not viable: requires 2 arguments, but 1 was provided
      map(const map& __m, const allocator_type& __a)
      ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../include/c++/8.2.1/bits/stl_map.h:242:7: note: candidate constructor not viable: requires 2 arguments, but 1 was provided
      map(map&& __m, const allocator_type& __a)
      ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../include/c++/8.2.1/bits/stl_map.h:248:7: note: candidate constructor not viable: requires 2 arguments, but 1 was provided
      map(initializer_list<value_type> __l, const allocator_type& __a)
      ^
1 error generated.

Aucun commentaire:

Enregistrer un commentaire