0

I am fairly new to C++ especially when it comes to using iterators with class vectors.

I am trying to create a function that would verify the user username/password on login through searching a vector that contains all the class objects (users) and matching it with the input. However, I am getting this error:

binary '==': 'userInfo' does not define this operator or a conversion to a type acceptable to the predefined operator

I was trying to find solutions online and I was told that that error is associated with an iterator being used incorrectly. Here's my function code:

void userInfo::VerifyUser()
{
    std::string tempusername = get_input < std::string >("CONSOLE: Please insert your username");
    std::vector<userInfo>::iterator user = std::find(m_allUsers.begin(), m_allUsers.end(), [&tempusername](userInfo& profile) {return profile.get_username() == tempusername; });
    {
        if (user != m_allUsers.end())
        {
            int choice = get_input<int>("CONSOLE: Username already exists - 0 to login and 1 to register");
            if (choice == 0)
            {
                std::string temppassword = get_input < std::string >("CONSOLE: Please insert your password to login");
                std::vector<userInfo>::iterator pass = std::find(m_allUsers.begin(), m_allUsers.end(), [&tempusername]( userInfo& profile) {return profile.get_username() == tempusername; });
                if (pass != m_allUsers.end())
                {
                    while (!(VerifyPassword(tempusername, temppassword)))
                    {
                        std::string temppassword = get_input < std::string >("CONSOLE: Please insert your password to login");
                        std::vector<userInfo>::iterator pass = std::find(m_allUsers.begin(), m_allUsers.end(), [&tempusername](userInfo& profile) {return profile.get_password() == tempusername; });
                    }

                    std::cout << "SUCESS: You have entered the correct information - logging you in." << std::endl;
                    userInfo profile(tempusername, temppassword, 1, 0);
                }
            }
            else if (choice == 1)
            {
                VerifyUser();
            }
        }
        else
        {
            std::cout << "CONSOLE: Username does not exist in the database - redirecting to registeration menu." << std::endl;
            userInfo().register_user();
        }
    }
}

bool userInfo::VerifyPassword(std::string username, std::string password)
{
    std::string tempuser;
    std::string temppass;
    std::string file_name = username + ".txt";
    std::fstream file(file_name);
    while (!file.eof())
    {
        file >> tempuser;
        file >> temppass;
    }
    if (temppass == password)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}

EDIT: Full error output:

Severity    Code    Description Project File    Line    Suppression State
Error   C2446   '==': no conversion from 'const _Ty' to 'userInfo'  Database (Project 1)    C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\include\xutility    4640    
Error   C2446   '==': no conversion from 'const _Ty' to 'userInfo'  Database (Project 1)    C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\include\xutility    4640    
Error   C2676   binary '==': 'userInfo' does not define this operator or a conversion to a type acceptable to the predefined operator   Database (Project 1)    C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\include\xutility    4640    

All these errors point to this template function in xutlity file:

template <class _InIt, class _Ty>
_InIt _Find_unchecked1(_InIt _First, const _InIt _Last, const _Ty& _Val, false_type) {
    // find first matching _Val
    for (; _First != _Last; ++_First) {
        if (*_First == _Val) // Error C2676 {
            break;
        }
    }

    return _First;
}
  • I apologize for the lengthy amount of code! I'll try to create a minimal example!
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
JPychon
  • 3
  • 2
  • 1
    *Where* do you get this error? What what are all those variables and functions you don't show? Please try to create a [mcve] to show us, with emphasis on the *minimal* part. Also please take some time to read [ask] as well as [this question checklist](https://codeblog.jonskeet.uk/2012/11/24/stack-overflow-question-checklist/). – Some programmer dude May 23 '20 at 12:03
  • 1
    On a different note, please don't use *recursion* for simple loops. – Some programmer dude May 23 '20 at 12:04
  • I don't think it is because of the iterator, your type `userInfo`, may not have an equality comparison operator-defined. Some of the algorithms you use require this operator, such as `std::find`. – Mansoor May 23 '20 at 12:06
  • Recursion is great for languages that support TRO (*tail recursion optimization*). The C++ standard does not require TRO. I've heard that there are C++ compilers that have TRO (I think in some limited capacity on par with *loop unrolling optimization*), none of the compilers I use have TRO. – Eljay May 23 '20 at 12:07
  • @Elijay - This suggests otherwise https://stackoverflow.com/questions/34125/which-if-any-c-compilers-do-tail-recursion-optimization . Admittedly, it is often necessary to explicitly use the more aggressive optimisation settings, since C ++ compilers aren't configured by default to do that. TRO also doesn't play well in some cases (e.g. stack unwinding and calling destructors). – Peter May 23 '20 at 12:16
  • I apologize for that! I'll try to create a minimal reproducible example! I get this error in a file called xutility (if (*_First == _Val) {) – JPychon May 23 '20 at 12:19
  • A good compiler will print a lot of messages for seemingly simple errors, and will hopefully also include a pointer to where in your code the problem might be. So please also include a *full* and *complete* copy-paste of the error output. And if any message references a line in your code, please add a comment on that line. – Some programmer dude May 23 '20 at 12:27
  • I've added the full error output to the thread! Thank you for response! – JPychon May 23 '20 at 12:33
  • It's a little clearer now, and as mentioned by e.g. @Mansoor, it's about comparing two `userInfo` objects. How would the compiler know how to compare two such objects with `==`? The answer is: It doesn't (unless `userInfo` is a type-alias for a standard type, which it doesn't seem to be). You need to implement (overload) the `==` operator for `userInfo`, or provide a function that the [`std::find`](https://en.cppreference.com/w/cpp/algorithm/find) function can call for the comparison. – Some programmer dude May 23 '20 at 12:38
  • That makes alot more sense! I'll have to do some more reading on operator overloading but that explains alot, thanks! – JPychon May 23 '20 at 12:40

1 Answers1

0

You need to add an equality comparison operator to the userInfo class:

class userInfo
{

public:

   bool operator==(const userInfo& rhs) const
   {
      if (this == &rhs)
         return true;
      // rest of implementation
   }

   bool operator!=(const userInfo& rhs) const
   {
      return !(*this == rhs);
   }
}

Mansoor
  • 2,357
  • 1
  • 17
  • 27
  • Thank you @Mansoor! I'll give it a shot! – JPychon May 23 '20 at 19:47
  • Hey @Mansoor! So I've been reading more about this and I cant quite wrap my head around it. Where are we defining the left hand side to be compared? Can we do something along the lines of (operator==(const std::string username, const userInfo& rhs) to compare the username string and the username associated with the object? – JPychon May 23 '20 at 23:29
  • For member functions, the `this` pointer (for the current object) is an implicit argument and hence it can be used inside the definition. Member functions with a single argument are therefore binary functions. You can define the operators outside the class as free functions, in which case they will take two arguments. As free functions, you can have the arguments be in any order whereas for member functions, the first argument is always of the your class type. – Mansoor May 24 '20 at 00:17