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?
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.
Structs in C++ are just classes with a default accessor of public instead of private. So yes, that would have a function overload.
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.
#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.
$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.
Related
I read that function call () can also be overloaded. http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B
What would the following mean?
It works.
template<typename T, typename Comp>
struct bind{
T v;
Comp comp;
bool operator()(const T& b){
return comp(b,v);
}
};
int main(){
bind<int, less<int> > b;
b.v = 2;
cout << b(3) << "\n";
}
It means that if you create an object of type bind<>, you can apply the function-call operator to that object.
Like this:
bind<int, std::less<int>> b;
b.v = 2;
std::cout << b(1) << "\n";
That snippet might print "true" on the standard output.
If you have a class called foo, I'm sure you understand what it means to call a member function of an object of that type:
foo f;
f.bar();
You may also understand that you can overload certain operations. For example, you could overload operator+ for foo so that you could do something like this:
foo f, g;
f + g;
Now you can also overload operator() for a class, which allows you to call it as though it were a function:
foo f;
f();
Yes, f is not a function but it is an object of class type that overloads operator(). Class types that do this are known as functors or function objects.
In the example you've given, bind is a functor. When you create an object of that type, you can call it like a function, passing it a const T& and it will return a bool back to you. The implementation of operator() actually calls the function stored in comp, passing it both the T object you passed to operator(), a, and the member object v of type T.
As it stands, it doesn't mean much of anything except "syntax error". For example:
template<T, Op>
This simply isn't allowed. For each template parameter, you need to specify whether it's a type (using class or typename) or a non-type parameter such as an int. Since the apparent intent is that both these should be type parameters, you need something like:
template <class T, class Op>
or:
template <typename T, typename Op>
For this situation, there's no difference in meaning between class and typename.
struct bind{
T v;
Leaving v uninitialized will lead to undefined behavior, so you probably don't want to allow that. You'd normally prevent it by adding a constructor that takes a T as its parameter and initializes v to that value:
bind(T const &v) : v(v) {}
When you include a constructor like this, the compiler won't automatically generate a default constructor, so it's no longer possible to create a bind object with v uninitialized -- exactly what we wanted.
Although creating the comp object:
Op comp;
is fairly harmless, it's also quite unnecessary. You could just as well do the comparison with a temporary instance created with Op(), in which case this:
bool operator()(const T& a){
return comp(a,v);
}
...would become something like this (and the Op comp; simply removed):
bool operator()(T const &a) {
return Op()(a, v);
}
Even with the corrections, I'd consider this code obsolescent. In C++98/03, it would have been useful in a situation where you needed to supply a functor to an algorithm, such as:
std::remove_copy_if(a.begin(), a.end(), bind<int,
std::back_inserter(b),
bind<int, std::less<int> >(5));
...which would copy numbers from a to b, removing those less that 5.
In C++11, however, most (if not all) uses of this bind should probably be written as lambdas instead though, so the bit above would become something like:
std::remove_copy_if(a.begin(), a.end(), bind<int,
std::back_inserter(b),
[](int x) { return x < 5; });
This is not only shorter, but (at least once you're used to it) quite a bit simpler than using std::less and bind to put together a function. It won't generally make any difference in run-time efficiency -- a lambda is basically a "shorthand" way of generating a class template, so what it generates would end up pretty similar to the code using bind.
I just read somebody call a class with a constructor and an operator() a predicate:
// Example
class Foo {
public:
Foo(Bar);
bool operator()(Baz);
private:
Bar bar;
};
However, I haven't heard the word predicate being used in this context before. I would call such a thing a functor. For me, a predicate would be something from the domain of formal logic.
This raises the following questions:
Is this a common word for something like Foo?
Are both terms used interchangeably, or do they mean slightly different things?
Or
Does the return type (bool versus something else) have something to do with it?
What about the operator() being const?
Functor is a term that refers to an entity that supports operator () in expressions (with zero or more parameters), i.e. something that syntactically behaves as a function. Functor is not necessarily an object of some class with overloaded operator (). Ordinary function names are functors as well. Although in some contexts you can see the term "functor" used in a more narrow and exclusive sense: just class objects, but not ordinary functions.
A predicate is a specific kind of functor: a functor that evaluates to a boolean value. It is not necessarily a value of bool type, but rather a value of any type with "boolean" semantics. The type should be implicitly convertible to bool though.
The shown class is a functor that implements a predicate.
A predicate is a boolean function.
About the operator() being non-const here: it should ideally be const, yes.
A predicate is a special kind of function object. See this excellent column by Nicolai Josuttis. To quote:
A function object that returns a Boolean value is a predicate. That's
what almost all tutorials, books, and manuals write about predicates
of the STL. This, however, is not the whole story.
However, there is an additional requirement that is unfortunately not
mentioned in any manual or in the C++ Standard: A predicate should
always return the same result for the same value.
Or, in the language of C++: You should declare operator() as a
constant member function (and not play games with mutable or casts).
For the same reason, a copy of a predicate should have the same state
as the original.
The reason is that the STL algorithms will copy function objects around, and the copying should not affect the outcome of applying the function objects.
template<typename Arg0>
struct UnaryPredicate
:
public std::function<bool(Arg0 const&)>
{
bool operator()(Arg0 const& a0) const
{
return // your code here
}
};
template<typename Arg0, typename Arg1>
struct BinaryPredicate
:
public std::function<bool(Arg0 const&, Arg1 const&)>
{
bool operator()(Arg const& a0, Arg const& a1) const
{
return // your code here
}
};
As has been said, a predicate is just a user supplied directive to analyze something to a boolean state. So you can have the same two things doing the same thing...
struct is_odd
{
is_odd() : count(0);
bool operartor () (int i) const { ++count; return (i % 2) == 1; }
private
int count;
}
And...
bool isOdd(int i) { return (i % 2) == 1; }
So, what is so special about the functor? It maintains state if you want it to! That means that while these two lines of code do the same thing (assume v is a vector, with values 0 - 9)...
for_each(v.begin(), v.end(), isOdd); //using C-style function pointer
And...
is_odd fn = for_each(v.begin(), v.end(), is_odd); //using functor
Only with the second use case can you then call...
int calls = fn.count;
That is because for_each (as well as other STL algorithm functions) returns the functor it used at the end, so now the final state can be queried.
One other cool thing to note is that in the second case, we are using what is called an "anonymous" object.
From the MSDN:
Represents the method that defines a set of criteria and determines
whether the specified object meets those criteria.
http://msdn.microsoft.com/en-us/library/bfcke1bz.aspx
// By using structure :
struct complex {
float real;
float imag;
};
complex operator+(complex, complex);
main() {
complex t1, t2, t3;
t3 = t1 + t2;
}
complex operator+(complex w, complex z) {
statement 1;
statement 2;
}
// By using class :
class complex {
int real;
int imag;
public:
complex operator+(complex c) {
statement 1;
statement 2;
}
main() {
complex t1, t2, t3;
t3 = t1 + t2;
}
While using structure, the overloaded function can accept two arguments whereas while using class the overloaded function accepts only one argument, when the overloaded operator function is a member function in both cases i.e in struct as well as in class. Why does this happen?
That has nothing to do with classes vs. structs. It's about member vs. nonmember.
Classes and structs in C++ differ solely bu their default accessibility level for members and bases (public for structs, and private for classes). Other than this, there is no difference at all.
When overloading operators, you almost always have the choice of defining an operator as a member or as a freestanding function. There are only 4 operators that have to be members. These are: (), [], ->, and = (as to why, see this question of mine). For the rest, the choice is yours.
This excellent FAQ entry explains (among other things) how to choose between member vs. nonmember.
To answer your core question: In case of member function, the first agument is *this
...when the overloaded operator function is a member function in both
cases i.e structure as well as class...
What makes you say that? That's not true.
In case of struct in your example, overloaded operator function is not a member. This is why it requires 2 parameters.
So, the difference has absolutely nothing to do with struct vs. class matter. The reason you have different number of parameters in these operators is that the first one is implemented as a non-member (and therefore has two explicit parameters), while the second one is implemented as member (and therefore has only one explicit parameter).
This happens because you using different methods to define operator. When you use struct you define it outside of struct, but when use class you define operator inside class.
When you want to pass two args to your overloaded operator+ you should create a friend function of the class and then pass const complex& lhs, const complex& rhs as your args. Now you can have two arguments to your operator+.
When the operator+ is a member of the class, one arg is implicitly passed as the this pointer.
//
complex operator +(cont complex& lhs, const complex& rhs)
{
...
}
main()
{
complex t1,t2,t3;
t3=t1+t2; // i.e. t3 = operator+(t1, t2);
}
//
class complex
{
int real,imag;
public:
complex operator +(const complex& rhs){}
};
main()
{
complex t1,t2,t3;
t3=t1+t2; // i.e. t3 = t1.operator+(t2);
}
In your second example the overloaded operator is a member function of the class, therefore when this operator is called, it's called as a member function of the first operand and the first operand is therefore implicitly given as the object on which the member function has been called (the this pointer if you like).
HI,
I started learning C++ STL's
i am just trying some small programs.one of them is below:
inline int const& max (int const& a, int const& b)
{
return a < b ? b : a;
}
template <typename T>
inline T const& max (T const& a, T const& b)
{
return a < b ? b : a;
}
int main()
{
::max(7, 42); // calls the nontemplate for two ints
::max<>(7, 42); // calls max<int> (by argument deduction)
::max('a', 42.7); // calls the nontemplate for two ints
}
I have some basic questions!!
why is the scope resolution
operator used here?
why/how is
that calling ::max<>(7, 42) will
assume that the parameter passed are
integers?
1) why is the scope resolution
operator used here?
Probably to differentiate the max declared here from the one in (for example) the std:: namespace.
2) why/how is that calling ::max<>(7, 42) will assume that the
parameter passed are integers?
It doesn't have to assume anything - integer literals have the type int.
And to answer the question you didn't ask:
max('a', 42.7);
matches the non-template version because type conversions are not performed on templated parameters, but are performed on non-template ones.
Presumably to avoid conflicts with std::max
It's not assuming that the parameters are integers, it sees that the parameters are integers. It then assumes that the template argument is int because the parameters are integers.
For 2) what you possible mean is that why does it work - the template does not require integers, just any types on which the "<" operator is defined. An integer fulfills this so it is ok to pass it to the template method.
This seems inconsistent. Why do we use &Example::func instead of Example::func? is there a use for Example::func or &exampleFunction? it doesnt seem like we can make a reference to a function so that rules out Example::func. and i cant think of a way to use &exampleFunction since exampleFunction already returns a pointer.
#include <iostream>
class Example {
public:
void func() { std::cout <<"print me\n"; }
};
void exampleFunction() { std::cout << "print me too\n"; }
typedef void (Example::*ExampleFunc_t)();
typedef void (*ExampleFunction_t)();
int main()
{
Example e;
ExampleFunc_t f = &Example::func;
ExampleFunction_t f2 = exampleFunction;
(e.*f)();
f2();
return 0;
}
Because that's how the standard defines pointers to functions.
You actually always have to use the address operator & to get a pointer to a function, but for regular functions and static member function, an implicit conversion from function to pointer-to-function is defined in the standard.
This is not defined for a (non static) memberfunction because you can't obtain an lvalue to a non static memberfunction.
From the C++ standard:
4.3 Function-to-pointer conversion
An lvalue of function type T can be converted to an rvalue of type
“pointer to T .” The result is a pointer to the function.
with footnote 52:
This conversion never applies to non-static member functions because
an lvalue that refers to a non-static member function cannot be obtained.
I think that they'd rather only allow &function, for consistency reasons, but that the implicit conversion is simply an artifact of the C heritage...
The point is using Function Pointers. For a very rough example, suppose you have a class having several member variables by which you may need to sort of the elements of an array of that class type, like this:
struct CL {
int x, y, z;
};
bool sort_by_x(const CL& obj1, const CL& obj2);
bool sort_by_y(const CL& obj1, const CL& obj2);
bool sort_by_z(const CL& obj1, const CL& obj2);
...
CL obj[100];
...
sort(obj, obj+100, sort_by_x);
...
sort(obj, obj+100, sort_by_y);
...
sort(obj, obj+100, sort_by_z);
Here std::sort is used to sort an array of CL objects. Look at the third parameter, it's name of a function. The std::sort function can take a function pointer in third parameter, and use that function as comparator to sort the array. It is upto us how to define sort_by_* functions so that std::sort works as expected.