joe_specimen
joe_specimen

Reputation: 355

"error C2678: binary '=' : no operator found which takes a left-hand operand of type..." when using lambda function for map filtering

I have written (partailly copied :) ) the following code: HigherOrderFunctions.h :

#ifndef HigherOrderFunctions_H
#define HigherOrderFunctions_H

#include <algorithm>

class HigherOrderFunctions {
public:
   template<class Coll, class Func>
   static Coll& filter(Coll& items, Func&& filterFunc);
private:
   HigherOrderFunctions() {}
};

template < class Coll, class Func>
Coll& HigherOrderFunctions::filter(Coll& items, Func&& filterFunc) {
   auto first = std::find_if_not(items.begin(), items.end(), filterFunc);
   const auto last = items.end();
   if (first != last) {
      for(auto it = first; ++it != last; ) {
         if (filterFunc(*it)) {
            *first++ = std::move(*it);
         }
      }
   }
   items.erase(first, items.end());
   return items;
}

#endif // HigherOrderFunctions_H

Now when I try to test the above code with the test function:

void HighOrderFunctionsTest::testFilter() {
   vector<int> integers = {1, 2, 3, 4, 5, 6, 7};
   HigherOrderFunctions::filter(integers, [](int elem) -> bool {
      return (elem % 2) == 0;
   });

   const int ADULT_AGE = 18;
   map<string, int> name_age_list = {{"sm", 10}, {"ak", 20}, {"al", 30}, {"am", 35}};
   function<bool(const pair<string, int>&)> funct = [ADULT_AGE](const pair<string, int>& elem) -> bool {
      return (elem.second > ADULT_AGE);
   };

   HigherOrderFunctions::filter(name_age_list, funct);
}

The part where I filter the vector compiles OK, but when I add the part with map I get the following compile error (using MSVS 2013):

HighOrderFunctionsTest.cpp
2>C:\winapp\MSVS2013PRO\VC\include\utility(175): error C2678: binary '=' : no operator found which takes a left-hand operand of type 'const std::string' (or there is no acceptable conversion)
2>          C:\winapp\MSVS2013PRO\VC\include\xstring(1017): could be 'std::basic_string<char,std::char_traits<char>,std::allocator<char>> &std::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator =(_Elem)'
2>          with
2>          [
2>              _Elem=char
2>          ]
2>          C:\winapp\MSVS2013PRO\VC\include\xstring(1012): or       'std::basic_string<char,std::char_traits<char>,std::allocator<char>> &std::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator =(const _Elem *)'
2>          with
2>          [
2>              _Elem=char
2>          ]
2>          C:\winapp\MSVS2013PRO\VC\include\xstring(996): or       'std::basic_string<char,std::char_traits<char>,std::allocator<char>> &std::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator =(const std::basic_string<char,std::char_traits<char>,std::allocator<char>> &)'
2>          C:\winapp\MSVS2013PRO\VC\include\xstring(957): or       'std::basic_string<char,std::char_traits<char>,std::allocator<char>> &std::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator =(std::initializer_list<_Elem>)'
2>          with
2>          [
2>              _Elem=char
2>          ]
2>          C:\winapp\MSVS2013PRO\VC\include\xstring(901): or       'std::basic_string<char,std::char_traits<char>,std::allocator<char>> &std::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator =(std::basic_string<char,std::char_traits<char>,std::allocator<char>> &&) throw()'
2>          while trying to match the argument list '(const std::string, const std::string)'
2>          C:\winapp\MSVS2013PRO\VC\include\utility(174) : while compiling class template member function 'std::pair<const _Kty,_Ty> &std::pair<const _Kty,_Ty>::operator =(std::pair<const _Kty,_Ty> &&)'
2>          with
2>          [
2>              _Kty=std::string
2>  ,            _Ty=int
2>          ]
2>          D:\tax\tax_win\tc\src\cpp\foundation\HigherOrderFunctions.h(219) : see reference to function template instantiation 'std::pair<const _Kty,_Ty> &std::pair<const _Kty,_Ty>::operator =(std::pair<const _Kty,_Ty> &&)' being compiled
2>          with
2>          [
2>              _Kty=std::string
2>  ,            _Ty=int
2>          ]
2>          ..\..\..\..\..\..\src\cpp\foundation\test\HighOrderFunctionsTest.cpp(33) : see reference to class template instantiation 'std::pair<const _Kty,_Ty>' being compiled
2>          with
2>          [
2>              _Kty=std::string
2>  ,            _Ty=int
2>          ]

I have looked for similar errors and I found out that this could happen if my function where the code is called would be const, but it is not. Can you please help me with this problem?

Upvotes: 0

Views: 1386

Answers (1)

user7860670
user7860670

Reputation: 37600

The problem is cause by *first++ = std::move(*it); line. When container is a map then stored items will be of type pair<const Key, Value>. De-referencing iterator will yield a reference to such a type and any attempt to perform move assignment to it will fail because the value of Key can not be changed.

I think the key issue with this code is that filter function is supposed to produce a new container with filtered values, not mutate supplied container. Currently implemented algorithm seems to be working similar to std::remove_if.

Upvotes: 2

Related Questions