I'm having a discussion with a colleague about the API of a simple class that has only one public method. I initially went for:
class CalculateSomething
{
public:
void operator()(const SomeObject &obj) const;
private:
// ...
}
However, my colleague opposes the use of operator() and wishes to simply name the method 'calculate' for the sake of clarity. Although I don't find that argument convincing, it made me think of the pros and cons.
I was surprised to see that my search on this didn't bring up much since I would assume that this is quite a common scenario (one class, one responsibility). As such, I'm really interested in hearing what other people think about this.
A function pointer allows a pointer to a function to be passed as a parameter to another function. Function Objects (Functors) - C++ allows the function call operator() to be overloaded, such that an object instantiated from a class can be "called" like a function.
A function assigns to every element of a set X an element of a set Y. A functor assigns to every object of a category C an object of a category D and also assigns to every morphism in C a morphism in D in a way compatible with sources, targets, and composition.
Functors give you more flexibility, at the cost of usually using slightly more memory, at the cost of being more difficult to use correctly, and at the cost of some efficiency.
std::function is the great unifying force of those things introduced by C++11. std::function is much older than lambda functions in C++, it's not just to make them easy to use.
If lambdas are really not an option, Your choice should depend on the scope of work that object undertakes... and of cause your coding conventions or styles. You can decide to be explicit (see Werolik's answer), its a good thing if the method is relatively unfamiliar and requires states, but
Let us take simple use-cases from the standard library...
One thing you see in common with all these is that they are verbs... In my perspective, if your class is exactly like the snippet you posted, CalculateSomething
signifies an action to me, so I can always instantiate it as CalculateSomething()(my_object...)
.
And like you cited, it comes in very handy in using STL algorithm itself and many other C++ libraries. If you go your colleague's method, you may have to resort to using std::binds and lambdas because you want to 'adapt' an interface.
Example:
class CalculateSomething
{
public:
void operator()(const SomeObject &obj) const;
private:
// ...
}
class CalculateNothing
{
public:
void calculate(const SomeObject &obj) const;
private:
// ...
}
An example usage is:
std::for_each(container.begin(), container.end(), CalculateSomething());
against
std::for_each(container.begin(), container.end(), [ c = CalculateNothing()](auto x) { c.calculate(x); });
I think I prefer the former.
Well, here are also mine 5 cents.
First of all, if possible, I'd simply use lambda or free function. Are you sure, you need a class for your needs?
Anyway, assuming that class is required.
SomethingCalculator
' - isn't it an object?DoWork
', 'Calculate
' or whatever.This will make it much more explicit.
UPD. All above can be still argued, but what I truly believe in, is that adding enough in-code documentation will make the real difference, independent of the method name.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With