Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

size_t: an operator? (and a way to use unordered_set)

What is

operator size_t () const

Environment: Visual Studio 2010 Professional


TL; DR

Today I was searching for a way to use std::tr1::unordered_set. Because I asked for how to use std::map last time, I decided to find it out myself.

I googled and most of the results told me to have a struct to do hashing. The way looked a little bit complicated for me, and I kept searching and finally came across another approach.

I need to implement

bool operator == (const edge & another) const

and

operator size_t () const

The resulting code is near the end of the question.

== is familiar without any problem. size_t is familiar, too. But what is operator size_t?

It seems like equals and hashCode for Java, which need to be overridden together according to Effective Java. But I am not sure, especially when the name is size_t.


The resulting code is as follows. The complete program works fine, and produces correct outputs.

class edge {
public:
    int x;
    int y;
    edge(int _x, int _y) : x(_x), y(_y) {
    }
    bool operator == (const edge & another) const {
        return (x == another.x && y == another.y);
    }
    operator size_t () const {
        return x * 31 + y;
    }
};

A little bit more:

Not

size_t operator () const

which cannot be compiled:

error C2143: syntax error : missing ';' before 'const'
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
error C2059: syntax error : '{'
error C2334: unexpected token(s) preceding '{'; skipping apparent function body

Even not

int operator size_t () const

but as I see it, the function returns int. The error code is as follows:

error C2549: user-defined conversion cannot specify a return type
like image 517
Dante May Code Avatar asked Jul 05 '11 15:07

Dante May Code


2 Answers

It's the type cast operator. Basically provides for implicitly converting the object to the specified type, in this case size_t.

EDIT:

Say you have a function defined as follows:

void Foo( size_t x )
{
  // do something with x
}

If your class edge defines the type-cast operator for conversion to size_t you can do the following:

edge e;
Foo( e );

The compiler will automatically convert the edge object to size_t. As @litb says in the comments section, do not do this. Implicit conversions can cause trouble by allowing the compiler to perform conversions when you may not have intended for that to happen.

You should instead define a member function like edge::to_size_t() (I know that's a terrible name) to perform the conversion.

As an example, std::string defines the std::string::c_str() member function instead of defining the type-cast operator for conversion to const char *.

EDIT 2: Sorry, I didn't read your question carefully enough. Now I see you're trying to use your class in an std::unordered_set. In that case you should define functors that do the hash and compare operations for your class. Alternatively, you can provide template specializations of std::hash and std::equal_to for your class and not have to specify the optional template parameters when creating the unordered_set object.

As you've asked in the question, this is very much like Java's hashCode() member function, but since C++ classes do not all derive from a common base class like Java classes, it is not implemented as an override-able base class function.

like image 132
Praetorian Avatar answered Sep 30 '22 12:09

Praetorian


It is a conversion operator, as hinted by error C2549: user-defined conversion cannot specify a return type. It defines how your type can be converted into size_t in this case. In general, operator X() {...} specifies how to create a X from your type.

like image 44
carlpett Avatar answered Sep 30 '22 13:09

carlpett