Tushar Jadhav
Tushar Jadhav

Reputation: 355

std::map with lambda comparator

My below code is giving me compiler error and I an not understanding what wrong I am doing. Can anyone help please?

Basically all I am trying to do is pass a STL map container by reference to a function which would fill it up. This map container also has a comparator lambda associated with it.

#include "stdafx.h"
#include <functional>
#include <map>

using namespace std;

typedef struct _tagAddressBook
{
  string strFirstName;
  string strLastName;
  long nZipCode;
} AddressBook;

void foo(map<string, AddressBook, function<bool(const string&, const string&)>> &myAddressBook)
{
  AddressBook addressBookInstance;
  addressBookInstance.strFirstName = "Bob";
  addressBookInstance.strLastName = "Parker";
  addressBookInstance.nZipCode = 12345;

  myAddressBook.insert(std::pair<string, AddressBook>(addressBookInstance.strFirstName, addressBookInstance));
}

int _tmain(int argc, _TCHAR* argv[])
{
  auto myComparator = [] (const string &strLeft, const string &strRight) { return(strLeft.compare(strRight) <= 0 ? true : false); };
  map<string, AddressBook, decltype(myComparator)> myAddressBook(myComparator);

  foo(myAddressBook);

    return 0;
}

I get the below compilation error on VS2012

Error 1 error C2664: 'foo' : cannot convert parameter 1 from 'std::map<_Kty,_Ty,_Pr>' to 'std::map<_Kty,_Ty,_Pr> &' d:\my projects\mapwithlambdacomparator\mapwithlambdacomparator\mapwithlambdacomparator.cpp 32

2   IntelliSense: a reference of type "std::map<std::string, AddressBook, std::function<bool (const std::string &, const std::string &)>, std::allocator<std::pair<const std::string, AddressBook>>> &" (not const-qualified) cannot be initialized with a value of type "std::map<std::string, AddressBook, lambda []bool (const std::string &strLeft, const std::string &strRight)->bool, std::allocator<std::pair<const std::string, AddressBook>>>" d:\My Projects\MapWithLambdaComparator\MapWithLambdaComparator\MapWithLambdaComparator.cpp  32

Upvotes: 1

Views: 4747

Answers (2)

DanielKO
DanielKO

Reputation: 4517

Please make an alias:

using AdressBookMap = map<string, AddressBook, function<bool(const string&, const string&)>>;

Then use it:

void foo(AddressBookMap& myAddressBook)
{
    // ...
}

int main(int argc, char* argv[])
{
    auto myComparator = [] (...) { ... };
    AddressBookMap myAddressBook(myComparator);

    foo(myAddressBook);

    return 0;
}

As Whoz said, lambdas are not std::function; the latter can be implicitly constructed from the former, but they don't have the same type. This means a std::map parametrized by one is completely unrelated to a std::map parametrized by the other.

Upvotes: 1

WhozCraig
WhozCraig

Reputation: 66194

Lambda functions are not related to std::function. In fact, each is its own class type. If you want to do what it appears you do, you can do it by template through foo and let deduction sort it out.

template <typename Cmp>
void foo(map<std::string, AddressBook, Cmp> &myAddressBook)
{
    AddressBook addressBookInstance;
    addressBookInstance.strFirstName = "Bob";
    addressBookInstance.strLastName = "Parker";
    addressBookInstance.nZipCode = 12345;

    myAddressBook.insert(std::pair<string, AddressBook>(addressBookInstance.strFirstName, addressBookInstance));
}

This works on my toolchain, "Apple LLVM version 5.0 (clang-500.2.75) (based on LLVM 3.3svn)". I see no reason it would not work with your toolchain as well.

Upvotes: 2

Related Questions