penelope
penelope

Reputation: 8419

Function passed as a class argument

In C++, we can pass a function/functor to a function like so:

template <typename F>
void doOperation(int a, int b, F f){
    std::cout << "Result: " << f(a,b) << std::endl;
}

we can then use both functions and functors:

int add(const int &a, const int &b){ return a+b; }
struct subtract(){
    void operator() (const int &a, const int &b) { return a-b; }
};

and use it in the following manner:

doOperation(1,2,add);
doOperation(5,2,subtract());

My question is, can I do something similar with a class and pass a function as an argument to a class, store it and use it later? E.g.

template <typename F>
class doOperation{
    public:
       doOperation(int &a, int &b, F f) : a(a), b(b), f(f) {};
   void setOperands(int &a, int &b) { this->a = a; this->b = b };
   void performCalculation(){
          std::cout << "Result: " << f(a,b) << std::endl;
       }
    private:
        int a,b;
        F f;
}

So that we may assign it a function once and then later use it:

doOperation summing(1,2,add);
summing.setOperands(2,3);
summing.performCalculation();

doOperation subtraction(7,3,subtract());
subtraction.performCalculation();

If my examples are valid, I would appreciate the explanation for the mechanics here as I seem to be getting a bit lost. In case I missed something, I am looking for hints on whether this can be achieved.

Lastly, how would I then use such a class doOperation in other functions and classes. For example, would defining something like this inside a member function require me to template the new class, its member function, and how would it be declared and used:

class higherFunctionality{    
 public:
     higherFunctionality() {...}

     void coolThings(){
        doOperation *myOperation = operationFactory( ... );
        myOperation->setOperands(4,5);
        myOperation->performCalculation();
     }
};

Upvotes: 2

Views: 68

Answers (1)

Edward Strange
Edward Strange

Reputation: 40849

Yes, but you have to supply the type when you instantiate template classes. The usual way to deal with this is to create a helper function:

template < typename Fun > struct operation_class 
{  
    operation_class(Fun f) : fun{f} {}
    Fun fun; 
};
template < typename Fun >
operation_class<Fun> operation(Fun fun) { return operation_class<Fun>{fun}; }

int main()
{
    auto op0 = operation(some_fun);
    auto op1 = operation(some_functor{});
}

Frankly though, you are better off just using lambda:

auto op0 = [a,b]() { return sum(a,b); };
auto op1 = [a,b]() { return subtract{a,b}(); }

// C++17:
auto op2 = [op=subtract{a,b}] { return op(); };

Upvotes: 1

Related Questions