Functions/functors as template parameters. Can they be stored?
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
David Williams
Updated on July 04, 2022Comments
-
David Williams almost 2 years
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
-
David Williams over 12 yearsExcellent, thanks for the info. I've adjusted MyClass as you suggested and I can now do:
-
David Williams over 12 yearsMeh, it seems I can't add more questions in the comments. Basically your solution does work for both functors and functions so thanks for that. There's a small syntactic issue I'm having with the functors, but I'll ask a new question if I can't work it out.
-
111111 over 12 years@PolyVox Just edit your post or post it here ill try and help
-
David Williams over 12 yearsThanks, but I worked it out. I was running into the 'most vexing parse' issue when trying to construct my functor.
-
David Williams over 12 yearsP.s. I can confirm that your solution is indeed faster than using std::function :-)
-
111111 over 12 yearsof course it is, although there are many benefits to
std::function<>
too, the first of which is that you don't have to templatize your code so it can have a separate header and implementation and reduce code bloat. If the call back isn't frequently callstd::function
is often a better bet. -
David Williams over 12 yearsOh, sure, I think std::function is great for some cases. But my real code is already templatised anyway and the function is being called millions of times. It's actually a ray traversing a 3D grid and calling the callback for each element it touches. I do need to think about my users though... the std::function approach is simpler for them. I will think about it ;-)
-
111111 over 12 years@PolyVox if you use the generate function I mentioned then actually it is not harder for your users at all. It might however increase compile times and code bloat.
-
David Williams over 12 yearsActually I didn't test your make_class function, and I can't get it to work. Is the idea that it can create an instance of 'MyClass' without the user needing to know the type of their free function? So it should be used with free functions but not functors? Can you provide an example of how it is used? Also, should the first line actually include 'typename' and should the return type include '<FuncType>'?
-
111111 over 12 yearsThe idea is that it is able deduce the type of the parameter without having to be explicitly told. which is easier to use. It have added an example as to how that might be used.
-
David Williams over 12 yearsBut in your line 'myclass mc=make_class(&my_callback);' surely you still need to place the type in angle brackets after 'myclass' as it is templatised. I.e. myclass<type_here> mc = ..., in which case you still need to know the type?
-
111111 over 12 years@PolyVox sorry I wasn't thinking, you are right, try
auto mc=myclass(&my_callback);
if you don't have C++11 this isn't going to work. -
David Williams over 12 yearsNo problem ;-) I can't use auto inside my library, but my users can and they are the ones who have to provide the callback. So I think I can use this.
-
111111 over 12 yearsan obvious thing to do would be to create a typedef for the common usages, so somehthing like
typedef myclass<void(*)(void)> mcvoid_t
or for quick usages to allow binding to anything you can reap some of the benefit ofstd::function
bytypedef myclass<std::function<void(void)> mc_generic_t
which would bind to anything (inc functors, lanbda, std::bind) taking nothing and returning nothing