Home > Net >  Problem with some hidden == operand when erasing shared_ptr from a vector
Problem with some hidden == operand when erasing shared_ptr from a vector

Time:10-11

I wrote this AddressBook program in C as an exercise, and everything works fine except the removeContact method.
The compiler (MSVC) reports an issue related, I think, to some sort of incompatible right operand with a == operator. Here's the compiler output:

error C2679: binary '==': no operator found which takes a right-hand operand of type 'std::shared_ptr<Contact>' (or there is no acceptable conversion)  
note: could be 'bool std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<_Ty>>>::operator ==(const std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<_Ty>>> &) noexcept const' [synthesized expression 'y == x']  
   with  
        [  
            _Ty=Database::ContactPtr  
        ]  
note: while trying to match the argument list '(std::shared_ptr<Contact>, const _Ty)'  
 with  
        [        
 _Ty=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<Database::ContactPtr>>>  
        ]  
note: see reference to function template instantiation '_FwdIt std::remove<std::shared_ptr<Contact>*,_Uty>(_FwdIt,const _FwdIt,const _Ty &)' being compiled  
        with  
        [  
            _FwdIt=std::shared_ptr<Contact> *,  
_Uty=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<Database::ContactPtr>>>,
            _Ty=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<Database::ContactPtr>>>  
        ]  
note: see reference to function template instantiation 'unsigned int  std::_Erase_remove<std::vector<Database::ContactPtr,std::allocator<Database::ContactPtr>>,_Uty>(_Container &,const _Uty &)' being compiled  
        with  
        [  
_Uty=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<Database::ContactPtr>>>,  
            _Container=std::vector<Database::ContactPtr,std::allocator<Database::ContactPtr>>  
        ]  
note: see reference to function template instantiation 'unsigned int  std::erase<Database::ContactPtr,std::allocator<Database::ContactPtr>,std::_Vector_iterator<std::_Vector_val<std::_Simple_types<_Ty>>>>(std::vector<_Ty,std::allocator<_Ty>> &,const _Uty &)' being compiled  
        with  
        [  
            _Ty=Database::ContactPtr,  
_Uty=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<Database::ContactPtr>>> 

I don't know if the issue is something really simple, but this report is cryptic. Here's the code:

#include "Database.h"
#include "ContactNotFoundException.h"

void Database::addContact(const Contact &contact) {
    contacts.push_back(std::make_shared<Contact>(contact));
}

void Database::removeContact(const Contact &contact) {
    removeContact(findContact(contact.getName()));
}

void Database::removeContact(std::string_view name) {
    removeContact(findContact(name));
}

void Database::removeContact(const size_t index) {
    auto iterator{contacts.begin()};
    iterator  = static_cast<int>(contacts.size() - index);
    std::erase(contacts, iterator);
}

size_t Database::findContact(std::string_view name) const {
    // TODO: algorithm
    for (size_t i = 0; i < contacts.size();   i) {
        if (contacts.at(i)->getName() == name)
            return i;
    }
    throw ContactNotFoundException();
}

Database::ContactPtr Database::getContact(std::string_view name) const {
    return contacts.at(findContact(name));
}

void Database::listContacts() const {
    for (const auto& contactPtr : contacts) {
        std::cout << contactPtr->getName() << std::endl;
    }
}

I also have to clarify that I put the compiler output in a code block because StackOverflow wouldn't let me post the answer, as it detects it as code.

CodePudding user response:

std::erase takes a value which is searched in your container and then removed, not an iterator.

Therefore trying to pass an iterator there triggers an error because std::erase is trying to compare your container elements with this iterator, but iterators and elements are normally not comparable.

To erase an element you already have an iterator for, you need contacts.erase(iterator) instead.

  • Related