Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Functions/functors as template parameters. Can they be stored?

Imagine I have the following free function and functor:

void myFreeFunction(void)
{
    cout << "Executing free function" << endl;
}

struct MyFunctor
{
    void operator()(void)
    {
        cout << "Executing functor" << endl;
    }
};

As discribed by this answer, I can pass my function or functor as a template argument to another function:

template <typename F>
void doOperation(F f)
{
    f();
}

And then call:

doOperation(myFreeFunction);
doOperation(MyFunctor());

So far so good. But what if I want something like the following:

template<typename Callback>
class MyClass
{
private:
    Callback mCallback;

public:
    MyClass(){}

    void execute()
    {
        mCallback();
    }
};

In this case I'm specifing the function/functor when I declare the class but not calling it until later. It works for functors:

MyClass<MyFunctor> myClass1;
myClass1.execute();

But not for functions:

MyClass<myFreeFunction> myClass2;
myClass2.execute();

Compiler says:

error C2923: 'MyClass' : 'myFreeFunction' is not a valid template type argument for parameter 'Callback'

Which is fair enough... but how would you structure this?

Note: I'm aware of std::function and may end up using this. It's measurably slower though so I'm looking at all options.

Thanks,

David

like image 357
David Williams Avatar asked Mar 02 '12 15:03

David Williams


1 Answers

The problem is that freefunction is not a type but a element of a of (int this case a function pointer.

to fix this problem you need to pass the function in, in construction, however you still need to know the exact type.

myclass<call_back_t> my_class(call_back);

EDIT: In c++11 the type can be got from decltype(call_back)

however getting the call back can be troublesome it is often a lot easier to create a generator function

//this should be in the namespace of the class or a static member of it
template<FuncType>
myclass<FuncType> make_class(FuncType func)
{
     return myclass<FuncType>(func);
}
//called like
myclass mc=make_class(&my_callback);

Don't for get to alter the constructor

template<typename CallBack>
myclass{
private:
   CallBack call_back;
public:
   myclass(CallBack call_back_)
   : call_back(call_back_)
   {}
};

or something like that

like image 118
111111 Avatar answered Oct 18 '22 08:10

111111