4

This is derived from Herb Sutter's gotw3 (http://www.gotw.ca/gotw/003.htm).

With the following class and FindAddr function...

using std::string;
using std::list;

class Employee
{
public:
    Employee(const string& n, const string& a) : name(n), addr(a) { }
    string name;
    string addr;
};

string FindAddr(const list<Employee>& l, const string& name)
{
    string addr;
    list<Employee>::const_iterator i = find(l.begin(), l.end(), name);

    if (i != l.end()) {
        addr = (*i).addr;
    }
    return addr;
} 

I get a compile error because the Employee class has no conversion to string. I can see that such a conversion is not necessarily sensible, but for the purpose of the exercise, I added a naive conversion:

string::string(const Employee& e)
{
    return e.name;
}

This gives me an error:

gotw3.cc:17:9: error: C++ requires a type specifier for all declarations
string::string(const Employee& e)
~~~~~~  ^

What am I doing wrong?

2

2 Answers 2

14

Two things: first, you cannot add to an existing class without modifying the class definition. If you have a class that you want convertible to std::string (or to double or whatever), you should define a conversion operator: in your case:

class Employee
{
    //  ...
    operator std::string() const
    {
        return name;  //  Or whatever...
    }
};

Second, the solution in your case isn't to provide an implicit conversion, it is to use std::find_if with an appropriate matcher. In C++11, this may be done by using a lambda, but in general (and in older versions of C++), you can always define a functional type. For cases like this, where a class has an natural "key", I would probably add a few member classes, along the lines of:

class Match : std::unary_function<Employee, bool>
{
    std::string myName;
public:
    explicit Match( std::string const& name )
        : myName( name )
    {
    }
    bool operator()( Employee const& toBeMatched ) const
    {
        return toBeMatched.name == myName;
    }
};

Additional functional types defining an ordering relationship, or equality of keys, might be in order as well.

Sign up to request clarification or add additional context in comments.

3 Comments

Yes. A typo on my part; I'll correct it. Thanks for pointing it out.
Thanks. But what is the name of the predicate function from the Match class that I pass to find_if?
A functional object can be called like a function; that's what the overload of operator()(...) does. You don't pass a function to find_if, you pass an instance of the class (e.g. Match( whatImLookingFor )).
3

There is no class string, there is a class template std::basic_string.

You should never modify anything in the std namespace.

For the purpose of conversion of a type to string you can add

Employee::operator std::string()

or define a

std::ostream& operator<<( const Employee& em, std::ostream& os ); - this way your type will work with lexical_cast.

.. but what you actually need here is std::find_if().

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.