views:

201

answers:

5

Hi, I got a simple C++ struct as follows:

// Functor for peak to decreasing intensity sorting
struct cmp_decr_int2
{
    bool operator() (peak2 a, peak2 b) 
    { 
        return a.int2 > b.int2;
    }   
};

is there an overload of the operator in this sample?

A: 

Structs in C++ are just classes with a default accessor of public instead of private. So yes, that would have a function overload.

Jonathan Sternberg
+10  A: 

Yes. operator() is called the "function call" operator, and allows an object to be usable as if it were a function. Such a class is called a "functor".

A common pattern is to make functors that compare two things for equality or relations, for use in anything requiring a comparison predicate. (This one could be usable in an std::map, for example. It would have a member likecmp_decr_int2 compare; and then it could compare the relation between two things with: if (compare(x, y)) /* x is less than y, by some metric */)

This particular struct orders two peak2's by comparing their int2 members. It could be better written as:

struct cmp_decr_int2
{
    //                     note const! vvvvv
    bool operator() (peak2 a, peak2 b) const
    { 
        return a.int2 > b.int2;
    }   
};

The function should be const because it does not need to change any members (there are none to change.) const-correctness is important.*

In many cases these functors are used in contexts where the arguments themselves are const, so you should either take the arguments by value as in the example or by constant reference.

You should prefer to pass types by const-reference over by-value, except when that type is fundamental (float, unsigned int, double, etc.) or smaller than a void*. In most cases, then, you will pass by const-reference:

struct cmp_decr_int2
{
    // note const&:  vvvvv       v    vvvvv       v    vvvvv
    bool operator() (const peak2 & a, const peak2 & b) const
    { 
        return a.int2 > b.int2;
    }   
};

*If this were used as a predicate in a std::map, for example, without const the map wouldn't be able to compare two things while within a const function.

GMan
@GMan: Thank you
ladyfafa
@Gman : +1, Good answer.
Prasoon Saurav
And if the `peak2` objects are not really small, the arguments should also be const references.
David Rodríguez - dribeas
@David: Good point. You can add it if you want. :)
GMan
I have tried to add it there. Feel free to adapt the style as you like, as it is *your* answer (and english is not my mother tongue). :)
David Rodríguez - dribeas
@David: I didn't know English isn't your native language, couldn't tell. :)
GMan
Excuse me, what is peak2 in this case? is it a class? it should have the attribute "int2", what is it ?
ladyfafa
@ladyfafa: It's definitely a class type, but that's all we can say. `int2` is probably an `int`.
GMan
A: 

in c++ a struct is in every way like a class, except that the default parameter access is public: rather than private:. It is a common practice to use struct instead of class when the scope of the defined type's use is very narrow, such as in the example of a simple functor.

What this example does is emulate the appearance of a function pointer without the fragility of possibly being null.

The operator() member here overloads function calling. when you try to do something like:

cmp_decr_int2 foo;
foo(peek2(), peek2());

that overload member gets called.

TokenMacGuy
@TokenMacGuy: that was very detailed for a beginner, really helped! :)
ladyfafa
A: 
#include <iostream>
using namespace std;

struct cmp_decr_int2
{
    bool operator() (int a, int b)
    { 
        return a > b;
    }

    bool operator() (int i)
    {
        return i > 0;
    }
};

int main()
{
    cmp_decr_int2 a;
    cout << a(1, 2) << endl;
    cout << a(1) << endl;
}

Yep, sure can overload the function! This worked perfectly for me.

BT
@BT: thanks!~~~
ladyfafa
A: 

$13.5.4 states-

operator() shall be a non-static member function with an arbitrary number of parameters. It can have default arguments. It implements the function call syntax postfix-expression ( expression-listopt ) where the postfix-expression evaluates to a class object and the possibly empty expression-list matches the parameter list of an operator() member function of the class. Thus, a call x(arg1,...) is interpreted as x.operator()(arg1, ...) for a class object x of type T if T::operator()(T1, T2, T3) exists and if the operator is selected as the best match function by the overload resolution mechanism (13.3.3).

Therefore, the struct 'cmp_decr_int2' has definitely overloaded operator().

Note that this is also the only operator in C++ that can take variable number of arguments.

Chubsdad