Dimitar
Dimitar

Reputation: 182

Modern C++ way of doing function return pointer to a function

I am new to C++ and I started to reading a book on the topic. There is an exercise that says: "Declare a pointer to a function taking an int as argument and returning a pointer to a function that takes a char as argument and returns float". I ended up with this code:

#include <iostream>
using namespace std;

float func(char c) {
    return 3.14;
}

float((*fun2(int))(char)) {
    return &func;
}

int main() {
    float(*fp)(char) = fun2(3);
    cout << fp('c') << endl;
}

The question is: is it still appropriate in today's C++ programming. If so - are there any needed changes to be made to the code(applying new abstractions etc.)? Thanks.

Upvotes: 2

Views: 3379

Answers (4)

Jarod42
Jarod42

Reputation: 218323

As alternative, there is the trailing return type (since C++11):

auto fun2(int) -> float(*)(char)
{
    return &func;
}

Upvotes: 2

Loreto
Loreto

Reputation: 694

My literal version:

#include <iostream>

using my_pf = float(*)(char);
using my_ppf = my_pf(*)(int);

float func(char)
{
    return 3.14f;
}

my_pf fun2(int)
{
    return &func;
}


int main()
{

    my_ppf ppf; // Your declaration: 
                // Pointer to a function taking an int as argument
                // and returning a pointer to a function
                // that takes a char as argument and returns float.

    ppf = &fun2; 

    my_pf pf = ppf(3);

    std::cout << pf('c') << '\n';

}

Upvotes: 1

Silvio Mayolo
Silvio Mayolo

Reputation: 70397

Since the problem states to return a "function pointer", you are sort of stuck with slightly old syntax. However, if you aren't constrained by that and just want to return a function (and C interoperability isn't an issue), you can use std::function, which is a more modern, more general function type.

#include <functional>

// ...

std::function<float(char)> fun2(int) {
  return &func;
}

The advantage to std::function (aside from looking prettier than the awkward float(*)(char) syntax) is that it can store function pointers, anonymous functions, and callable objects, whereas a traditional function pointer can only store pointers to global functions. So, for example, the following would be allowed.

struct Foo {
  float operator()(char) {
    // ...
  }
};

std::function<float(char)> fun3(int) {
  return Foo();
}

std::function<float(char)> fun4(int) {
  return [](char) { return 1.0; };
}

Neither of fun3 nor fun4 would compile with a simple function pointer.

Upvotes: 2

user7860670
user7860670

Reputation: 37599

You can declare a type alias:

using my_fp = float ( * )(char); // can work before C++11 with typedef

my_fp fun2(int){
  return &func;
}

my_fp fp = fun2(0);

and / or completely automatic type deduction:

auto fun2(int) { // available in C++14
  return &func;
}

// Use a suitable value in the call to fun2
auto fp{fun2(0)}; // available in C++11

Upvotes: 5

Related Questions