0

I am trying to sort a vector that contains custom struct entries using a lambda function in c++ . But I get prompted the following error message

error: use of deleted function ‘dummy_struct& dummy_struct::operator=(const dummy_struct&)

The code looks like the following:

#include <regex>

struct dummy_struct
{
    dummy_struct(std::string name, int64_t value_a) :
        name(name),
        value_a(value_a)
    {}
    
    const std::string name;
    const int64_t value_a;
    
    int ExtractNumberFromName(std::regex key)
    {
        int retval;
        std::cmatch match;
        std::regex_search(this->name.c_str(),match,key);
        retval=std::stoi(match[0],nullptr);
        return retval;
    }
    
};


void SortByCustomKey(const std::vector<dummy_struct> collection, std::regex key)
{

    auto compare = [key](dummy_struct a, dummy_struct b)
    {
        return a.ExtractNumberFromName(key) > b.ExtractNumberFromName(key)
    };
    
    std::sort(std::begin(collection),std::end(collection),compare);

}

int main()
{

    std::vector<dummy_struct> test;
    
    test.push_back(dummy_struct("Entry[1]",1));
    test.push_back(dummy_struct("Entry[2]",2));
    test.push_back(dummy_struct("Entry[3]",3));
    
    SortByCustomKey(test,std::regex("[0-9]+"));
}

What am I missing here?

ex1led
  • 427
  • 5
  • 21
  • 3
    all your fields are `const` so how assignment could do anything? One `const` field is enough to prevent compiler from generating default implementation of assignment operator. – Marek R Mar 23 '21 at 13:06
  • 1
    You should pass non-trivial parameters by references, currently your sort works on a copy of the `test` vector. – Quimby Mar 23 '21 at 13:07
  • @MarekR I used the ```const``` notation because the fields shall not be changed once initialized. Does this mean that by invoking the ```sort``` I am creating issues due to values being changed? – ex1led Mar 23 '21 at 13:10
  • See [doc of std::sort](https://en.cppreference.com/w/cpp/algorithm/sort): `The type of dereferenced RandomIt must meet the requirements of MoveAssignable and MoveConstructible.` – Marek R Mar 23 '21 at 13:12
  • If the fields shall not be changed under any circumstances, how would copy or move assignment be possible? – Ted Lyngmo Mar 23 '21 at 13:12
  • You can also check a similar post [here.](https://stackoverflow.com/questions/5966698/error-use-of-deleted-function/5966859) – S.Seba Mar 23 '21 at 13:12
  • @MarekR so this means, that if I use a ```const``` at any point in my struct fields, I cannot use functions like e.g., ```std::sort``` due to these criteria being not met. So the solution is to mark the fields as non ```const``` ? – ex1led Mar 23 '21 at 13:18
  • 1
    @Broxigar Correct. `const` member variables are painful :-) Just make them `private` and don't change them - unless copy or move assignment is being done. – Ted Lyngmo Mar 23 '21 at 13:22
  • I see. Much appreciated guys. @TedLyngmo yes...they are.......... – ex1led Mar 23 '21 at 13:24
  • @Broxigar yes and no. If you have one `const` filed then compiler will not generate default assign operator, but it is possible to define own assign operator. In your context it doesn't make seance, so just drop `const`. – Marek R Mar 23 '21 at 13:36

1 Answers1

3

std::sort sorts vector by swapping it's elements in place.

This requires for your class to implement copy assignment operator (or move assignment), which compiler won't generate for you due to const fields in the class. For your example the only solution seems to remove the const qualifiers from the fields. If you don't want them to be modified just make them private and don't provide (public) setters. If they absolutely must stay there and you just want to get your values in sorted order you can use a different structure or store pointers in the vector.

Another solution is to write a custom swap implementation for your class that would const_cast away the qualifiers of the fields for the purpose of the assignment, although this is usually a bad code smell.

Dan M.
  • 3,818
  • 1
  • 23
  • 41