C ++: function pointer as template argument instead of functor
I am trying to create this class that can either use the default functor as an argument, or the user can provide it if they want. But I cannot pass the function pointer as a template argument. Could you please help me in understanding what I am missing.
template <typename T>
struct CheckFunctor
{
bool operator()(T obj)
{
return true;
}
};
template <typename _Ty,
class _Pr = CheckFunctor<_Ty>
>
class MyClass
{
typedef _Ty mapped_type;
typedef _Pr CanBeCleaned_type;
_Ty data;
CanBeCleaned_type predicate;
public:
void SomeMethod()
{
if( predicate(data))
{
std::cout << "Do something";
}
}
MyClass(_Ty timeOutDuration, _Pr pred = _Pr())
: data( timeOutDuration), predicate( pred)
{}
};
template< typename T>
struct CheckEvenFunctor
{
bool operator()(T val)
{
return (val%2 == 0);
}
};
bool CheckEven( int val)
{
return (val%2 == 0);
}
int main()
{
//Usage -1
MyClass<int> obj1( 5);
//Usage- 2
MyClass< int, CheckEven> obj2(6, CheckEven); //Error: 'CheckEven' is not a valid template type argument for parameter '_Pr'
//Usage -3
MyClass<int, CheckEvenFunctor<int>>( 7);
}
source to share
You are trying to pass CheckEven
as a type parameter, although CheckEven
it is not a type but a function (of a type bool(int)
). You must define the type as a pointer to the type of the passed function. decltype
it is convenient here:
MyClass< int, decltype(&CheckEven)> obj2(6, CheckEven);
You can also create a factory function and let the compiler infer the template parameters:
template<class T, class F>
MyClass<T, F> makeClass(T timeOutDuration, F pred) {
return {timeOutDuration, pred};
}
auto obj2 = makeClass(6, CheckEven);
source to share
It is possible to allow a template parameter to be a function, but yours MyClass
expects the second argument to be a type and not a function. You might think that template specialization could be used so that you can define MyClass
to also take a function in the second template argument, but that won't work. Template specialization allows you to change behavior MyClass
for certain types that are passed as template arguments, but those types must still conform to the template's definition MyClass
, which is that the two arguments are types.
You can change the type MyClass
you create by giving a second argument of the function pointer type as suggested in the other answer, but you will lose the benefit of extending the template making your calls to inline functions. Another solution would be to create a helper class that converts your function to a functor and uses it to instantiate it MyClass
.
template <bool P (int)>
struct F {
bool operator()(int obj) { return P(obj); }
};
//...
MyClass<int, F<CheckEven> > obj2(6);
source to share