William Morris
William Morris

Reputation: 3684

Converting class to string

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?

Upvotes: 4

Views: 13254

Answers (2)

James Kanze
James Kanze

Reputation: 153899

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.

Upvotes: 14

Alexander Chertov
Alexander Chertov

Reputation: 2108

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().

Upvotes: 3

Related Questions