user1899020
user1899020

Reputation: 13575

How to use a general function pointer as a template parameter?

Is it possible to use a general function pointer as a template parameter? The function pointer template can accept free functions, member functions, and lambda functions. For simplicity, assuming the functions has only one argument, like

template<class ArgumentT, class ReturnT, function* f>
struct A
{
   // f is used somewhere.
};

Upvotes: 7

Views: 16526

Answers (4)

Slava
Slava

Reputation: 44288

I would recommend to use std::function<> if you can use C++11 or boost::function<> if you cannot:

template<class ArgumentT, class ReturnT > struct A { 
    typedef std::function< ReturnT( ArgumentT ) > Function;
    void foobar( Function f ) { ReturnT ret = f( arg ); }
};

In this case you can pass function pointer, functor, lambda, or use std::bind or boost::bind with almost any function which signature does not match. I am not sure you need template in this case, you can use std::function directly, but that depends on your code.

Upvotes: 2

Simple
Simple

Reputation: 14420

You can achieve something close with:

template<class ArgumentT, class ReturnT, class F, F f>
struct A;

template<class ArgumentT, class ReturnT, ReturnT (*f)()>
struct A<ArgumentT, ReturnT, ReturnT (*)(), f>
{
   // f is used somewhere.
};

template<class ArgumentT, class ReturnT, class C, ReturnT (C::*f)()>
struct A<ArgumentT, ReturnT, ReturnT (C::*)(), f>
{
   // f is used somewhere.
};

...but you can't take something like a std::function<ReturnT ()> as a non-type template parameter. The specialisation for function pointers will also accept non-capturing lambdas.

Upvotes: 0

Jerry Coffin
Jerry Coffin

Reputation: 490693

A normal template argument can refer to a function.

#include <iostream>

template <class ArgT, class RetT, class F>
struct A {
    F f;
public:
    A(F f) : f(f) {}

    RetT operator()(ArgT arg) { return f(arg); }
};

int unchanged(int i) { return i; }

int main(){
    A < int, int, int(*)(int)> t{ unchanged };

    for (int i = 0; i < 10; i++)
        std::cout << t(i) << "\n";
}

There's nothing restricting the template argument to a function though -- you could just as easily use some class that overloads operator(), and invoke that instead (and, in fact, that's often preferable).

Upvotes: 9

Paul Evans
Paul Evans

Reputation: 27577

You're combining types and data, you want something more like:

template<class ArgumentT, class ReturnT, typename F*>
struct A {
    //use F* to refer to f somewhere
};

Upvotes: 0

Related Questions