I have the following code:
class Employee {
friend string FindAddr( list<Employee> lst,string name );
public:
Employee(const string& s){ cout << "Employee CTOR" << endl;}
bool operator==( Employee& e) {
return e.name == name;
}
private:
string name;
string addr;
};
string FindAddr( list<Employee> lst, string name ) {
string result = "";
for( list<Employee>::iterator itr = lst.begin(); itr != lst.end(); itr++ ) {
if ( *itr == name ) { // Problematic code
return (*itr).addr;
}
}
return result;
}
As I understand, the problematic line if ( *itr == name ) should follow these steps:
- Recognizing it is
operator==on classEmployee. - Trying to figure out if there is a conversion from
string nametoEmployeeso that the operator could work. - Implicitly call the constructor
Employee(const string& s)on objectstring name. - Continue with
operator==.
However, this line gives me trouble at compile time:
Invalid operands to binary expression ('Employee' and 'string' (aka 'basic_string<char>'))
Even if I explicitly call the constructor:
if ( *itr == Employee::Employee(name) )
I get the same error.
This is confusing. I’m having trouble to understand when implicit constructor call works (and why the code doesn’t work even if I explicitly call the constructor).
Thanks!
The rule is:
Temporaries can be bound only to a
constreference.As you mentioned for the
==to work,The object
namewhich is of the typestd::stringneeds to be converted to typeEmployee, the conversion operators in your classEmployeeshould make this happen. However, the createdEmployeeobject is an temporary object.i.e a nameless object which doesn’t live long enough to need a name.Such a nameless temporary object cannot be bound to a non-const reference.[Ref 1]So what you need is a const reference:
[Ref 1]
Motivation for the rule:
Motivation for this particular rule is outline by Bajrne in Section 3.7 of The design and evolution of C++.
Thus many a times temporary objects are generated unknowingly in function calls, where they are least expected and one might (wrongly)assume that their function works on the original object being passed, whereas the function operates on the temporary.Thus it’s easy to write a code that assumes one thing and does another.So to avoid such easy to mislead situations the rule was put in place.