简体   繁体   English

使用lambda的多图谓词

[英]multimap predicate using lambda

I am trying to sort some relational data using a multimap but am having issues getting the predicate defined correctly. 我正在尝试使用多图对一些关系数据进行排序,但是在正确定义谓词时遇到了问题。

  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();
  });

The types seem to be correct but visual studio says otherwise. 这些类型似乎是正确的,但Visual Studio则相反。

A lambda can be used in place of a function pointer, but a lambda is not a function pointer. 可以使用lambda代替函数指针,但是lambda不是函数指针。 Therefore the type of the third template argument is wrong. 因此,第三个模板参数的类型是错误的。

Instead you could define the lambda first, and use eg decltype to get the lambda type. 相反,您可以先定义lambda,然后使用例如decltype来获取lambda类型。 Something like the following code: 类似于以下代码:

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);

Your comparator template parameter type is 您的比较器模板参数类型为

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

while the type the lambda can decay to is 而lambda可以衰减的类型是

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

I suggest you make the multimap take references in its comparator parameter too. 我建议您也使多图在其比较器参数中也采用引用。

I'll go through some of the options mentioned: 我将介绍一些提到的选项:

Option 1 @Joachim Pilborg 选项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);

results in 结果是

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>          ]

Option 2 @PlasmaHH 选项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);

This DOES compile, but strangely leaves an error in visual studios error list (and leaves an annoying red squiggle): 确实可以编译,但是奇怪的是在Visual Studio错误列表中留下了一个错误(并留下了一个令人讨厌的红色花体):

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

} }

I instead settle with 我反而与

  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);

Option 1 appears not to work: 选项1似乎无效:

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

explicitly defining the type works, and using std::function for some reason makes the (annoying!!) red squiggle and error list entry go away. 显式定义该类型有效,并且出于某种原因使用std :: function会使(烦人的!)红色花键和错误列表条目消失。 Hope this helps! 希望这可以帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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