C++ function pointer as Template parameter

1.1k Views Asked by At

I have questions with below code snippet, not sure if I correctly understand the codes.

template <typename R, typename... Args>                                     
class RunnableAdapter<R(*)(Args...)> {
 public:
  typedef R (RunType)(Args...);

  explicit RunnableAdapter(R(*function)(Args...))   
      : function_(function) {
  }

  R Run(Arg... args) {
    return function_(args...);
  }

 private:
  R (*function_)(Args...);
};
  1. <R(*)(Args...)> is a "type of function pointer"and blink space between R and (*) is not necessarily required?

  2. and what could instanciation of RunnableAdapter be? I assume it is like below.
    void myFunction(int i){ // }; RunnableAdfapter<(void)(*)(int)> ra(MyFunction); ra.Run(1); //which calls MyFunction(1)

1

There are 1 best solutions below

5
On

At first the code you provided have some mistakes and does not even compile. To answer tou questions:

  1. Spaces are not necessary.
  2. See below example

You could declare you class like this

template <typename T>
class RunnableAdapter;

template <typename R, typename... Args>                                     
class RunnableAdapter<R(*)(Args...)> { ... }

And instantiate it

RunnableAdapter<void(*)(int)> ra(&myFunction);

But you could simplify it (here is full working example)

#include <iostream>
#include <string>

template <typename T>
class RunnableAdapter;

template <typename R, typename... Args>                                     
class RunnableAdapter<R (Args...)> {
public:

  explicit RunnableAdapter(R(*function)(Args...))   
      : function_(function) {
  }

  R Run(Args... args) {
    return function_(args...);
  }

private:
  R (*function_)(Args...);
};

void myFunction(int i){ std::cout << i << std::endl; }

int main()
{
    RunnableAdapter<void(int)> ra(&myFunction);
    ra.Run(1);
}

This would allow instantiation with signature-like expressions like void(int). It just looks better, no need in (*).

Also here is another way is to do it without class specialization, like this. The result is the same, but class declaration and instantiation is slightly different.

#include <iostream>
#include <string>

template <typename R, typename... Args>                                     
class RunnableAdapter {
public:

  explicit RunnableAdapter(R(*function)(Args...))   
      : function_(function) {
  }

  R Run(Args... args) {
    return function_(args...);
  }

private:
  R (*function_)(Args...);
};

void myFunction(int i){ std::cout << i << std::endl; }

int main()
{
    RunnableAdapter<void, int> ra(&myFunction);
    ra.Run(1);
}

EDIT

As @Jarod42 proposed it is better to make Run like this

template<typename... Ts>
R Run(Ts&&... args) {
  return function_(std::forward<Ts...>(args)...);
}