c++oopfunctordesign-guidelines

Pros and Cons of implementing functionality as functor


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.

Advantages operator()

Disadvantages operator()

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.


Solution

  • 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.