DEV Community

loading...
Cover image for C++ Pointer to Function

C++ Pointer to Function

aakatev profile image Artem ・1 min read

Hey guys! I haven't written anything in a while, and this post will be very brief too. That said, I think you can greatly benefit from it, especially if you regularly have to deal with C/C++ (and even more likely if you learned C++ in school together with OOP).

Anyhow, I will show you a paraphrased snipped from Google's crypto library BoringSSL. It is a great example of using a pointer to function.

Here it is!

#include <iostream>
#include <string>

typedef void (*tool_func_t)();

struct Tool {
  const char *name;
  tool_func_t func;
};

void info_func() { std::cout << "You selected info" << std::endl; }

void help_func() { std::cout << "You selected help" << std::endl; }

const Tool kTools[] = {
    {"info", info_func},
    {"help", help_func},
};

tool_func_t find_tool(const std::string &name) {
  for (size_t i = 0;; i++) {
    const Tool &tool = kTools[i];
    if (tool.func == nullptr || name == tool.name) {
      return tool.func;
    }
  }
}

int main(int argc, char **argv) {
  if (argc == 1) {
    std::cout << "You didn't povide any arguments" << std::endl;
    return 1;
  }
  tool_func_t tool = nullptr;
  tool = find_tool(argv[1]);
  if (tool == nullptr) {
    std::cout << "You can either get info, or ask for help!" << std::endl;
    return 2;
  }
  tool();
  return 0;
}
Enter fullscreen mode Exit fullscreen mode

The key step is typedef declaration which defines the function's signature (in this example takes no arguments and returns void). After that, you have great flexibility in working with functions having this signature.

Of course, you can read more about it on www.learncpp.com.

Discussion (5)

pic
Editor guide
Collapse
pgradot profile image
Pierre Gradot • Edited

Since C++11, using is generally more readable than typedef:

using Pointer = void (*)();
Enter fullscreen mode Exit fullscreen mode

More generally, with C++11 and above, we now tend to use std::function instead of function pointers as they are able to hold more different types of functions, such as capturing lambdas. Example:

#include <iostream>
#include <functional>

void f() {
    std::cout << "f" << '\n';
}

using Pointer = void (*)();
using Function = std::function<void(void)>;

int main() {

    Pointer pf = f;
    pf();
    Function ff = f;
    ff();

    int a = 42;
    auto lambda = [a]() {
        std::cout << "Lambda a=" << a << '\n';
    };

    Function fl = lambda;
    fl();

//  Pointer pl = lambda; // error: cannot convert 'main()::<lambda()>' to 'Pointer' {aka 'void (*)()'} in initialization
}
Enter fullscreen mode Exit fullscreen mode

Function pointers are still necessary to interface C++ and C codes.

Collapse
aakatev profile image
Artem Author

Learned a lot from this comment. Thanks!!

Collapse
pgradot profile image
Pierre Gradot

Glad it helped : )

There is another use-case for std::function: it can be used to hold a "function object" (also called a "functor":

#include <iostream>
#include <functional>

using Function = std::function<void(void)>;

struct Callable {
    void operator()() {
        std::cout << "callable::operator()()" << '\n';
    }
};

int main() {
    Callable callable;
    Function f = callable;
    f();
}
Enter fullscreen mode Exit fullscreen mode
Collapse
epsi profile image
Collapse
jpaulin profile image
Jukka Paulin

One of those nice features to have in a language.