Read this question about how to compare custom objects in C++.
I did not understand the operator overloading used here. What is the operator being overloaded here? Is it ()? What is the use of overloading that?
struct MyStruct
{
int key;
std::string stringValue;
MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}
};
struct less_than_key
{
inline bool operator() (const MyStruct& struct1, const MyStruct& struct2)
{
return (struct1.key < struct2.key);
}
};
The point is to use a less_than_key object as a function:
less_than_key f;
bool result = f(key1, key2);
Object that can be called like functions (including garden variety functions) are sometimes called functors (warning: this is not the meaning of functor in mathematics), or function objects, or sometimes functoids.
Many standard library algorithms and containers expect such function objects as arguments. For instance, std::map can be customized with a binary function object (exactly like the one you showed us) to know how it should sort the keys.
Please refer to this beginners' book list and read about standard algorithms and containers to understand where you can use those beasts.
Function objects and iterators are the core of the C++ standard library, you should really learn about them to make the best use of C++.
The operator() is a function call operator with, probably, the most common use being to allow you to use normal function call syntax on an object that could be considered as behaving in a 'function-like' way.
In this example, you can call less_than_key() which is used by the STL sort.
This is called functor. This is used heavily in C++ apis. Some of these apis take a functor which performs object specific operations.
Example pseudo code:
- Sorting a list of MyStruct objects.
sort api in algorithm.
std::list<MyStruct> mystructlist;
// populate mystructlist
sort(mystructlist.begin(), mystructlist.end(), less_than_key);
It is often called the "functor" operator and it is useful because it mimics the syntax of a call to a regular function.
Objects with such an overloaded operator are often used with stlalgorithms like std::find_if() or in your case, std::sort().
Here are some samples:
std::vector<MyStruct> myvector;
less_than_key comparator;
std::sort(myvector.begin(), myvector.end(), comparator);
Or:
MyStruct a, b;
less_than_key comparator;
if (comparator(a, b))
// Do something
else
// Do something else.
As you can see, there is not syntax difference between calling the operator() method of an instance of less_than_key and calling a function with the same prototype (well, disregarding of the hidden this parameter).
Related
I want to create a multiset of objects of my own Class with a custom comparator, and every example I have seen out there does it without classes.
The code I have so far main.cpp is like this:
multiset<MyClass> myMultiSet;
whereas in Myclass.cpp there is a comparator function:
bool MyClass::operator<(const MyClass c) const {
return (this->data->size() < c.size());
}
Multiset seems to take the less operator by default, and it actually uses the operator< function in the class, but I cannot find a way to specify it to use another operator (such as operator<=)
For example, I would like it to look like this:
multiset<MyClass, MyClass::operator<=> myMultiSet;
bool MyClass::operator<=(const MyClass c) const { // <----- Now it's using this one
return (this->data->size() <= c.size());
}
Member functions are different to functions: they take an the this pointer. As a result, you can't use pointer-to-member-functions directly (and you would need to take the address explicitly as member functions don't decay to pointer-to-member-functions, i.e., &MyClass::operator<=). Also, the parameter is type, not a value. Also, as was pointed out, operator<= doesn't implement a strict weak order, i.e., you can't use that anyway.
The easiest to use an actual operator, whether member of not, is to use the names from <functional>, e.g.
std::multiset<MyClass, std::greater<MyClass>> s;
If the member isn't a known name, I'd think using a lambda is the easiest approach but requires C++20:
std::multiset<MyClass, decltype([](MyClass const&l, MyClass const&r){ return l.member(r); })> s;
Without C++20 I think you can use std::mem_fn although that is slightly annoying as you'll need to provide the pointer to member as a constructor argument:
#include <functional>
#include <set>
struct MyClass
{
bool member(MyClass const&) const { return false; }
};
int main()
{
std::multiset<MyClass, decltype(std::mem_fn(&MyClass::member))> s(std::mem_fn(&MyClass::member));
}
I want to declare a multiset of a structure.
The current form of my declaration of multiset is
struct obj
{
//code
};
struct compare
{
inline bool operator()(const obj &a, const obj &b)
{
//code
}
};
multiset<obj,compare> mst;
Is there any other form of declaration which may use only one structre by overloading operator for obj.
Yes, you can overload operator < for your struct, either as a member function or as a free-standing one. This will make code more concise (in my purely subjective opinion), but in practice would not lead to any difference in performance.
As a matter of fact, optimizing compiler is more than likely to generate exactly the same code (provided the actual comparison code is the same).
I am writing a library in C++ for which I implemented a map wrapper with type erasure. The wrapper is structured as in this wonderful article: http://www.cplusplus.com/forum/articles/18756/.
TLDR:
template<typename K, typename V>
class AnyMap
{
class MapConcept
{
public:
// Lots of pure virtual methods...
// These mimic the intersection of STL and Boost maps' interfaces
// Example:
virtual size_type size() = 0;
};
template<typename ActualMapType>
class MapModel : MapConcept
{
ActualMapType m;
public:
// Implementations of the parent's virtual methods...
// These basically just call the same method on member m.
// Example:
size_type size() { return m.size(); }
};
MapConcept* mapConcept;
public:
// Again, the STL and Boost maps' interface methods
// Example:
size_type size() { return mapConcept->size(); }
};
I'm not sure whether I will expose this map as part of the finished library or tuck it away as a helper class, but either way I'm wondering what do with the assignment operator.
Currently, I have something like this:
AnyMap& AnyMap::operator=(const AnyMap& other) {
delete mapConcept;
mapConcept = other.mapConcept->clone();
return *this;
}
This means that if I create two maps with say an STL's map and a Boost's unordered_map and then assign one to the other, both will now have the same map type underlying them.
std::map<string, int> stlMap;
boost::unordered_map<string, int> boostMap;
// insert some stuff into maps
AnyMap<string, int> stlAnyMap( stlMap );
AnyMap<string, int> boostAnyMap( boostMap );
stlAnyMap = boostAnyMap;
// now stlAnyMap has a copy of boostMap
So, this makes some sense because the contents of the map assigned to are what's expected. However, I suspect that usually the map types will differ by one of the type arguments with default values (such as Hash in Boost::unordered_map). So, maybe it should retain the underlying map type. I think, this can be done with something like the following:
AnyMap& AnyMap::operator=(const AnyMap& other) {
mapConcept->clear();
mapConcept->insert( other.mapConcept->begin(), other.mapConcept->end() );
return *this;
}
This should work because of the templated insert method:
template <class InputIterator>
void insert (InputIterator first, InputIterator last);
By the way, if anyone is wondering how I dealt with the iterators: I used Thomas Becker's any_iterator - http://thbecker.net/free_software_utilities/type_erasure_for_cpp_iterators/any_iterator.html.
So, what do you guys think? I'm leaning toward the latter approach, but I'd like to hear any arguments for either side.
Thanks in advance!
EDIT: Here is the first argument against (perhaps, you could tell me how important this is): the contents of one map type might now map one-to-one to another map if one predicate distinguishes two keys in the map while the other considers them the same.
Do you want the map wrapper to have value semantics or not? That will determine how deep the copy has to be. In any case, the implementation of other.mapConcept->clone() will be polymorphic (this is, after all, the essence of the C++ type erasure technique) and result in a dispatch to a call in the MapModel subclass that looks like this
virtual MapModel *clone() { return new MapModel(m); } // covariant return type
So everything boils down to what ActualMapType's copy constructor does (since the member variable m will be a copy.)
Since the technique was invented to get value semantics, I think retaining that feature is consistent with the principle of Least Surprise. Moreover, the point is to have a fixed interface. The implementation (STL or boost or whatever) is irrelevant by design, so there is little point in trying to retain the implementation in any particular object instance.
Incidentally your implementation of operator= for the "standard" case is not exception safe. The copy-and-swap idiom (perhaps with a custom swap() method) works better
AnyMap( AnyMap const& other )
: mapConcept( other.mapConcept ? other.mapConcept->clone() : 0)
{}
AnyMap& operator= ( AnyMap rhs ) // note temporary: invokes copy constructor
{ std::swap( mapConcept, rhs.mapConcept ) ; return *this; }
I read the tutorials about the binary and unary functions. I understood the structure of them, but I couldn't imagine in which case I need these functions. Can you give an example for usage of them.
http://www.cplusplus.com/reference/std/functional/unary_function/
http://www.cplusplus.com/reference/std/functional/binary_function/
These aren't functions, these are classes (structs, actually, but doesn't matter). When you define your own binary functions to use with STL algorithms, you derive them from these classes in order to automatically get all the typedefs.
E.g.
struct SomeFancyUnaryFunction: public std::unary_function<Arg_t, Result_t>
{
Result_t operator ()(Arg_t const &)
{
...
}
};
now you don't need to manually provide the typedefs for argument_type, result_type etc. These structs, just like the iterator struct are there just for our convenience, in order to reuse the typedefs needed for algorithms.
Update for C++11:
As of C++11, the new std::bind does not really need any typedefs, so there are, in a way, obsolete.
Basically, they provide all the typedefs necessary to allow composition of higher-order functions from unary and binary function objects using function adaptors. For example, this allows using a binary functor where a unary is needed, binding one of the arguments to a literal value:
std::find_if( begin, end, std::bind1st(greater<int>(),42) );
std::bind1st relies on the functor passed to it to provide those types.
AFAIK the new std::bind doesn't need them, so it seems in new code you can use std::bindand do away with them.
There's an explanation on the sgi STL documentation of Function Objects. In summary, unary_function and binary_function are used to make functors adaptable. This allows them to be used with function object adaptors such as unary_negate.
What are they?
std::unary_function and std::binary_function are base structs for creation adaptable function objects. The word adaptable means that they provide necessary typedefs for being used in conjunction with standard function adaptors like std::not1, std::not2, std::bind1st, std::bind2nd.
When I need to use them?
You may use them every time you need to use your custom function object together with standard function adaptor.
Do you have an example?
Lets consider some examples (I know, they are artificial. From the other side I hope, that they are rather descriptive).
Example 1.
Suppose you want to print all strings in a vector with their lengths not less than a particular threshold and print them to std::cout.
One might use the next function object:
class LengthThreshold
{
public:
LengthThreshold(std::size_t threshold) : threshold(threshold) {}
bool operator()(const std::string& instance) const
{
return (instance.size() < threshold);
}
private:
const std::size_t threshold;
};
Now the task is pretty simple and can be performed by std::remove_copy_if algorithm:
// std::size_t threshold is defined somewhere
std::remove_copy_if(some_strings.begin(), some_strings.end(),
std::ostream_iterator<std::string>(std::cout, "\n"),
LengthThreshold(threshold)
);
What if you want to use the same function object to print all the strings with their lengths strictly less than the threshold?
The obvious solution we can come up with is the usage of std::not1 function adaptor:
// std::size_t threshold is defined somewhere
std::remove_copy_if(some_strings.begin(), some_strings.end(),
std::ostream_iterator<std::string>(std::cout, "\n"),
std::not1(LengthThreshold(threshold))
);
In fact, the code above won't compile because our LengthThreshold is not adaptable and has no typedefs which are necessary for std::not1.
To make it adaptable we need to inherit from std::unary_function:
class LengthThreshold : public std::unary_function<std::string, bool>
{
// Function object's body remains the same
}
Now our first example works like a charm.
Example 2.
Lets change our previous example. Suppose we don't want to store a threshold inside the function object. In such case we may change the function object from unary predicate to binary predicate:
class LengthThreshold : public std::binary_function<std::string, std::size_t, bool>
{
public:
bool operator()(const std::string& lhs, std::size_t threshold) const
{
return lhs.size() < threshold;
}
};
And make use of std::bind2nd function adaptor:
// std::size_t threshold is defined somewhere
std::remove_copy_if(some_strings.begin(), some_strings.end(),
std::ostream_iterator<std::string>(std::cout, "\n"),
std::bind2nd(LengthThreshold(), threshold)
);
What about C++11 and higher?
All the examples above intentionally use only C++ 03.
The reason is that std::unary_function and std::binary_function are deprecated since C++ 11 and completely removed from C++ 17.
It happened with the advent of more generalized and flexible functions like std::bind which make inheriting from std::unary_function and std::binary_function superfluous.
In the Boost Signals library, they are overloading the () operator.
Is this a convention in C++? For callbacks, etc.?
I have seen this in code of a co-worker (who happens to be a big Boost fan). Of all the Boost goodness out there, this has only led to confusion for me.
Any insight as to the reason for this overload?
One of the primary goal when overloading operator() is to create a functor. A functor acts just like a function, but it has the advantages that it is stateful, meaning it can keep data reflecting its state between calls.
Here is a simple functor example :
struct Accumulator
{
int counter = 0;
int operator()(int i) { return counter += i; }
}
...
Accumulator acc;
cout << acc(10) << endl; //prints "10"
cout << acc(20) << endl; //prints "30"
Functors are heavily used with generic programming. Many STL algorithms are written in a very general way, so that you can plug-in your own function/functor into the algorithm. For example, the algorithm std::for_each allows you to apply an operation on each element of a range. It could be implemented something like that :
template <typename InputIterator, typename Functor>
void for_each(InputIterator first, InputIterator last, Functor f)
{
while (first != last) f(*first++);
}
You see that this algorithm is very generic since it is parametrized by a function. By using the operator(), this function lets you use either a functor or a function pointer. Here's an example showing both possibilities :
void print(int i) { std::cout << i << std::endl; }
...
std::vector<int> vec;
// Fill vec
// Using a functor
Accumulator acc;
std::for_each(vec.begin(), vec.end(), acc);
// acc.counter contains the sum of all elements of the vector
// Using a function pointer
std::for_each(vec.begin(), vec.end(), print); // prints all elements
Concerning your question about operator() overloading, well yes it is possible. You can perfectly write a functor that has several parentheses operator, as long as you respect the basic rules of method overloading (e.g. overloading only on the return type is not possible).
It allows a class to act like a function. I have used it in a logging class where the call should be a function but i wanted the extra benefit of the class.
so something like this:
logger.log("Log this message");
turns into this:
logger("Log this message");
Many have answered that it makes a functor, without telling one big reason why a functor is better than a plain old function.
The answer is that a functor can have state. Consider a summing function - it needs to keep a running total.
class Sum
{
public:
Sum() : m_total(0)
{
}
void operator()(int value)
{
m_total += value;
}
int m_total;
};
You may also look over the C++ faq's Matrix example. There are good uses for doing it but it of course depends on what you are trying to accomplish.
The use of operator() to form functors in C++ is related to functional programming paradigms that usually make use of a similar concept: closures.
A functor is not a function, so you cannot overload it.
Your co-worker is correct though that the overloading of operator() is used to create "functors" - objects that can be called like functions. In combination with templates expecting "function-like" arguments this can be quite powerful because the distinction between an object and a function becomes blurred.
As other posters have said: functors have an advantage over plain functions in that they can have state. This state can be used over a single iteration (for example to calculate the sum of all elements in a container) or over multiple iterations (for example to find all elements in multiple containers satisfying particular criteria).
Start using std::for_each, std::find_if, etc. more often in your code and you'll see why it's handy to have the ability to overload the () operator. It also allows functors and tasks to have a clear calling method that won't conflict with the names of other methods in the derived classes.
Functors are basically like function pointers. They are generally intended to be copyable (like function pointers) and invoked in the same way as function pointers. The main benefit is that when you have an algorithm that works with a templated functor, the function call to operator() can be inlined. However, function pointers are still valid functors.
One strength I can see, however this can be discussed, is that the signature of operator() looks and behaves the same across different types. If we had a class Reporter which had a member method report(..), and then another class Writer, which had a member method write(..), we would have to write adapters if we would like to use both classes as perhaps a template component of some other system. All it would care about is to pass on strings or what have you. Without the use of operator() overloading or writing special type adapters, you couldn't do stuff like
T t;
t.write("Hello world");
because T has a requirement that there is a member function called write which accepts anything implicitly castable to const char* (or rather const char[]). The Reporter class in this example doesn't have that, so having T (a template parameter) being Reporter would fail to compile.
However, as far I can see this would work with different types
T t;
t("Hello world");
though, it still explicitly requires that the type T has such an operator defined, so we still have a requirement on T. Personally, I don't think it's too wierd with functors as they are commonly used but I would rather see other mechanisms for this behavior. In languages like C# you could just pass in a delegate. I am not too familiar with member function pointers in C++ but I could imagine you could achieve the same behaviour there aswell.
Other than syntatic sugar behaviour I don't really see the strengths of operator overloading to perform such tasks.
I am sure there are more knowingly people who have better reasons than I have but I thought I'd lay out my opinion for the rest of you to share.
Another co-worker pointed out that it could be a way to disguise functor objects as functions. For example, this:
my_functor();
Is really:
my_functor.operator()();
So does that mean this:
my_functor(int n, float f){ ... };
Can be used to overload this as well?
my_functor.operator()(int n, float f){ ... };
Other posts have done a good job describing how operator() works and why it can be useful.
I've recently been using some code that makes very extensive use of operator(). A disadvantage of overloading this operator is that some IDEs become less effective tools as a result. In Visual Studio, you can usually right-click on a method call to go to the method definition and/or declaration. Unfortunately, VS isn't smart enough to index operator() calls. Especially in complex code with overridden operator() definitions all over the place, it can be very difficult to figure out what piece of code is executing where. In several cases, I found I had to run the code and trace through it to find what was actually running.
Overloading operator() can make the class object calling convention easier. Functor is one of the applications of operator() overloading.
It is easy to get confused between Functor and user-defined conversion function.
Below 2 examples show the difference between
1. Functor
2. User-defined conversion function
1. Functor:
struct A {
int t = 0;
int operator()(int i) { return t += i; } // must have return type or void
};
int main() {
A a;
cout << a(3); // 3
cout << a(4); // 7 (Not 4 bcos it maintaines state!!!)
}
2. User-defined conversion function:
struct A {
int t = 3;
operator int() { return t; } // user-defined conversion function
// Return type is NOT needed (incl. void)
};
int main() {
cout << A(); // 3 - converts the object{i:3} into integer 3
A a;
cout << a; // 3 - converts the object{i:3} into integer 3
}