Search code examples
c++auto

How to pass an Auto variable as input to another function


I really want to pass a variable that is auto (function) as input in another function.

Here is a structure that receives parameters for my xroot f:

struct my_f_params { 
    double flag; 
    auto inter_auto(double x, double y);
};

Here is the function I essentially want to have (it's based on a GSL library, so the form can't be changed). I want to be able to pass a "function" as a variable, and the only way I guessed it would happen is with auto.

After passing it, I try storing it to a new auto, But I get an error (see below):

double xrootf (double x, void * p)
{
    my_f_params * params = (my_f_params *)p;
    double flag = (params->flag);
    auto inter_auto = (params->inter_auto);    
    return flag*inter_auto(x);
}

Here is an auto function that returns an auto function. This works perfectly (if xrootf is commented, I can print for example new_f(2)(2), etc):

auto new_f(double x){
    auto in_result = [](double x, double y){
        return x*y;
    };

    using namespace std::placeholders;
    auto result_f = std::bind(in_result,x,_1);
    
    return result_f;
}

The test code that proves that the auto function new_f is working good:

int main(int argc, char const *argv[])
{
    auto nest_f = new_f(-0.5);
    printf("%f\n", nest_f(+2));
    return 0;
} 

Recasting the auto function to double is not working, either (for the struct part of the code).

The error I'm getting is:

auto_pass.cpp: In function 'double xrootf(double, void*)':
auto_pass.cpp:28:42: error: unable to deduce 'auto' from 'params->my_f_params::inter_auto'
28 |     auto inter_auto = (params->inter_auto);
   |                                          ^
auto_pass.cpp:28:42: note:   couldn't deduce template parameter 'auto'

The aim of the code is this:

  1. Have a function that is able to return a function (DONE W/ new_f)

  2. Have a function that is able to take a function as a variable (the one with new_f) (Not Done)

EDIT: Here's a quick Python script that's very easy to achieve what I'm saying:

def new_f(y):
    #make any number of computatioanly costly Algebra with y
    def g(x):
        return x*y
    return g
def xroot(f,flag):
    return flag-f(flag)

Solution

  • auto is just a placeholder for a compiler-deduced type, depending on the context in which auto is used.

    In your example, you can't use auto as the return value of my_f_params::inter_auto(), because the compiler has no way to know what type inter_auto() actually returns, so it can't deduce the type of the auto. You would need to do this instead:

    struct my_f_params { 
        double flag; 
        auto inter_auto(double x, double y) { return ...; }
    };
    

    Then the compiler can deduce the type of the auto from the return statement.

    Without that inline code, you would have to be explicit about the return type, eg:

    struct my_f_params { 
        double flag; 
        double inter_auto(double x, double y);
    };
    
    double my_f_params::inter_auto(double x, double y) {
        return ...;
    }
    

    But in any case, this is not what you really want. Your xrootf() function is trying to call inter_auto() with only one parameter, but my_f_params::inter_auto() is declared to take 2 parameters instead. Based on the Python script you showed, what you really want is for inter_auto to be a reference to some other external function instead. In which case, you can use std::function for that purpose (and there is no need to use std::bind() with a lambda at all).

    Try this:

    #include <iostream>
    #include <functional>
    
    struct my_f_params { 
        double flag; 
        std::function<double(double)> inter_auto;
    };
    
    double xrootf(double x, void * p)
    {
        my_f_params * params = static_cast<my_f_params*>(p);
        return params->flag * params->inter_auto(x);
    }
    
    auto new_f(double x){
        return [x](double y) {
            return x * y;
        };
    }
    
    int main(int argc, char const *argv[])
    {
        my_f_params p;
        p.flag = 123.45;
        p.inter_auto = new_f(-0.5);
        std::cout << xrootf(+2, &p) << std::endl;
        return 0;
    } 
    

    Demo

    When calling xrootf(), the resulting equation will be:

    flag * (x * y)

    which in this example is:

    123.45 * (-0.5 * +2) = -123.45