-1

I need to create a function which will return a pointer to another function as a result so that I could write something like f(n)(v) in main().

For example "make function of vector v that, when called returns a function on integer n where that function returned calculates p(n) where p is polynomial with coefficients from vector v", I think I could understand everything through sample code for this example.

Where should the body of that other function be?

Richard Chambers
  • 14,509
  • 3
  • 62
  • 86
NotEuler
  • 1
  • 1
  • 1
    You might want to learn about [`std::function`](https://en.cppreference.com/w/cpp/utility/functional/function). – Some programmer dude Sep 16 '19 at 17:00
  • Hello and welcome to StackOverflow. Please take some time to read the help page, especially the sections named ["What topics can I ask about here?"](http://stackoverflow.com/help/on-topic) and ["What types of questions should I avoid asking?"](http://stackoverflow.com/help/dont-ask). And more importantly, please read [the Stack Overflow question checklist](http://meta.stackexchange.com/q/156810/204922). You might also want to learn about [Minimal, Complete, and Verifiable Examples](http://stackoverflow.com/help/mcve) – dtell Sep 16 '19 at 17:02
  • 1
    First place, that one, typically, looks, if one has questions about the language, is the [documentation](https://en.cppreference.com/w/cpp/language/pointer#Pointers_to_functions). – Algirdas Preidžius Sep 16 '19 at 17:02
  • yes i tried but everything is poorly explained – NotEuler Sep 16 '19 at 17:04
  • and this stuff you sent me only talks about pointers to functions but not about problem I gave you in this example – NotEuler Sep 16 '19 at 17:07
  • Note that traditionally functions in c/c++ are hard typed. You can write a function p(v) that can take a particular type of vector v, and return either another function or a class that can act as a function that takes an integer n, but if you want it to work for a generic class of vectors, or other container types, or execute with values other than integer n, it all becomes very much NOT "beginner in this programming stuff" – Gem Taylor Sep 16 '19 at 17:48

2 Answers2

1

You should make yourself familiar with lambdas.

This is the implementation you asked for (try on godbolt):

#include <vector>
#include <cmath>
#include <iostream>

auto polynomial(const std::vector<float> &coeffs) {
    return [=](float x){
        float result = 0.f;
        float exponent = 0.f;
        for(const auto& c : coeffs) {
            result += std::pow(x, exponent) * c;
            exponent += 1.f;
        }
        return result;
    };
}

int main() {
    auto p = polynomial({1.f, 2.f, 3.f});
    std::cout << p(5.f) << '\n'; // returns 86
}

Basic description of what is happening here:

The lambda expression captures everything (=) by copy, so it creates a local copy of the coeffs vector. Since the type of a lambda expression is not known, you have to use auto return type deduction (or maybe some decltype construct).

eike
  • 969
  • 5
  • 17
  • 1
    my rule of thumb is to use `std::function` only when I do need the flexibility it offers, ie: store any kind of callable, though when I need only one specific kind of callable then I dont want to pay for what I dont use. Just dont forget that `std::function` comes with a bit of overhead – 463035818_is_not_a_number Sep 16 '19 at 17:19
  • @formerlyknownas_463035818 I agree. Edited the answer. – eike Sep 16 '19 at 17:22
  • 1
    @formerlyknownas_463035818: when you need a specific kind of callable what are you going to do? polluting global namespace with free functions to allow them to return them through pointers? I don't agree with you, I use `std::function`, then change it to something more efficient if I see it's necessary. Yours looks like premature optimization. – Jack Sep 16 '19 at 17:25
  • can I do this with something simpler like : double (*f(vector v))(double d); – NotEuler Sep 16 '19 at 17:28
  • @Jack In this case, I think just returning the lambda is just as good as returning a `std::function` and you loose the overhead. I would suggest using `std::function`, when you need to know the return type (i.e. for passing it to another function). – eike Sep 16 '19 at 17:29
  • 1
    @eike: it's not clear if he's against using anonymous functions in general or just specifying `std::function` coercion on return type, that's the reason of my question. – Jack Sep 16 '19 at 17:31
  • @NotEuler I don't see how that would be simpler, but yes, you probably could. You could even implement `calcPolynomial(coeffs, x)` and bind the coefficients using `std::bind` or `std::bind_front` (starting with C++2a / C++20) – eike Sep 16 '19 at 17:33
  • This is mentioned in the book I'm using, but only this line that is whats confusing me, where does body of each function go – NotEuler Sep 16 '19 at 17:50
  • @Jack I dont understand what you refer to when you say mine looks like premature optimization. OP never asked for polluting global namespace neither did I suggest something in this direction. – 463035818_is_not_a_number Sep 16 '19 at 17:52
  • The lambda expression `[...] (...) {...}` creates a function. Use the link I provided in the question or this one https://stackoverflow.com/q/7627098/4253931 for more information on lambdas. – eike Sep 16 '19 at 17:53
  • 1
    @Jack for polynomials I'd probably write a functor class that encapsulates the coefficients and has an `operator()`. – 463035818_is_not_a_number Sep 16 '19 at 17:54
  • 1
    sorry for extended discussion in comments. I wrote an answer, hope it is more clear what my comments were about – 463035818_is_not_a_number Sep 17 '19 at 07:42
1

I need to create a function which will return a pointer to another function as a result so that I could write something like f(n)(v) in main().

Think more general! Let me reformulate this just a bit: You need to create a function that returns something so that you can write f(n)(v) in main().

This something must not necessarily be a function (or function pointer). If we stick to this syntax f(n)(v), then it definitely has to be a callable. Note that "callable" can be many things. All that we need for some object F to be callable is that F(v) is valid for certain types of v.

A rather traditional type of callables are functors. A functor is an object of a class that has an operator(). I don't wont to give away the full free lunch, so for the sake of the example I will restrict myself to linear functions (extension to polynomials should be straight-forward).

We start by defining the functor class:

struct linear_fun {
    double a;
    double b;
    double operator()(double x) { return a + b*x; }
};

Once we have this, passing around a function object is as simple as it can get:

// returns a linear_fun that crosses the origin and the given point
linear_fun fun_crossing_point(double x,double y) {
    return { 0.0 , y / x };
}

Lastly we want to test it

int main() {
    std::cout << fun_crossing_point( 1.1 , 5.0 )(1.1);    
}

Prints:

5

Note that there are also lambdas which are basically syntactic sugar for functor classes. They come in handy when you want to define the functor only in a narrow scope. The downside is that every lambda is of different type, so when you want one specific type then it is worth to consider writing the functor class yourself.

Also C++ has std::function, which is the catch-it-all solution for callables. It comes with great flexibility, because a single std::function object can be assigned almost any kind of callable. However, this flexibility comes at some cost and usually one does not need it. I presume you just need to define one type that defines your polynomial and you do not need to mix eg free functions, member functions and others.

463035818_is_not_a_number
  • 64,173
  • 8
  • 58
  • 126