This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How can overloading operator “function call” in C++ be useful?
I see often where the parenthesis operator, operator(), is overloaded on a class or struct. I have never run into such a need myself, and wonder what is the typical use/need of this operator?
For instance, overloading operator== is accepted as returning true or false based on some equality made with the argument provided. This has a certain accepted and anticipated behavior.
It's used a lot for the hashes, sets and algorithms component of STL to construct things called 'functors'. For example:
using stl::map ;
map<string, string> myMap ;
but if you look at the specification for map it also includes a 'Compare' entry which defaults to less. The Compare is the 'functor' you want map to use when comparing two keys. It looks something like this:
template<class Key>
class less<Key> {
public:
boolean operator()(const Key& a, const Key& b) { return a < b ;}
} ;
so what you have is:
map<string, string, less<string> > myMap ;
and evertime you put something in the map or try to find something in the map it will use the less::operator() to do the comparisons.
You can use this to acchieve other effects such as when using 'sort' you can get sort to yield items in reverse order by using a different functor.
You can use operator(), also known as the 'function call operator', to make an object behave like (and be usable as) a function.
These objects are often referred to as 'functors', but that shouldn't be confused with the same term from mathematics. I believe a more proper term is 'function object'.
Imagine you have a function that takes a callback. But suppose you need to store some state in that callback.
[note: I haven't compiled this code, but you get the idea]
void DoStuffAndCallBack(MyCallbackType Callback)
{
...
Callback(args)
...
}
In C, or in 'C-with-classes'-style C++, you would pass a static callback function to this method, and store results in some global or class-static variable.
But in C++, the function could be written like so:
template<CallbackType>
void DoStuffAndCallBack(CallbackType Callback)
{
...
Callback(args)
...
}
Now you can define a functor object that overloads operator() and pass an instance of that object to the function. That instance will get the callback, and any intermediate results you want to store can be stored in that instance.
In other words, it's a nice way to avoid globals (:
I'm sure there are other uses, but that's one good one, IMO.
The canonical example is for a smart pointer class returning whether or not it is null, so you can do things like:
SmartPointer p = someOtherThing;
if (p)
{
// do something
}
In this case, the return type of the () operator should be bool, and the code will work as written. It creates a functor that allows the instance of the class to be called like a function.
Related
I've tried various solutions on SO to solve this problem, yet I must be doing something wrong.
I have several classes where methods in each of the classes have the same method signature:
typedef int (*ControllerMethod)(const std::string &data, const std::unordered_map<std::string, std::string> ¶ms);
And an example class having some method using that signature:
class StaticContentController {
public:
int handleStaticContentRequest(const std::string &data, const std::unordered_map<std::string, std::string> ¶ms) {
return 1;
}
}
Now I try to create a map of pointers to member functions:
std::map<std::string, ControllerMethod> operations;
operations.emplace("staticContent", &StaticContentController::handleStaticContentRequest);
std::string d("test.txt");
ControllerMethod f = operations["staticContent"];
auto s = ((_staticContentController).*f)(d, pooledQueries); // <- compile error here
but calling the method gives the compile error
Right hand operand to .* has non-pointer-to-member type 'web::server::ControllerMethod'
What am I missing?
Update:
I now have an empty Controller base class which other controller classes inherit from:
namespace web { namespace server {
class Controller {
};
typedef ControllerResponse (Controller::*ControllerMethod)(const std::string &data, const std::unordered_map<std::string, std::string> ¶ms);
}}
Now I'm getting the following error at operations.emplace():
No matching constructor for initialization of 'std::__1::pair<const std::__1::basic_string<char>, web::server::ControllerResponse
Updated answer
You're trying to use two different paradigms here, and they aren't really compatible with one another. If I interpret your edit correctly, you're trying to create a map of functions that call into other classes, and you want to declare this map as a set of function pointers.
Function pointers are an assembly level construct, exposed by C. The syntax reflects this - and getting a C++ class to conform to this is not possible without help - namely, adding a context pointer parameter that is associated with every function pointer, and converting the context pointer to a class instance to call the member function.
So, how do we fix the problem?
In both of the next approaches, we need a context object associated with the function table. This involves creating a structure to hold the member function and the context:
template<typename T> struct FunctionTableEntry
{
ControllerMethod Function;
T* Context;
};
and our function pointer becomes the following:
typedef ControllerResponse (T::*ControllerMethod)(const std::string &data, const StringMap ¶ms);
Here, StringMap is a typedef for std::unordered_map<std::string, std::string>.
Our main problem now comes with removing the template parameter T, as we can't make maps of runtime defined templates (a template who's type will only be known at run time).
There are two main approaches to take in resolving this, and both have issues that will need to be considered. The first is to perform C style type erasure with pointers and very careful association. The second is to abandon function pointers in favor of C++ function objects.
C-Style Type Erasure
This option involves using C-style casts to convert the class instance pointer to its base class type, the member function pointer to the type expected by the function declaration, and then making the call as though the base class defines the method. This requires the use of pointers, and cannot be done without them.
To do this, our FunctionTableEntry structure changes to the following:
struct FunctionTableEntry
{
ControllerMethod Function;
Controller* Context;
}
and our function pointer to:
typedef ControllerResponse (Controller::*ControllerMethod)(const std::string &data, const StringMap ¶ms);
To add a new entry, we do the following:
std::map<std::string, FunctionTableEntry> operations;
FunctionTableEntry Entry;
Entry.Function = (ControllerMethod)&StaticContentController::handleStaticContentRequest;
Entry.Context = (Controller*)&_staticContentController;
operations.emplace("staticContent", Entry);
And to call it:
FunctionTableEntry f = operations["staticContent"];
auto s = ((f.Context)->*f.Function)(d, pooledQueries);
This method suffers from a few drawbacks - first, you have no other choice but to use pointers to refer to your controller objects - casting will not function properly otherwise. You can make this a bit more C++ friendly with std::shared_ptr, but otherwise, there is no way to replace it. This also means you need to carefully manage the lifetime of your controller objects. If they get freed while the function table is still referencing them you will almost certainly crash the system.
Second, the casting can cause issues with complex inheritance hierarchies. This method only works if (Controller*)_staticContentController == _staticContentController, i.e. casting to the base class gives the same numerical pointer value. Otherwise, the called method will fail as it will not be able to properly reference its local data.
This method has the advantage of being quite fast, however. There is no function overhead besides the table lookup, and the generated assembly is not much more than just calling the function normally. It is also runtime independent - so long as the equality expression above is true with all users of the controller system, anyone with a C++ compiler can create a new controller and this system will be able to call their functions, even if they use a completely different runtime library.
Additionally, if you know the controller instance is going to be used with multiple functions, you can modify the structure to provide a map of functions associated with one Context value, allowing you to reduce some of the memory overhead. This may not be possible with your design, but it's worth looking into if memory is a concern.
C++ Function Objects
The second solution is to completely do away with C-style function pointers altogether and use std::function. Since std::function can contain instance data as part of itself, and can be placed into a map, this allows you to std::bind a member function, creating a partially specified function call (I believe in functional programming this is what's called a closure).
In this case, there is no FunctionTableEntry structure - instead we use the following:
typedef std::function<ControllerResponse(const std::string&, const StringMap&)> ControllerMethod;
To add a new method, we do the following:
std::map<std::string, ControllerMethod> operations;
operations.emplace("staticContent", std::bind(&StaticContextController::handleStaticContentRequest, &_staticContentController, std::placeholders::_1, std::placeholders::_2);
This creates a closure that calls the member function with the required controller instance.
To call this, we do the following:
std::string d("test.txt");
ControllerMethod f = operations["staticContent"];
auto s = f(d, pooledQueries);
C++ function objects override operator (), which allows them to work as though they were static functions.
This method allows for both member functions and static functions to exist in the same map. It also allows for complex inheritance hierarchies to occur, as there is no casting to make things function - everything occurs with template functions.
The downside to this method is you still need to deal with object lifespan - the content controller objects cannot be destroyed until after the function map has been cleared. In addition, there is some overhead due to the use of std::function with placeholder parameters (though that likely depends on the runtime library in use, my tests have shown it generates a whole lot more code in x86-64 GCC 9.3).
This method also is not runtime independent - whatever runtime you choose to use here must also be used by every programmer that uses this code, otherwise incompatibilities in the way each library creates and stores std::function will cause strange failures. This means no compiler mixing - if you used MSVC 2019 to build the API, everyone else who uses this library must use MSVC2019 to build their controller component. If you aren't providing an API here, then this is not an issue.
Original answer
Your function pointer declaration is wrong - pointers to members have a different syntax to the normal function pointer typedef.
A normal function pointer uses the syntax you have currently:
typedef int (*foo)(int x, int y);
A pointer to member function typedef looks like this:
typedef int (SomeClass::*foo)(int x, int y);
The SomeClass:: section is required as pointers to members have an additional parameter to them, called this. In C++, the this pointer is passed as the first argument to the function, which makes the function declaration different (as the actual assembly code needed to call the function is different, see MSVC generated assembly for a real world example).
To solve the issue, you need to provide a base class that can be used to declare the typedef, then inherit from that class to allow the method to be called. This is effectively identical to using inheritance, unless you have multiple methods in the same type that have the same signature, but do different things.
The DirectX 11 Effects framework uses this exact paradigm to avoid branching when configuring different shader types in the graphics pipeline - see here, at line 590.
As pointed out, the type of a non-static member function of the class StaticContentController is not:
typedef int (*ControllerMethod)(const std::string &data, const std::unordered_map<std::string, std::string> ¶ms);
Instead, it is:
typedef int (StaticContentController::*StaticContentControllerMethod)(const std::string &data, const std::unordered_map<std::string, std::string> ¶ms);
This was your initial error.
This makes sense as you need an instance to call the member function, and the instance has a type as well. And it makes sense that if you have a Base::*Function pointer, you can call it with an instance of a class publicly and unambiguously derived from Base, because a derived pointer can be converted implicitly to a base pointer.
It also makes sense that you cannot assign a Derived::*Function pointer to a Base::*Function pointer because the result could be called with any Base instance, which need not be a Derived instance. This was the error in the question update.
In this very limited circumstance, C++ behaves completely logically.
With the modification to the correct type, your snippet will compile:
std::map<std::string, StaticContentControllerMethod> operations;
operations.emplace("staticContent",
&StaticContentController::handleStaticContentRequest);
std::string d("test.txt");
StaticContentControllerMethod f = operations["staticContent"];
auto s = ((_staticContentController).*f)(d, pooledQueries); // <- works
So presumably your actual question is how to store in this map member function pointers for multiple classes and not just StaticContentController. But that is the wrong question. You have to have the instance (_staticContentController) to invoke the member function pointer, so you already know the type.
So maybe you want to ask how to erase the type. One way is storing something that doesn't require an instance: for that, use std::function as the mapped type and bind the instance when inserting into the map. That would work and be straightforward if you have the controller at the time the map is created. A second way is using a type erasing type like std::any for the mapped type, and use any_cast at the point of use to return it to its initial type. A third way is to use a common base class with virtual functions which are overridden in your classes. Since the virtual functions can be called with a base pointer, you can store member function pointers of the base class.
Alternatively, maybe you want to ask how to have a type-indexed collection: the type is known at lookup time (because you have an instance) and you need to lookup a value whose type (member function pointer) depends on the "key" type.
The simplest way to do this is to have templated classes, and let the compiler handle the mapping:
template<typename T>
struct operations {
static std::map<std::string, void (T::*)(etc.)> pointers;
};
// use:
operations<StaticContentController>::pointers["staticContent"];
Another version of type-indexing might have the following interface:
template<template<typename> typename Value>
class type_keyed_map
{
public:
template<typename T>
void insert(std::unique_ptr<Value<T>> value);
template<typename T>
auto find() -> Value<T>*; // return null if not found
};
You can use a std::map in the implementation, but std::map does not allow multiple value types.
bool all_ok = boost::algorithm::all_of(info.begin(), threadInfo.end(), [&](std::pair<std::string, Info> const &p){ return p.second.am_ok; });
Above is a line I am trying to remove c++11 from (in order to be compliant with an application I am integrating with, if you must know). I would like to replace the lambda without defining a function external to the current method.
My question is, how can I utilize boost::bind to represent a function & binding that takes in a single input and returns a boolean?
If you really want to use boost::bind to do this, it would look something like this:
boost::bind(&Info::am_ok, boost::bind(&std::pair<std::string, Info>::second, _1));
Boost.Bind supports composition of its function objects, so in this case the function object created by the nested bind gets called first, and its result (the Info object) is passed to the enclosing function object, which returns the am_ok member of the structure.
You see that the code is somewhat contrived, so you'll probably want to write a custom function object anyway.
struct is_ok
{
typedef bool result_type;
result_type operator() (std::pair<std::string, Info> const &p) const
{
return p.second.am_ok;
}
};
I need to establish a hash table using a hasher different from the default one, so I write something like:
class foo {
public:
...
private:
struct myhasher {
size_t operator() (myclass bar) { return hash_calculation bar; }
}
static size_t hash_calculation (myclass bar) {
// do some calculation
}
hash_map<myclass, myhasher> myhashmap;
}
It works. Now for some reason I have to write a non-static member function to replace hash_calculation, say, it needs a non-static member of the class as an argument. Then the whole thing failed because I cannot use a non-static method in a nested struct.
This is somehow similar to another widely discussed problem: how to use a non-static function to do comparison or sorting. See for example:
Using a non-static class member inside a comparison function
and
C++ std list sort with custom comparator that depends on an member variable for the object instance . They both established a functor instead of a function as the comparator. However in my case this trick does not work because I need a class name inside the hash_map definition, not a specific struct object. What should I do? Thanks in advance for your help!
You can't. How is the hash_map supposed to know which instance of myhasher should be used when calling myhaser::hash_calculation?
hash_map isn't part of the standard C++ library, not even in C++11, so it's a custom class, and you have included no information about how it works. If there is a way for it to take some sort of constructor argument for which myhasher it should use, you're in luck. But it doesn't sound like it.
Also, you're using pass by value when you probably mean to pass in a const reference. Passing by value is likely going to be really slow and inefficient.
The standard "hash-map", i.e., std::unordered_map<K, V, H, E, A> takes a hash object of type H as constructor argument. A copy of this object is used to determine the hash for the object by way of the function call operator. This way can provide some context. Obviously, you were already using a non-static function call operator but you choose to delegate to a static member.
In c++ do you have 'out parameters' like in c#?
In c# the method signature would be:
bool TryGetValue(int key, out OrderType order)
The idea is the variable may not be assigned before passed but MUST be assigned before exiting the method.
MSDN out params link: http://msdn.microsoft.com/en-us/library/aa645764(v=vs.71).aspx
There is nothing as strict as C# out parameters in C++. You can use pointers and references to pass values back but there is no guarantee by the compiler that they are assigned to within the function. They are much closer to C# ref than out
// Compiles just fine in C++
bool TryGetValue(int key, OrderType& order) {
return false;
}
No, there are no out parameters in C++ that force you to assign to it before exiting the function. Pointers and references are more like ref parameters in C#.
If you really like a 'out' keyword, you can define a maro:
#define out
as a mark, although it has not effect for compiler.
Just like some one would define 'public', 'private' keyword for C.
You can use references or pointers to simulate out parameters, but a better way is to use tuples (std::tuple in C++11 or boost::tuple in C++98/03) to return multiple values from a function. You cannot return without a complete tuple.
#include <tuple>
std::tuple<bool, OrderType> TryGetValue(int key) {
OrderType ot;
...
return std::tuple<bool, OrderType>(true, ot);
}
...
bool b;
OrderType o;
std::tie(b, o) = TryGetValue(k);
That would be one use of references:
bool TryGetValue(int key, OrderType &order)
Then you can simply assing to order and the calling function would get the data.
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
}