简体   繁体   中英

C++: Function pointer as Template argument instead of functor

I have been trying to create this class which can either use the default functor as an argument or the user can provide one if he wants. But I am unable to pass function pointer as my template argument. Can 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);
}

You are trying to pass CheckEven as a type parameter even though CheckEven is not a type but a function (of type bool(int) ). You should define the type as a pointer to the type of function that you are passing. decltype is handy here:

MyClass< int, decltype(&CheckEven)> obj2(6, CheckEven);

You can also create a factory function and let the compiler deduce the template parameters:

template<class T, class F>
MyClass<T, F> makeClass(T timeOutDuration, F pred) {
    return {timeOutDuration, pred};
}

auto obj2 = makeClass(6, CheckEven);

It is possible to allow a template parameter to be a function, but your MyClass is expecting the second argument to be a type, not a function. You might think that template specialization could be used to allow you to define MyClass to also take a function in the second template argument, but it won't work. Template specialization allows you to modify the behavior of MyClass for particular types that are passed as template arguments, but those types must still match the template definition of MyClass , which is that the two arguments are types.

You could modify the type of MyClass you are instantiating by making the second argument a function pointer type as suggested in a different answer, but you would lose the advantage of template expansion making your calls to functions inline. Another solution would be to create a helper class that will convert your function into a functor, and use that to create your MyClass instance.

template <bool P (int)>
struct F {
    bool operator()(int obj) { return P(obj); }
};

//...
MyClass<int, F<CheckEven> > obj2(6);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM