I want to have a function that checks certain conditions based on a given callback function.
Considers this code:
class Foo{
template <class ParamType>
struct IsGood
{
typedef bool (*Check)(typename const ParamType*, int other);
};
template< typename ParamType >
void DoSmth(IsGood<ParamType>::Check isGood, const ParamType* param){
//...
if(isGood(param, some_int_calculated_here)) doSmthElse();
}
What I want is to call it with:
bool checkEqualInt(int* i, int j){return *i==j;}
bool checkEqualFloat(float* i, float j){return *i==j;}
DoSmth(checkEqualInt, &i);
DoSmth(checkEqualFloat, &i_float);
(All constructed examples to show the problem)
The compiler won't get that and throws me error C2664 "converting param 1 from bool(int*,int) in bool(ParamType,int) not possible"
I there a solution without using
template< typename ParamType, Check >
void DoSmth(Check isGood, const ParamType param)
Which ommits the necessary declaration of the check function?
Best solution would be to get the IsGood() header in the function itself.
We can define it in other words like this: If the reference of a function is passed to another function argument for calling, then it is called the callback function. In C we have to use the function pointer to call the callback function. The following code is showing how the callback function is doing its task.
main cannot be a function template; it must be a function.
Function templates. Function templates are special functions that can operate with generic types. This allows us to create a function template whose functionality can be adapted to more than one type or class without repeating the entire code for each type.
The main type of templates that can be implemented in C are static templates. Static templates are created at compile time and do not perform runtime checks on sizes, because they shift that responsibility to the compiler.
The problem is that the first argument of your template function is not deducible:
template< typename ParamType >
void DoSmth(typename IsGood<ParamType>::Check isGood, const ParamType param)
// ^ ^^^^^^^^^^^^^^^^^^^^^^^^
// missing nested type! not deducible!
The simple option is to expand the signature in place (C++03,C++11):
template< typename ParamType >
void DoSmth(void (*isGood)(ParamType,int), const ParamType param)
// note: dropped 'const' that will be dropped anyway by the compiler
Or if you have C++11 you can substitute the IsGood<ParamType>::Check
by a template alias:
template <typename T>
using IsGood = void (*)(T,int);
template< typename ParamType >
void DoSmth(IsGood<ParamType> isGood, const ParamType param)
Or alternatively refactor your code to take a functor that will make it more flexible, simple and possibly efficient since there will be easier for the compiler to inline the call:
template <typename P, typename T>
void DoSmth(P predicate, T param) {
if (predicate(param,somethingelse)) { ...
}
Using a functor template will solve your issues:
template< typename Functor, typename ParamType >
void DoSmth(Functor isGood, const ParamType param){
//...
if(isGood(param, some_int_calculated_here)) doSmthElse();
}
Now you can use any function or functor object that has a compatible signature(not necessarily one that takes a ParamType
and an int
as parameters). Otherwise, you'll need to use functions with that exact signature.
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