使用lambda的multimap谓词

时间:2014-07-04 10:35:54

标签: c++ c++11 stl lambda

我正在尝试使用multimap对某些关系数据进行排序,但是在正确定义谓词时遇到了问题。

  std::multimap<
      std::vector<Message>, std::string,
      bool (*)(const std::vector<Message>, const std::vector<Message>)>
  sortmap([&](const std::vector<Message> &lhs,
              const std::vector<Message> &rhs) {
    return lhs.size() < rhs.size();
  });

这些类型似乎是正确的,但视觉工作室却说不然。

3 个答案:

答案 0 :(得分:4)

可以使用lambda代替函数指针,但lambda不是函数指针。因此,第三个模板参数的类型是错误的。

相反,您可以先定义lambda,然后使用例如decltype获取lambda类型。类似下面的代码:

auto comparator = [](const std::vector<Message>& lhs,
                     const std::vector<Message>& rhs) {
    return lhs.size() < rhs.size();
};

std::multimap<std::vector<Message>, std::string, decltype(comparator)> sortmap(comparator);

答案 1 :(得分:4)

比较器模板参数类型为

bool (*)(const std::vector<Message>, const std::vector<Message>)

而lambda可以衰变的类型是

bool (*)(const std::vector<Message>&, const std::vector<Message>&)

我建议你让multimap也在它的比较器参数中引用。

答案 2 :(得分:1)

我将介绍一些提到的选项:

选项1 @Joachim Pilborg

  auto comparator = [](const std::vector<Message>& lhs,
    const std::vector<Message>& rhs) {
    return lhs.size() < rhs.size();
  };

  std::multimap<std::vector<Message>, std::string, decltype(comparator)> sortmap(comparator);

  Message msg;
  std::vector<Message> messages;
  messages.push_back(msg);

  std::string str;
  auto test = std::make_pair(messages, str);

  sortmap.emplace(test);

结果

1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\xtree(1007): error C3497: you cannot construct an instance of a lambda
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\xtree(1006) : while compiling class template member function 'main::<lambda_2efe1f793bd1dfe8b84381ab9a3a87dc> std::_Tree_comp<false,_Traits>::_Getcomp(void) const'
1>          with
1>          [
1>              _Traits=std::_Tmap_traits<std::vector<Message,std::allocator<Message>>,std::string,main::<lambda_2efe1f793bd1dfe8b84381ab9a3a87dc>,std::allocator<std::pair<const std::vector<Message,std::allocator<Message>>,std::string>>,true>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\xtree(1789) : see reference to function template instantiation 'main::<lambda_2efe1f793bd1dfe8b84381ab9a3a87dc> std::_Tree_comp<false,_Traits>::_Getcomp(void) const' being compiled
1>          with
1>          [
1>              _Traits=std::_Tmap_traits<std::vector<Message,std::allocator<Message>>,std::string,main::<lambda_2efe1f793bd1dfe8b84381ab9a3a87dc>,std::allocator<std::pair<const std::vector<Message,std::allocator<Message>>,std::string>>,true>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\xtree(1024) : see reference to class template instantiation 'std::_Tree_comp<false,_Traits>' being compiled
1>          with
1>          [
1>              _Traits=std::_Tmap_traits<std::vector<Message,std::allocator<Message>>,std::string,main::<lambda_2efe1f793bd1dfe8b84381ab9a3a87dc>,std::allocator<std::pair<const std::vector<Message,std::allocator<Message>>,std::string>>,true>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\map(275) : see reference to class template instantiation 'std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,true>>' being compiled
1>          with
1>          [
1>              _Kty=std::vector<Message,std::allocator<Message>>
1>  ,            _Ty=std::string
1>  ,            _Pr=main::<lambda_2efe1f793bd1dfe8b84381ab9a3a87dc>
1>  ,            _Alloc=std::allocator<std::pair<const std::vector<Message,std::allocator<Message>>,std::string>>
1>          ]
1>          c:\users\c\documents\visual studio 2013\projects\project1\project1\source.cpp(15) : see reference to class template instantiation 'std::multimap<std::vector<Message,std::allocator<_Ty>>,std::string,main::<lambda_2efe1f793bd1dfe8b84381ab9a3a87dc>,std::allocator<std::pair<const _Kty,std::basic_string<char,std::char_traits<char>,std::allocator<char>>>>>' being compiled
1>          with
1>          [
1>              _Ty=Message
1>  ,            _Kty=std::vector<Message,std::allocator<Message>>
1>          ]

选项2 @PlasmaHH

  std::multimap<
      std::vector<Message>, std::string,
      bool (*)(const std::vector<Message> &, const std::vector<Message> &)>
  sortmap([&](const std::vector<Message> &lhs,
              const std::vector<Message> &rhs) {
    return lhs.size() < rhs.size();
  });
  Message msg;
  std::vector<Message> messages;
  messages.push_back(msg);

  std::string str;
  auto test = std::make_pair(messages, str);

  sortmap.emplace(test);

这个DOES编译,但奇怪的是在视觉工作室错误列表中留下了一个错误(并留下恼人的红色波形):

1   IntelliSense: no instance of constructor "std::multimap<_Kty, _Ty, _Pr, _Alloc>::multimap [with _Kty=std::vector<Message, std::allocator<Message>>, _Ty=std::string, _Pr=bool (*)(const std::vector<Message, std::allocator<Message>> &, const std::vector<Message, std::allocator<Message>> &), _Alloc=std::allocator<std::pair<const std::vector<Message, std::allocator<Message>>, std::string>>]" matches the argument list
        argument types are: (lambda []bool (const std::vector<Message, std::allocator<Message>> &lhs, const std::vector<Message, std::allocator<Message>> &rhs)->bool)  c:\Users\c\Documents\Visual Studio 2013\Projects\Project1\Project1\Source.cpp   12

}

我决定与

结婚
  auto comparator = [](const std::vector<Message> &lhs,
    const std::vector<Message> &rhs) {
    return lhs.size() < rhs.size();
  };
  std::multimap<std::vector<Message>, std::string,
    std::function<bool(const std::vector<Message> &,
    const std::vector<Message> &) >>
    sortmap(comparator);
  Message msg;
  std::vector<Message> messages;
  messages.push_back(msg);

  std::string str;
  auto test = std::make_pair(messages, str);

  sortmap.emplace(test);

选项1似乎不起作用:

https://connect.microsoft.com/VisualStudio/feedback/details/727957/vc11-beta-compiler-fails-to-compile-lambda-key-comparer-for-maps-and-sets

显式定义类型工作,并且由于某种原因使用std :: function使得(恼人的!!)红色波浪线和错误列表条目消失。希望这有帮助!